mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
wg_engine: pipelines and bind groups refactoring
- shader and system types synchronized - pipelens and bind groups description separated - pipelines description simplified
This commit is contained in:
parent
f173b45e04
commit
9742cfe293
29 changed files with 1748 additions and 2539 deletions
|
@ -1,14 +1,20 @@
|
||||||
source_file = [
|
source_file = [
|
||||||
|
'tvgWgBindGroups.h',
|
||||||
|
'tvgWgCommon.h',
|
||||||
|
'tvgWgGeometry.h',
|
||||||
|
'tvgWgPipelines.h',
|
||||||
|
'tvgWgRenderData.h',
|
||||||
|
'tvgWgRenderer.h',
|
||||||
|
'tvgWgShaderSrc.h',
|
||||||
|
'tvgWgShaderTypes.h'
|
||||||
|
'tvgWgBindGroups.cpp',
|
||||||
|
'tvgWgCommon.cpp',
|
||||||
'tvgWgGeometry.cpp',
|
'tvgWgGeometry.cpp',
|
||||||
'tvgWgPipelineBase.cpp',
|
'tvgWgPipelines.cpp',
|
||||||
'tvgWgPipelineEmpty.cpp',
|
|
||||||
'tvgWgPipelineLinear.cpp',
|
|
||||||
'tvgWgPipelineSolid.cpp',
|
|
||||||
'tvgWgPipelineRadial.cpp',
|
|
||||||
'tvgWgPipelineStroke.cpp',
|
|
||||||
'tvgWgRenderData.cpp',
|
'tvgWgRenderData.cpp',
|
||||||
'tvgWgRenderer.cpp',
|
'tvgWgRenderer.cpp',
|
||||||
'tvgWgShaderSrc.cpp'
|
'tvgWgShaderSrc.cpp',
|
||||||
|
'tvgWgShaderTypes.cpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
engine_dep += [declare_dependency(
|
engine_dep += [declare_dependency(
|
||||||
|
|
239
src/renderer/wg_engine/tvgWgBindGroups.cpp
Normal file
239
src/renderer/wg_engine/tvgWgBindGroups.cpp
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tvgWgBindGroups.h"
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroupCanvas::layout = nullptr;
|
||||||
|
WGPUBindGroupLayout WgBindGroupCanvas::getLayout(WGPUDevice device) {
|
||||||
|
if (layout) return layout;
|
||||||
|
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
||||||
|
makeBindGroupLayoutEntryBuffer(0)
|
||||||
|
};
|
||||||
|
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1);
|
||||||
|
assert(layout);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupCanvas::releaseLayout() {
|
||||||
|
releaseBindGroupLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgBindGroupCanvas::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeMat4x4f& uViewMat) {
|
||||||
|
release();
|
||||||
|
uBufferViewMat = createBuffer(device, queue, &uViewMat, sizeof(uViewMat));
|
||||||
|
const WGPUBindGroupEntry bindGroupEntries[] {
|
||||||
|
makeBindGroupEntryBuffer(0, uBufferViewMat)
|
||||||
|
};
|
||||||
|
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1);
|
||||||
|
assert(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupCanvas::release() {
|
||||||
|
releaseBindGroup(mBindGroup);
|
||||||
|
releaseBuffer(uBufferViewMat);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroupPaint::layout = nullptr;
|
||||||
|
WGPUBindGroupLayout WgBindGroupPaint::getLayout(WGPUDevice device) {
|
||||||
|
if (layout) return layout;
|
||||||
|
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
||||||
|
makeBindGroupLayoutEntryBuffer(0),
|
||||||
|
makeBindGroupLayoutEntryBuffer(1)
|
||||||
|
};
|
||||||
|
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 2);
|
||||||
|
assert(layout);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupPaint::releaseLayout() {
|
||||||
|
releaseBindGroupLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgBindGroupPaint::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeMat4x4f& uModelMat, WgShaderTypeBlendSettings& uBlendSettings) {
|
||||||
|
release();
|
||||||
|
uBufferModelMat = createBuffer(device, queue, &uModelMat, sizeof(uModelMat));
|
||||||
|
uBufferBlendSettings = createBuffer(device, queue, &uBlendSettings, sizeof(uBlendSettings));
|
||||||
|
const WGPUBindGroupEntry bindGroupEntries[] {
|
||||||
|
makeBindGroupEntryBuffer(0, uBufferModelMat),
|
||||||
|
makeBindGroupEntryBuffer(1, uBufferBlendSettings)
|
||||||
|
};
|
||||||
|
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 2);
|
||||||
|
assert(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupPaint::release() {
|
||||||
|
releaseBindGroup(mBindGroup);
|
||||||
|
releaseBuffer(uBufferBlendSettings);
|
||||||
|
releaseBuffer(uBufferModelMat);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroupSolidColor::layout = nullptr;
|
||||||
|
WGPUBindGroupLayout WgBindGroupSolidColor::getLayout(WGPUDevice device) {
|
||||||
|
if (layout) return layout;
|
||||||
|
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
||||||
|
makeBindGroupLayoutEntryBuffer(0)
|
||||||
|
};
|
||||||
|
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1);
|
||||||
|
assert(layout);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupSolidColor::releaseLayout() {
|
||||||
|
releaseBindGroupLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgBindGroupSolidColor::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeSolidColor &uSolidColor) {
|
||||||
|
release();
|
||||||
|
uBufferSolidColor = createBuffer(device, queue, &uSolidColor, sizeof(uSolidColor));
|
||||||
|
const WGPUBindGroupEntry bindGroupEntries[] {
|
||||||
|
makeBindGroupEntryBuffer(0, uBufferSolidColor)
|
||||||
|
};
|
||||||
|
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1);
|
||||||
|
assert(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupSolidColor::release() {
|
||||||
|
releaseBindGroup(mBindGroup);
|
||||||
|
releaseBuffer(uBufferSolidColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroupLinearGradient::layout = nullptr;
|
||||||
|
WGPUBindGroupLayout WgBindGroupLinearGradient::getLayout(WGPUDevice device) {
|
||||||
|
if (layout) return layout;
|
||||||
|
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
||||||
|
makeBindGroupLayoutEntryBuffer(0)
|
||||||
|
};
|
||||||
|
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1);
|
||||||
|
assert(layout);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupLinearGradient::releaseLayout() {
|
||||||
|
releaseBindGroupLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgBindGroupLinearGradient::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeLinearGradient &uLinearGradient) {
|
||||||
|
release();
|
||||||
|
uBufferLinearGradient = createBuffer(device, queue, &uLinearGradient, sizeof(uLinearGradient));
|
||||||
|
const WGPUBindGroupEntry bindGroupEntries[] {
|
||||||
|
makeBindGroupEntryBuffer(0, uBufferLinearGradient)
|
||||||
|
};
|
||||||
|
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1);
|
||||||
|
assert(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupLinearGradient::release() {
|
||||||
|
releaseBindGroup(mBindGroup);
|
||||||
|
releaseBuffer(uBufferLinearGradient);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroupRadialGradient::layout = nullptr;
|
||||||
|
WGPUBindGroupLayout WgBindGroupRadialGradient::getLayout(WGPUDevice device) {
|
||||||
|
if (layout) return layout;
|
||||||
|
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
||||||
|
makeBindGroupLayoutEntryBuffer(0)
|
||||||
|
};
|
||||||
|
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1);
|
||||||
|
assert(layout);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupRadialGradient::releaseLayout() {
|
||||||
|
releaseBindGroupLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgBindGroupRadialGradient::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeRadialGradient &uRadialGradient) {
|
||||||
|
release();
|
||||||
|
uBufferRadialGradient = createBuffer(device, queue, &uRadialGradient, sizeof(uRadialGradient));
|
||||||
|
const WGPUBindGroupEntry bindGroupEntries[] {
|
||||||
|
makeBindGroupEntryBuffer(0, uBufferRadialGradient)
|
||||||
|
};
|
||||||
|
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1);
|
||||||
|
assert(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupRadialGradient::release() {
|
||||||
|
releaseBuffer(uBufferRadialGradient);
|
||||||
|
releaseBindGroup(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroupPicture::layout = nullptr;
|
||||||
|
WGPUBindGroupLayout WgBindGroupPicture::getLayout(WGPUDevice device) {
|
||||||
|
if (layout) return layout;
|
||||||
|
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
||||||
|
makeBindGroupLayoutEntrySampler(0),
|
||||||
|
makeBindGroupLayoutEntryTextureView(1)
|
||||||
|
};
|
||||||
|
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 2);
|
||||||
|
assert(layout);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupPicture::releaseLayout() {
|
||||||
|
releaseBindGroupLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgBindGroupPicture::initialize(WGPUDevice device, WGPUQueue queue, WGPUSampler uSampler, WGPUTextureView uTextureView) {
|
||||||
|
release();
|
||||||
|
const WGPUBindGroupEntry bindGroupEntries[] {
|
||||||
|
makeBindGroupEntrySampler(0, uSampler),
|
||||||
|
makeBindGroupEntryTextureView(1, uTextureView)
|
||||||
|
};
|
||||||
|
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 2);
|
||||||
|
assert(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupPicture::release() {
|
||||||
|
releaseBindGroup(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroupCompose::layout = nullptr;
|
||||||
|
WGPUBindGroupLayout WgBindGroupCompose::getLayout(WGPUDevice device) {
|
||||||
|
if (layout) return layout;
|
||||||
|
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
||||||
|
makeBindGroupLayoutEntrySampler(0),
|
||||||
|
makeBindGroupLayoutEntryTextureView(1),
|
||||||
|
makeBindGroupLayoutEntryTextureView(2)
|
||||||
|
};
|
||||||
|
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 3);
|
||||||
|
assert(layout);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupCompose::releaseLayout() {
|
||||||
|
releaseBindGroupLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgBindGroupCompose::initialize(WGPUDevice device, WGPUQueue queue, WGPUSampler uSampler, WGPUTextureView uTextureSrc, WGPUTextureView uTextureDst) {
|
||||||
|
release();
|
||||||
|
const WGPUBindGroupEntry bindGroupEntries[] {
|
||||||
|
makeBindGroupEntrySampler(0, uSampler),
|
||||||
|
makeBindGroupEntryTextureView(1, uTextureSrc),
|
||||||
|
makeBindGroupEntryTextureView(2, uTextureDst)
|
||||||
|
};
|
||||||
|
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 3);
|
||||||
|
assert(mBindGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroupCompose::release() {
|
||||||
|
releaseBindGroup(mBindGroup);
|
||||||
|
}
|
116
src/renderer/wg_engine/tvgWgBindGroups.h
Normal file
116
src/renderer/wg_engine/tvgWgBindGroups.h
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TVG_WG_BIND_GROUPS_H_
|
||||||
|
#define _TVG_WG_BIND_GROUPS_H_
|
||||||
|
|
||||||
|
#include "tvgWgCommon.h"
|
||||||
|
#include "tvgWgShaderTypes.h"
|
||||||
|
|
||||||
|
// @group(0)
|
||||||
|
struct WgBindGroupCanvas: public WgBindGroup {
|
||||||
|
static WGPUBindGroupLayout layout;
|
||||||
|
static WGPUBindGroupLayout getLayout(WGPUDevice device);
|
||||||
|
static void releaseLayout();
|
||||||
|
|
||||||
|
WGPUBuffer uBufferViewMat{};
|
||||||
|
void initialize(WGPUDevice device, WGPUQueue queue,
|
||||||
|
WgShaderTypeMat4x4f& uViewMat);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
// @group(1)
|
||||||
|
struct WgBindGroupPaint: public WgBindGroup {
|
||||||
|
static WGPUBindGroupLayout layout;
|
||||||
|
static WGPUBindGroupLayout getLayout(WGPUDevice device);
|
||||||
|
static void releaseLayout();
|
||||||
|
|
||||||
|
WGPUBuffer uBufferModelMat{};
|
||||||
|
WGPUBuffer uBufferBlendSettings{};
|
||||||
|
void initialize(WGPUDevice device, WGPUQueue queue,
|
||||||
|
WgShaderTypeMat4x4f& uModelMat,
|
||||||
|
WgShaderTypeBlendSettings& uBlendSettings);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
// @group(2)
|
||||||
|
struct WgBindGroupSolidColor: public WgBindGroup {
|
||||||
|
static WGPUBindGroupLayout layout;
|
||||||
|
static WGPUBindGroupLayout getLayout(WGPUDevice device);
|
||||||
|
static void releaseLayout();
|
||||||
|
|
||||||
|
WGPUBuffer uBufferSolidColor;
|
||||||
|
void initialize(WGPUDevice device, WGPUQueue queue,
|
||||||
|
WgShaderTypeSolidColor &uSolidColor);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
// @group(2)
|
||||||
|
struct WgBindGroupLinearGradient: public WgBindGroup {
|
||||||
|
static WGPUBindGroupLayout layout;
|
||||||
|
static WGPUBindGroupLayout getLayout(WGPUDevice device);
|
||||||
|
static void releaseLayout();
|
||||||
|
|
||||||
|
WGPUBuffer uBufferLinearGradient;
|
||||||
|
void initialize(WGPUDevice device, WGPUQueue queue,
|
||||||
|
WgShaderTypeLinearGradient &uLinearGradient);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
// @group(2)
|
||||||
|
struct WgBindGroupRadialGradient: public WgBindGroup {
|
||||||
|
static WGPUBindGroupLayout layout;
|
||||||
|
static WGPUBindGroupLayout getLayout(WGPUDevice device);
|
||||||
|
static void releaseLayout();
|
||||||
|
|
||||||
|
WGPUBuffer uBufferRadialGradient;
|
||||||
|
void initialize(WGPUDevice device, WGPUQueue queue,
|
||||||
|
WgShaderTypeRadialGradient &uRadialGradient);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
// @group(2)
|
||||||
|
struct WgBindGroupPicture: public WgBindGroup {
|
||||||
|
static WGPUBindGroupLayout layout;
|
||||||
|
static WGPUBindGroupLayout getLayout(WGPUDevice device);
|
||||||
|
static void releaseLayout();
|
||||||
|
|
||||||
|
void initialize(WGPUDevice device, WGPUQueue queue,
|
||||||
|
WGPUSampler uSampler,
|
||||||
|
WGPUTextureView uTextureView);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
// @group(2)
|
||||||
|
struct WgBindGroupCompose: public WgBindGroup {
|
||||||
|
static WGPUBindGroupLayout layout;
|
||||||
|
static WGPUBindGroupLayout getLayout(WGPUDevice device);
|
||||||
|
static void releaseLayout();
|
||||||
|
|
||||||
|
void initialize(WGPUDevice device, WGPUQueue queue,
|
||||||
|
WGPUSampler uSampler,
|
||||||
|
WGPUTextureView uTextureSrc,
|
||||||
|
WGPUTextureView uTextureDst);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _TVG_WG_BIND_GROUPS_H_
|
343
src/renderer/wg_engine/tvgWgCommon.cpp
Normal file
343
src/renderer/wg_engine/tvgWgCommon.cpp
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tvgWgCommon.h"
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
// bind group
|
||||||
|
//*****************************************************************************
|
||||||
|
|
||||||
|
void WgBindGroup::set(WGPURenderPassEncoder encoder, uint32_t groupIndex) {
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(encoder, groupIndex, mBindGroup, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupEntry WgBindGroup::makeBindGroupEntryBuffer(uint32_t binding, WGPUBuffer buffer) {
|
||||||
|
WGPUBindGroupEntry bindGroupEntry{};
|
||||||
|
bindGroupEntry.nextInChain = nullptr;
|
||||||
|
bindGroupEntry.binding = binding;
|
||||||
|
bindGroupEntry.buffer = buffer;
|
||||||
|
bindGroupEntry.offset = 0;
|
||||||
|
bindGroupEntry.size = wgpuBufferGetSize(buffer);
|
||||||
|
bindGroupEntry.sampler = nullptr;
|
||||||
|
bindGroupEntry.textureView = nullptr;
|
||||||
|
return bindGroupEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupEntry WgBindGroup::makeBindGroupEntrySampler(uint32_t binding, WGPUSampler sampler) {
|
||||||
|
WGPUBindGroupEntry bindGroupEntry{};
|
||||||
|
bindGroupEntry.nextInChain = nullptr;
|
||||||
|
bindGroupEntry.binding = binding;
|
||||||
|
bindGroupEntry.buffer = nullptr;
|
||||||
|
bindGroupEntry.offset = 0;
|
||||||
|
bindGroupEntry.size = 0;
|
||||||
|
bindGroupEntry.sampler = sampler;
|
||||||
|
bindGroupEntry.textureView = nullptr;
|
||||||
|
return bindGroupEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupEntry WgBindGroup::makeBindGroupEntryTextureView(uint32_t binding, WGPUTextureView textureView) {
|
||||||
|
WGPUBindGroupEntry bindGroupEntry{};
|
||||||
|
bindGroupEntry.nextInChain = nullptr;
|
||||||
|
bindGroupEntry.binding = binding;
|
||||||
|
bindGroupEntry.buffer = nullptr;
|
||||||
|
bindGroupEntry.offset = 0;
|
||||||
|
bindGroupEntry.size = 0;
|
||||||
|
bindGroupEntry.sampler = nullptr;
|
||||||
|
bindGroupEntry.textureView = textureView;
|
||||||
|
return bindGroupEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryBuffer(uint32_t binding) {
|
||||||
|
WGPUBindGroupLayoutEntry bindGroupLayoutEntry{};
|
||||||
|
bindGroupLayoutEntry.nextInChain = nullptr;
|
||||||
|
bindGroupLayoutEntry.binding = binding;
|
||||||
|
bindGroupLayoutEntry.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
||||||
|
bindGroupLayoutEntry.buffer.nextInChain = nullptr;
|
||||||
|
bindGroupLayoutEntry.buffer.type = WGPUBufferBindingType_Uniform;
|
||||||
|
bindGroupLayoutEntry.buffer.hasDynamicOffset = false;
|
||||||
|
bindGroupLayoutEntry.buffer.minBindingSize = 0;
|
||||||
|
return bindGroupLayoutEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntrySampler(uint32_t binding) {
|
||||||
|
WGPUBindGroupLayoutEntry bindGroupLayoutEntry{};
|
||||||
|
bindGroupLayoutEntry.nextInChain = nullptr;
|
||||||
|
bindGroupLayoutEntry.binding = binding;
|
||||||
|
bindGroupLayoutEntry.visibility = WGPUShaderStage_Fragment;
|
||||||
|
bindGroupLayoutEntry.sampler.nextInChain = nullptr;
|
||||||
|
bindGroupLayoutEntry.sampler.type = WGPUSamplerBindingType_Filtering;
|
||||||
|
return bindGroupLayoutEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryTextureView(uint32_t binding) {
|
||||||
|
WGPUBindGroupLayoutEntry bindGroupLayoutEntry{};
|
||||||
|
bindGroupLayoutEntry.nextInChain = nullptr;
|
||||||
|
bindGroupLayoutEntry.binding = binding;
|
||||||
|
bindGroupLayoutEntry.visibility = WGPUShaderStage_Fragment;
|
||||||
|
bindGroupLayoutEntry.texture.nextInChain = nullptr;
|
||||||
|
bindGroupLayoutEntry.texture.sampleType = WGPUTextureSampleType_Float;
|
||||||
|
bindGroupLayoutEntry.texture.viewDimension = WGPUTextureViewDimension_2D;
|
||||||
|
bindGroupLayoutEntry.texture.multisampled = false;
|
||||||
|
return bindGroupLayoutEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBuffer WgBindGroup::createBuffer(WGPUDevice device, WGPUQueue queue, const void *data, size_t size) {
|
||||||
|
WGPUBufferDescriptor bufferDescriptor{};
|
||||||
|
bufferDescriptor.nextInChain = nullptr;
|
||||||
|
bufferDescriptor.label = "The uniform buffer";
|
||||||
|
bufferDescriptor.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
||||||
|
bufferDescriptor.size = size;
|
||||||
|
bufferDescriptor.mappedAtCreation = false;
|
||||||
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &bufferDescriptor);
|
||||||
|
assert(buffer);
|
||||||
|
wgpuQueueWriteBuffer(queue, buffer, 0, data, size);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroup WgBindGroup::createBindGroup(WGPUDevice device, WGPUBindGroupLayout layout, const WGPUBindGroupEntry* bindGroupEntries, uint32_t count) {
|
||||||
|
WGPUBindGroupDescriptor bindGroupDesc{};
|
||||||
|
bindGroupDesc.nextInChain = nullptr;
|
||||||
|
bindGroupDesc.label = "The binding group sampler";
|
||||||
|
bindGroupDesc.layout = layout;
|
||||||
|
bindGroupDesc.entryCount = count;
|
||||||
|
bindGroupDesc.entries = bindGroupEntries;
|
||||||
|
return wgpuDeviceCreateBindGroup(device, &bindGroupDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBindGroupLayout WgBindGroup::createBindGroupLayout(WGPUDevice device, const WGPUBindGroupLayoutEntry* bindGroupLayoutEntries, uint32_t count) {
|
||||||
|
WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{};
|
||||||
|
bindGroupLayoutDesc.nextInChain = nullptr;
|
||||||
|
bindGroupLayoutDesc.label = "The bind group layout";
|
||||||
|
bindGroupLayoutDesc.entryCount = count;
|
||||||
|
bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding
|
||||||
|
return wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroup::releaseBuffer(WGPUBuffer& buffer) {
|
||||||
|
if (buffer) {
|
||||||
|
wgpuBufferDestroy(buffer);
|
||||||
|
wgpuBufferRelease(buffer);
|
||||||
|
buffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroup::releaseBindGroup(WGPUBindGroup& bindGroup) {
|
||||||
|
if (bindGroup) wgpuBindGroupRelease(bindGroup);
|
||||||
|
bindGroup = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgBindGroup::releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout) {
|
||||||
|
if (bindGroupLayout) wgpuBindGroupLayoutRelease(bindGroupLayout);
|
||||||
|
bindGroupLayout = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
// pipeline
|
||||||
|
//*****************************************************************************
|
||||||
|
|
||||||
|
void WgPipeline::allocate(WGPUDevice device,
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount,
|
||||||
|
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
|
||||||
|
const char* shaderSource, const char* shaderLabel, const char* pipelineLabel)
|
||||||
|
{
|
||||||
|
mShaderModule = createShaderModule(device, shaderSource, shaderLabel);
|
||||||
|
assert(mShaderModule);
|
||||||
|
|
||||||
|
mPipelineLayout = createPipelineLayout(device, bindGroupLayouts, bindGroupsCount);
|
||||||
|
assert(mPipelineLayout);
|
||||||
|
|
||||||
|
mRenderPipeline = createRenderPipeline(device,
|
||||||
|
vertexBufferLayouts, attribsCount,
|
||||||
|
stencilCompareFunction, stencilOperation,
|
||||||
|
mPipelineLayout, mShaderModule, pipelineLabel);
|
||||||
|
assert(mRenderPipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgPipeline::release() {
|
||||||
|
destroyRenderPipeline(mRenderPipeline);
|
||||||
|
destroyShaderModule(mShaderModule);
|
||||||
|
destroyPipelineLayout(mPipelineLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgPipeline::set(WGPURenderPassEncoder renderPassEncoder) {
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, mRenderPipeline);
|
||||||
|
};
|
||||||
|
|
||||||
|
WGPUBlendState WgPipeline::makeBlendState() {
|
||||||
|
WGPUBlendState blendState{};
|
||||||
|
blendState.color.operation = WGPUBlendOperation_Add;
|
||||||
|
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
||||||
|
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
||||||
|
blendState.alpha.operation = WGPUBlendOperation_Add;
|
||||||
|
blendState.alpha.srcFactor = WGPUBlendFactor_Zero;
|
||||||
|
blendState.alpha.dstFactor = WGPUBlendFactor_One;
|
||||||
|
return blendState;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUColorTargetState WgPipeline::makeColorTargetState(const WGPUBlendState* blendState) {
|
||||||
|
WGPUColorTargetState colorTargetState{};
|
||||||
|
colorTargetState.nextInChain = nullptr;
|
||||||
|
colorTargetState.format = WGPUTextureFormat_BGRA8Unorm; // (WGPUTextureFormat_BGRA8UnormSrgb)
|
||||||
|
colorTargetState.blend = blendState;
|
||||||
|
colorTargetState.writeMask = WGPUColorWriteMask_All;
|
||||||
|
return colorTargetState;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUVertexBufferLayout WgPipeline::makeVertexBufferLayout(const WGPUVertexAttribute* vertexAttributes, uint32_t count, uint64_t stride) {
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayoutPos{};
|
||||||
|
vertexBufferLayoutPos.arrayStride = stride;
|
||||||
|
vertexBufferLayoutPos.stepMode = WGPUVertexStepMode_Vertex;
|
||||||
|
vertexBufferLayoutPos.attributeCount = count;
|
||||||
|
vertexBufferLayoutPos.attributes = vertexAttributes;
|
||||||
|
return vertexBufferLayoutPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUVertexState WgPipeline::makeVertexState(WGPUShaderModule shaderModule, const WGPUVertexBufferLayout* buffers, uint32_t count) {
|
||||||
|
WGPUVertexState vertexState{};
|
||||||
|
vertexState.nextInChain = nullptr;
|
||||||
|
vertexState.module = shaderModule;
|
||||||
|
vertexState.entryPoint = "vs_main";
|
||||||
|
vertexState.constantCount = 0;
|
||||||
|
vertexState.constants = nullptr;
|
||||||
|
vertexState.bufferCount = count;
|
||||||
|
vertexState.buffers = buffers;
|
||||||
|
return vertexState;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUPrimitiveState WgPipeline::makePrimitiveState() {
|
||||||
|
WGPUPrimitiveState primitiveState{};
|
||||||
|
primitiveState.nextInChain = nullptr;
|
||||||
|
primitiveState.topology = WGPUPrimitiveTopology_TriangleList;
|
||||||
|
primitiveState.stripIndexFormat = WGPUIndexFormat_Undefined;
|
||||||
|
primitiveState.frontFace = WGPUFrontFace_CCW;
|
||||||
|
primitiveState.cullMode = WGPUCullMode_None;
|
||||||
|
return primitiveState;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUDepthStencilState WgPipeline::makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation) {
|
||||||
|
WGPUDepthStencilState depthStencilState{};
|
||||||
|
depthStencilState.nextInChain = nullptr;
|
||||||
|
depthStencilState.format = WGPUTextureFormat_Stencil8;
|
||||||
|
depthStencilState.depthWriteEnabled = false;
|
||||||
|
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
||||||
|
depthStencilState.stencilFront.compare = compare;
|
||||||
|
depthStencilState.stencilFront.failOp = operation;
|
||||||
|
depthStencilState.stencilFront.depthFailOp = operation;
|
||||||
|
depthStencilState.stencilFront.passOp = operation;
|
||||||
|
depthStencilState.stencilBack.compare = compare;
|
||||||
|
depthStencilState.stencilBack.failOp = operation;
|
||||||
|
depthStencilState.stencilBack.depthFailOp = operation;
|
||||||
|
depthStencilState.stencilBack.passOp = operation;
|
||||||
|
depthStencilState.stencilReadMask = 0xFFFFFFFF;
|
||||||
|
depthStencilState.stencilWriteMask = 0xFFFFFFFF;
|
||||||
|
depthStencilState.depthBias = 0;
|
||||||
|
depthStencilState.depthBiasSlopeScale = 0.0f;
|
||||||
|
depthStencilState.depthBiasClamp = 0.0f;
|
||||||
|
return depthStencilState;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUMultisampleState WgPipeline::makeMultisampleState() {
|
||||||
|
WGPUMultisampleState multisampleState{};
|
||||||
|
multisampleState.nextInChain = nullptr;
|
||||||
|
multisampleState.count = 1;
|
||||||
|
multisampleState.mask = 0xFFFFFFFF;
|
||||||
|
multisampleState.alphaToCoverageEnabled = false;
|
||||||
|
return multisampleState;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUFragmentState WgPipeline::makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size) {
|
||||||
|
WGPUFragmentState fragmentState{};
|
||||||
|
fragmentState.nextInChain = nullptr;
|
||||||
|
fragmentState.module = shaderModule;
|
||||||
|
fragmentState.entryPoint = "fs_main";
|
||||||
|
fragmentState.constantCount = 0;
|
||||||
|
fragmentState.constants = nullptr;
|
||||||
|
fragmentState.targetCount = size;
|
||||||
|
fragmentState.targets = targets;
|
||||||
|
return fragmentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUPipelineLayout WgPipeline::createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, uint32_t count) {
|
||||||
|
WGPUPipelineLayoutDescriptor pipelineLayoutDesc{};
|
||||||
|
pipelineLayoutDesc.nextInChain = nullptr;
|
||||||
|
pipelineLayoutDesc.label = "The Pipeline layout";
|
||||||
|
pipelineLayoutDesc.bindGroupLayoutCount = count;
|
||||||
|
pipelineLayoutDesc.bindGroupLayouts = bindGroupLayouts;
|
||||||
|
return wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUShaderModule WgPipeline::createShaderModule(WGPUDevice device, const char* code, const char* label) {
|
||||||
|
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
|
||||||
|
shaderModuleWGSLDesc.chain.next = nullptr;
|
||||||
|
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
||||||
|
shaderModuleWGSLDesc.code = code;
|
||||||
|
WGPUShaderModuleDescriptor shaderModuleDesc{};
|
||||||
|
shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain;
|
||||||
|
shaderModuleDesc.label = label;
|
||||||
|
shaderModuleDesc.hintCount = 0;
|
||||||
|
shaderModuleDesc.hints = nullptr;
|
||||||
|
return wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPURenderPipeline WgPipeline::createRenderPipeline(WGPUDevice device,
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
|
||||||
|
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
|
||||||
|
WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule,
|
||||||
|
const char* pipelineName) {
|
||||||
|
WGPUBlendState blendState = makeBlendState();
|
||||||
|
WGPUColorTargetState colorTargetStates[] = {
|
||||||
|
makeColorTargetState(&blendState)
|
||||||
|
};
|
||||||
|
|
||||||
|
WGPUVertexState vertexState = makeVertexState(shaderModule, vertexBufferLayouts, attribsCount);
|
||||||
|
WGPUPrimitiveState primitiveState = makePrimitiveState();
|
||||||
|
WGPUDepthStencilState depthStencilState = makeDepthStencilState(stencilCompareFunction, stencilOperation);
|
||||||
|
WGPUMultisampleState multisampleState = makeMultisampleState();
|
||||||
|
WGPUFragmentState fragmentState = makeFragmentState(shaderModule, colorTargetStates, 1);
|
||||||
|
|
||||||
|
WGPURenderPipelineDescriptor renderPipelineDesc{};
|
||||||
|
renderPipelineDesc.nextInChain = nullptr;
|
||||||
|
renderPipelineDesc.label = pipelineName;
|
||||||
|
renderPipelineDesc.layout = pipelineLayout;
|
||||||
|
renderPipelineDesc.vertex = vertexState;
|
||||||
|
renderPipelineDesc.primitive = primitiveState;
|
||||||
|
renderPipelineDesc.depthStencil = &depthStencilState;
|
||||||
|
renderPipelineDesc.multisample = multisampleState;
|
||||||
|
renderPipelineDesc.fragment = &fragmentState;
|
||||||
|
return wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgPipeline::destroyPipelineLayout(WGPUPipelineLayout& pipelineLayout) {
|
||||||
|
if (pipelineLayout) wgpuPipelineLayoutRelease(pipelineLayout);
|
||||||
|
pipelineLayout = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgPipeline::destroyShaderModule(WGPUShaderModule& shaderModule) {
|
||||||
|
if (shaderModule) wgpuShaderModuleRelease(shaderModule);
|
||||||
|
shaderModule = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgPipeline::destroyRenderPipeline(WGPURenderPipeline& renderPipeline) {
|
||||||
|
if (renderPipeline) wgpuRenderPipelineRelease(renderPipeline);
|
||||||
|
renderPipeline = nullptr;
|
||||||
|
}
|
|
@ -28,4 +28,63 @@
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
#include "tvgRender.h"
|
#include "tvgRender.h"
|
||||||
|
|
||||||
|
struct WgBindGroup {
|
||||||
|
WGPUBindGroup mBindGroup{};
|
||||||
|
|
||||||
|
void set(WGPURenderPassEncoder encoder, uint32_t groupIndex);
|
||||||
|
|
||||||
|
static WGPUBindGroupEntry makeBindGroupEntryBuffer(uint32_t binding, WGPUBuffer buffer);
|
||||||
|
static WGPUBindGroupEntry makeBindGroupEntrySampler(uint32_t binding, WGPUSampler sampler);
|
||||||
|
static WGPUBindGroupEntry makeBindGroupEntryTextureView(uint32_t binding, WGPUTextureView textureView);
|
||||||
|
|
||||||
|
static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryBuffer(uint32_t binding);
|
||||||
|
static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntrySampler(uint32_t binding);
|
||||||
|
static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryTextureView(uint32_t binding);
|
||||||
|
|
||||||
|
static WGPUBuffer createBuffer(WGPUDevice device, WGPUQueue queue, const void *data, size_t size);
|
||||||
|
static WGPUBindGroup createBindGroup(WGPUDevice device, WGPUBindGroupLayout layout, const WGPUBindGroupEntry* bindGroupEntries, uint32_t count);
|
||||||
|
static WGPUBindGroupLayout createBindGroupLayout(WGPUDevice device, const WGPUBindGroupLayoutEntry* bindGroupLayoutEntries, uint32_t count);
|
||||||
|
|
||||||
|
static void releaseBuffer(WGPUBuffer& buffer);
|
||||||
|
static void releaseBindGroup(WGPUBindGroup& bindGroup);
|
||||||
|
static void releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WgPipeline {
|
||||||
|
protected:
|
||||||
|
void allocate(WGPUDevice device,
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount,
|
||||||
|
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
|
||||||
|
const char* shaderSource, const char* shaderLabel, const char* pipelineLabel);
|
||||||
|
WGPUPipelineLayout mPipelineLayout{};
|
||||||
|
WGPUShaderModule mShaderModule{};
|
||||||
|
WGPURenderPipeline mRenderPipeline{};
|
||||||
|
public:
|
||||||
|
virtual void initialize(WGPUDevice device) = 0;
|
||||||
|
virtual void release();
|
||||||
|
void set(WGPURenderPassEncoder renderPassEncoder);
|
||||||
|
|
||||||
|
static WGPUBlendState makeBlendState();
|
||||||
|
static WGPUColorTargetState makeColorTargetState(const WGPUBlendState* blendState);
|
||||||
|
static WGPUVertexBufferLayout makeVertexBufferLayout(const WGPUVertexAttribute* vertexAttributes, uint32_t count, uint64_t stride);
|
||||||
|
static WGPUVertexState makeVertexState(WGPUShaderModule shaderModule, const WGPUVertexBufferLayout* buffers, uint32_t count);
|
||||||
|
static WGPUPrimitiveState makePrimitiveState();
|
||||||
|
static WGPUDepthStencilState makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation);
|
||||||
|
static WGPUMultisampleState makeMultisampleState();
|
||||||
|
static WGPUFragmentState makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size);
|
||||||
|
|
||||||
|
static WGPUPipelineLayout createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, uint32_t count);
|
||||||
|
static WGPUShaderModule createShaderModule(WGPUDevice device, const char* code, const char* label);
|
||||||
|
static WGPURenderPipeline createRenderPipeline(
|
||||||
|
WGPUDevice device,
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
|
||||||
|
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
|
||||||
|
WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule,
|
||||||
|
const char* pipelineLabel);
|
||||||
|
static void destroyPipelineLayout(WGPUPipelineLayout& pipelineLayout);
|
||||||
|
static void destroyShaderModule(WGPUShaderModule& shaderModule);
|
||||||
|
static void destroyRenderPipeline(WGPURenderPipeline& renderPipeline);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _TVG_WG_COMMON_H_
|
#endif // _TVG_WG_COMMON_H_
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tvgWgPipelineBase.h"
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
// WgPipelineData
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
void WgPipelineData::updateMatrix(const float* viewMatrix, const RenderTransform* transform) {
|
|
||||||
float modelMatrix[16]{};
|
|
||||||
if (transform) {
|
|
||||||
modelMatrix[0] = transform->m.e11;
|
|
||||||
modelMatrix[1] = transform->m.e21;
|
|
||||||
modelMatrix[3] = transform->m.e31;
|
|
||||||
modelMatrix[4] = transform->m.e12;
|
|
||||||
modelMatrix[5] = transform->m.e22;
|
|
||||||
modelMatrix[7] = transform->m.e32;
|
|
||||||
modelMatrix[10] = 1.0f;
|
|
||||||
modelMatrix[12] = transform->m.e13;
|
|
||||||
modelMatrix[13] = transform->m.e23;
|
|
||||||
modelMatrix[15] = transform->m.e33;
|
|
||||||
} else {
|
|
||||||
modelMatrix[0] = 1.0f;
|
|
||||||
modelMatrix[5] = 1.0f;
|
|
||||||
modelMatrix[10] = 1.0f;
|
|
||||||
modelMatrix[15] = 1.0f;
|
|
||||||
}
|
|
||||||
// matrix multiply
|
|
||||||
for(auto i = 0; i < 4; ++i) {
|
|
||||||
for(auto j = 0; j < 4; ++j) {
|
|
||||||
float sum = 0.0;
|
|
||||||
for (auto k = 0; k < 4; ++k)
|
|
||||||
sum += viewMatrix[k*4+i] * modelMatrix[j*4+k];
|
|
||||||
uMatrix.transform[j*4+i] = sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
// WgPipelineBindGroup
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
void WgPipelineBindGroup::bind(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex) {
|
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, groupIndex, mBindGroup, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
// WgPipelinePipeline
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
void WgPipelineBase::set(WGPURenderPassEncoder renderPassEncoder) {
|
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, mRenderPipeline);
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TVG_WG_PIPELINE_BASE_H_
|
|
||||||
#define _TVG_WG_PIPELINE_BASE_H_
|
|
||||||
|
|
||||||
#include "tvgWgCommon.h"
|
|
||||||
|
|
||||||
struct WgPipelineMatrix {
|
|
||||||
float transform[4*4]{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WgPipelineData {
|
|
||||||
WgPipelineMatrix uMatrix{}; // @binding(0)
|
|
||||||
void updateMatrix(const float* viewMatrix, const RenderTransform* transform);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WgPipelineBindGroup {
|
|
||||||
WGPUBuffer uBufferMatrix{};
|
|
||||||
WGPUBindGroup mBindGroup{};
|
|
||||||
void bind(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineBase {
|
|
||||||
public:
|
|
||||||
WGPUBindGroupLayout mBindGroupLayout{}; // @group(0)
|
|
||||||
WGPUPipelineLayout mPipelineLayout{};
|
|
||||||
WGPUShaderModule mShaderModule{};
|
|
||||||
WGPURenderPipeline mRenderPipeline{};
|
|
||||||
public:
|
|
||||||
virtual void initialize(WGPUDevice device) = 0;
|
|
||||||
virtual void release() = 0;
|
|
||||||
|
|
||||||
void set(WGPURenderPassEncoder renderPassEncoder);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _TVG_WG_PIPELINE_BASE_H_
|
|
|
@ -1,243 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tvgWgPipelineEmpty.h"
|
|
||||||
#include "tvgWgShaderSrc.h"
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupEmpty
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineBindGroupEmpty::initialize(WGPUDevice device, WgPipelineEmpty& pipelinePipelineEmpty) {
|
|
||||||
// buffer uniform uMatrix
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uMatrix{};
|
|
||||||
bufferUniformDesc_uMatrix.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline empty uMatrix";
|
|
||||||
bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bufferUniformDesc_uMatrix.mappedAtCreation = false;
|
|
||||||
uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix);
|
|
||||||
assert(uBufferMatrix);
|
|
||||||
|
|
||||||
// bind group entry @binding(0) uMatrix
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uMatrix{};
|
|
||||||
bindGroupEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupEntry_uMatrix.buffer = uBufferMatrix;
|
|
||||||
bindGroupEntry_uMatrix.offset = 0;
|
|
||||||
bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bindGroupEntry_uMatrix.sampler = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.textureView = nullptr;
|
|
||||||
// bind group entries
|
|
||||||
WGPUBindGroupEntry bindGroupEntries[] {
|
|
||||||
bindGroupEntry_uMatrix // @binding(0) uMatrix
|
|
||||||
};
|
|
||||||
// bind group descriptor
|
|
||||||
WGPUBindGroupDescriptor bindGroupDescPipeline{};
|
|
||||||
bindGroupDescPipeline.nextInChain = nullptr;
|
|
||||||
bindGroupDescPipeline.label = "The binding group pipeline empty";
|
|
||||||
bindGroupDescPipeline.layout = pipelinePipelineEmpty.mBindGroupLayout;
|
|
||||||
bindGroupDescPipeline.entryCount = 1;
|
|
||||||
bindGroupDescPipeline.entries = bindGroupEntries;
|
|
||||||
mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline);
|
|
||||||
assert(mBindGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupEmpty::release() {
|
|
||||||
if (uBufferMatrix) {
|
|
||||||
wgpuBufferDestroy(uBufferMatrix);
|
|
||||||
wgpuBufferRelease(uBufferMatrix);
|
|
||||||
uBufferMatrix = nullptr;
|
|
||||||
}
|
|
||||||
if (mBindGroup) {
|
|
||||||
wgpuBindGroupRelease(mBindGroup);
|
|
||||||
mBindGroup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupEmpty::update(WGPUQueue queue, WgPipelineDataEmpty& pipelineDataEmpty) {
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataEmpty.uMatrix, sizeof(pipelineDataEmpty.uMatrix));
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineEmpty
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineEmpty::initialize(WGPUDevice device) {
|
|
||||||
// bind group layout group 0
|
|
||||||
// bind group layout descriptor @group(0) @binding(0) uMatrix
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{};
|
|
||||||
bindGroupLayoutEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout entries @group(0)
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
|
||||||
bindGroupLayoutEntry_uMatrix
|
|
||||||
};
|
|
||||||
// bind group layout descriptor scene @group(0)
|
|
||||||
WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{};
|
|
||||||
bindGroupLayoutDesc.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutDesc.label = "Bind group layout pipeline empty";
|
|
||||||
bindGroupLayoutDesc.entryCount = 1;
|
|
||||||
bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding
|
|
||||||
mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
|
|
||||||
assert(mBindGroupLayout);
|
|
||||||
|
|
||||||
// pipeline layout
|
|
||||||
|
|
||||||
// bind group layout descriptors
|
|
||||||
WGPUBindGroupLayout mBindGroupLayouts[] {
|
|
||||||
mBindGroupLayout
|
|
||||||
};
|
|
||||||
// pipeline layout descriptor
|
|
||||||
WGPUPipelineLayoutDescriptor pipelineLayoutDesc{};
|
|
||||||
pipelineLayoutDesc.nextInChain = nullptr;
|
|
||||||
pipelineLayoutDesc.label = "Pipeline pipeline layout empty";
|
|
||||||
pipelineLayoutDesc.bindGroupLayoutCount = 1;
|
|
||||||
pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts;
|
|
||||||
mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
|
|
||||||
assert(mPipelineLayout);
|
|
||||||
|
|
||||||
// depth stencil state
|
|
||||||
WGPUDepthStencilState depthStencilState{};
|
|
||||||
depthStencilState.nextInChain = nullptr;
|
|
||||||
depthStencilState.format = WGPUTextureFormat_Stencil8;
|
|
||||||
depthStencilState.depthWriteEnabled = false;
|
|
||||||
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
|
||||||
// depthStencilState.stencilFront
|
|
||||||
depthStencilState.stencilFront.compare = WGPUCompareFunction_Always;
|
|
||||||
depthStencilState.stencilFront.failOp = WGPUStencilOperation_Invert;
|
|
||||||
depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Invert;
|
|
||||||
depthStencilState.stencilFront.passOp = WGPUStencilOperation_Invert;
|
|
||||||
// depthStencilState.stencilBack
|
|
||||||
depthStencilState.stencilBack.compare = WGPUCompareFunction_Always;
|
|
||||||
depthStencilState.stencilBack.failOp = WGPUStencilOperation_Invert;
|
|
||||||
depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Invert;
|
|
||||||
depthStencilState.stencilBack.passOp = WGPUStencilOperation_Invert;
|
|
||||||
// stencil mask
|
|
||||||
depthStencilState.stencilReadMask = 0xFFFFFFFF;
|
|
||||||
depthStencilState.stencilWriteMask = 0xFFFFFFFF;
|
|
||||||
// depth bias
|
|
||||||
depthStencilState.depthBias = 0;
|
|
||||||
depthStencilState.depthBiasSlopeScale = 0.0f;
|
|
||||||
depthStencilState.depthBiasClamp = 0.0f;
|
|
||||||
|
|
||||||
// shader module wgsl descriptor
|
|
||||||
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
|
|
||||||
shaderModuleWGSLDesc.chain.next = nullptr;
|
|
||||||
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
|
||||||
shaderModuleWGSLDesc.code = cShaderSource_PipelineEmpty;
|
|
||||||
// shader module descriptor
|
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc{};
|
|
||||||
shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain;
|
|
||||||
shaderModuleDesc.label = "The shader module pipeline empty";
|
|
||||||
shaderModuleDesc.hintCount = 0;
|
|
||||||
shaderModuleDesc.hints = nullptr;
|
|
||||||
mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
|
||||||
assert(mShaderModule);
|
|
||||||
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexAttribute vertexAttributes[] = {
|
|
||||||
{ WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position
|
|
||||||
};
|
|
||||||
// vertex buffer layout
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayout{};
|
|
||||||
vertexBufferLayout.arrayStride = sizeof(float) * 2; // position
|
|
||||||
vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex;
|
|
||||||
vertexBufferLayout.attributeCount = 1; // position
|
|
||||||
vertexBufferLayout.attributes = vertexAttributes;
|
|
||||||
|
|
||||||
// blend state
|
|
||||||
WGPUBlendState blendState{};
|
|
||||||
// blendState.color
|
|
||||||
blendState.color.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
|
||||||
// blendState.alpha
|
|
||||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.alpha.srcFactor = WGPUBlendFactor_Zero;
|
|
||||||
blendState.alpha.dstFactor = WGPUBlendFactor_One;
|
|
||||||
|
|
||||||
// color target state (WGPUTextureFormat_BGRA8UnormSrgb)
|
|
||||||
WGPUColorTargetState colorTargetState0{};
|
|
||||||
colorTargetState0.nextInChain = nullptr;
|
|
||||||
colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm;
|
|
||||||
//colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb;
|
|
||||||
colorTargetState0.blend = &blendState;
|
|
||||||
colorTargetState0.writeMask = WGPUColorWriteMask_All;
|
|
||||||
// color target states
|
|
||||||
WGPUColorTargetState colorTargetStates[] = {
|
|
||||||
colorTargetState0
|
|
||||||
};
|
|
||||||
// fragmanet state
|
|
||||||
WGPUFragmentState fragmentState{};
|
|
||||||
fragmentState.nextInChain = nullptr;
|
|
||||||
fragmentState.module = mShaderModule;
|
|
||||||
fragmentState.entryPoint = "fs_main";
|
|
||||||
fragmentState.constantCount = 0;
|
|
||||||
fragmentState.constants = nullptr;
|
|
||||||
fragmentState.targetCount = 1;
|
|
||||||
fragmentState.targets = colorTargetStates; // render target index
|
|
||||||
|
|
||||||
// render pipeline descriptor
|
|
||||||
WGPURenderPipelineDescriptor renderPipelineDesc{};
|
|
||||||
renderPipelineDesc.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.label = "Render pipeline pipeline empty";
|
|
||||||
// renderPipelineDesc.layout
|
|
||||||
renderPipelineDesc.layout = mPipelineLayout;
|
|
||||||
// renderPipelineDesc.vertex
|
|
||||||
renderPipelineDesc.vertex.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.vertex.module = mShaderModule;
|
|
||||||
renderPipelineDesc.vertex.entryPoint = "vs_main";
|
|
||||||
renderPipelineDesc.vertex.constantCount = 0;
|
|
||||||
renderPipelineDesc.vertex.constants = nullptr;
|
|
||||||
renderPipelineDesc.vertex.bufferCount = 1;
|
|
||||||
renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index
|
|
||||||
// renderPipelineDesc.primitive
|
|
||||||
renderPipelineDesc.primitive.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
|
||||||
renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
|
|
||||||
renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW;
|
|
||||||
renderPipelineDesc.primitive.cullMode = WGPUCullMode_None;
|
|
||||||
// renderPipelineDesc.depthStencil
|
|
||||||
renderPipelineDesc.depthStencil = &depthStencilState;
|
|
||||||
// renderPipelineDesc.multisample
|
|
||||||
renderPipelineDesc.multisample.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.multisample.count = 1;
|
|
||||||
renderPipelineDesc.multisample.mask = 0xFFFFFFFF;
|
|
||||||
renderPipelineDesc.multisample.alphaToCoverageEnabled = false;
|
|
||||||
// renderPipelineDesc.fragment
|
|
||||||
renderPipelineDesc.fragment = &fragmentState;
|
|
||||||
mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
|
||||||
assert(mRenderPipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineEmpty::release() {
|
|
||||||
wgpuRenderPipelineRelease(mRenderPipeline);
|
|
||||||
wgpuShaderModuleRelease(mShaderModule);
|
|
||||||
wgpuPipelineLayoutRelease(mPipelineLayout);
|
|
||||||
wgpuBindGroupLayoutRelease(mBindGroupLayout);
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TVG_WG_PIPELINE_EMPTY_H_
|
|
||||||
#define _TVG_WG_PIPELINE_EMPTY_H_
|
|
||||||
|
|
||||||
#include "tvgWgPipelineBase.h"
|
|
||||||
|
|
||||||
class WgPipelineEmpty;
|
|
||||||
|
|
||||||
struct WgPipelineDataEmpty: WgPipelineData {};
|
|
||||||
|
|
||||||
class WgPipelineBindGroupEmpty: public WgPipelineBindGroup {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device, WgPipelineEmpty& pipelinePipelineEmpty);
|
|
||||||
void release();
|
|
||||||
|
|
||||||
void update(WGPUQueue mQueue, WgPipelineDataEmpty& pipelineDataSolid);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This pipeline is used for drawing filled, concave polygons using the stencil buffer
|
|
||||||
* This can be done using the stencil buffer, with a two-pass algorithm.
|
|
||||||
*
|
|
||||||
* First, clear the stencil buffer and disable writing into the color buffer. Next, draw each of the triangles in turn, using the INVERT function in the stencil buffer. (For best performance, use triangle fans.)
|
|
||||||
* This flips the value between zero and a nonzero value every time a triangle is drawn that covers a pixel.
|
|
||||||
*
|
|
||||||
* After all the triangles are drawn, if a pixel is covered an even number of times, the value in the stencil buffers is zero; otherwise, it's nonzero.
|
|
||||||
* Finally, draw a large polygon over the whole region (or redraw the triangles), but allow drawing only where the stencil buffer is nonzero.
|
|
||||||
*
|
|
||||||
* There is a link to the solution, how to draw filled, concave polygons using the stencil buffer:
|
|
||||||
* https://www.glprogramming.com/red/chapter14.html#name13
|
|
||||||
*
|
|
||||||
* The benefit of this solution is to don`t use complex tesselation to fill self intersected or concave poligons.
|
|
||||||
*
|
|
||||||
* This pipeline implements the first pass of this solution. It`s did not write anything into color buffer but fills the stencil buffer using invert strategy
|
|
||||||
*/
|
|
||||||
class WgPipelineEmpty: public WgPipelineBase {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device) override;
|
|
||||||
void release() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _TVG_WG_PIPELINE_EMPTY_H_
|
|
|
@ -1,415 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tvgWgPipelineImage.h"
|
|
||||||
#include "tvgWgShaderSrc.h"
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineDataImage
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineDataImage::updateFormat(const ColorSpace format) {
|
|
||||||
uColorInfo.format = (uint32_t)format;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineDataImage::updateOpacity(const uint8_t opacity) {
|
|
||||||
uColorInfo.opacity = opacity / 255.0f; // alpha
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupImage
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineBindGroupImage::initialize(WGPUDevice device, WgPipelineImage& pipelineImage, Surface* surface) {
|
|
||||||
// buffer uniform uMatrix
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uMatrix{};
|
|
||||||
bufferUniformDesc_uMatrix.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline image uMatrix";
|
|
||||||
bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bufferUniformDesc_uMatrix.mappedAtCreation = false;
|
|
||||||
uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix);
|
|
||||||
assert(uBufferMatrix);
|
|
||||||
// buffer uniform uColorInfo
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uColorInfo{};
|
|
||||||
bufferUniformDesc_uColorInfo.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uColorInfo.label = "Buffer uniform pipeline image uColorInfo";
|
|
||||||
bufferUniformDesc_uColorInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uColorInfo.size = sizeof(WgPipelineImageColorInfo);
|
|
||||||
bufferUniformDesc_uColorInfo.mappedAtCreation = false;
|
|
||||||
uBufferColorInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uColorInfo);
|
|
||||||
assert(uBufferColorInfo);
|
|
||||||
// sampler uniform uSamplerBase
|
|
||||||
WGPUSamplerDescriptor samplerDesc_uSamplerBase{};
|
|
||||||
samplerDesc_uSamplerBase.nextInChain = nullptr;
|
|
||||||
samplerDesc_uSamplerBase.label = "Sampler uniform pipeline image uSamplerBase";
|
|
||||||
samplerDesc_uSamplerBase.addressModeU = WGPUAddressMode_ClampToEdge;
|
|
||||||
samplerDesc_uSamplerBase.addressModeV = WGPUAddressMode_ClampToEdge;
|
|
||||||
samplerDesc_uSamplerBase.addressModeW = WGPUAddressMode_ClampToEdge;
|
|
||||||
samplerDesc_uSamplerBase.magFilter = WGPUFilterMode_Nearest;
|
|
||||||
samplerDesc_uSamplerBase.minFilter = WGPUFilterMode_Nearest;
|
|
||||||
samplerDesc_uSamplerBase.mipmapFilter = WGPUMipmapFilterMode_Nearest;
|
|
||||||
samplerDesc_uSamplerBase.lodMinClamp = 0.0f;
|
|
||||||
samplerDesc_uSamplerBase.lodMaxClamp = 32.0f;
|
|
||||||
samplerDesc_uSamplerBase.compare = WGPUCompareFunction_Undefined;
|
|
||||||
samplerDesc_uSamplerBase.maxAnisotropy = 1;
|
|
||||||
uSamplerBase = wgpuDeviceCreateSampler(device, &samplerDesc_uSamplerBase);
|
|
||||||
assert(uSamplerBase);
|
|
||||||
// webgpu texture data holder
|
|
||||||
WGPUTextureDescriptor textureDesc{};
|
|
||||||
textureDesc.nextInChain = nullptr;
|
|
||||||
textureDesc.label = "Texture base pipeline image";
|
|
||||||
textureDesc.usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst;
|
|
||||||
textureDesc.dimension = WGPUTextureDimension_2D;
|
|
||||||
textureDesc.size = { surface->w, surface->h, 1 };
|
|
||||||
textureDesc.format = WGPUTextureFormat_RGBA8Unorm;
|
|
||||||
textureDesc.mipLevelCount = 1;
|
|
||||||
textureDesc.sampleCount = 1;
|
|
||||||
textureDesc.viewFormatCount = 0;
|
|
||||||
textureDesc.viewFormats = nullptr;
|
|
||||||
mTextureBase = wgpuDeviceCreateTexture(device, &textureDesc);
|
|
||||||
assert(mTextureBase);
|
|
||||||
// texture view uniform uTextureViewBase
|
|
||||||
WGPUTextureViewDescriptor textureViewDesc{};
|
|
||||||
textureViewDesc.nextInChain = nullptr;
|
|
||||||
textureViewDesc.label = "The depth-stencil texture view";
|
|
||||||
textureViewDesc.format = WGPUTextureFormat_RGBA8Unorm;
|
|
||||||
textureViewDesc.dimension = WGPUTextureViewDimension_2D;
|
|
||||||
textureViewDesc.baseMipLevel = 0;
|
|
||||||
textureViewDesc.mipLevelCount = 1;
|
|
||||||
textureViewDesc.baseArrayLayer = 0;
|
|
||||||
textureViewDesc.arrayLayerCount = 1;
|
|
||||||
textureViewDesc.aspect = WGPUTextureAspect_All;
|
|
||||||
uTextureViewBase = wgpuTextureCreateView(mTextureBase, &textureViewDesc);
|
|
||||||
assert(uTextureViewBase);
|
|
||||||
|
|
||||||
// bind group entry @binding(0) uMatrix
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uMatrix{};
|
|
||||||
bindGroupEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupEntry_uMatrix.buffer = uBufferMatrix;
|
|
||||||
bindGroupEntry_uMatrix.offset = 0;
|
|
||||||
bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bindGroupEntry_uMatrix.sampler = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.textureView = nullptr;
|
|
||||||
// bind group entry @binding(1) uColorInfo
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uColorInfo{};
|
|
||||||
bindGroupEntry_uColorInfo.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uColorInfo.binding = 1;
|
|
||||||
bindGroupEntry_uColorInfo.buffer = uBufferColorInfo;
|
|
||||||
bindGroupEntry_uColorInfo.offset = 0;
|
|
||||||
bindGroupEntry_uColorInfo.size = sizeof(WgPipelineImageColorInfo);
|
|
||||||
bindGroupEntry_uColorInfo.sampler = nullptr;
|
|
||||||
bindGroupEntry_uColorInfo.textureView = nullptr;
|
|
||||||
// bind group entry @binding(2) uSamplerBase
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uSamplerBase{};
|
|
||||||
bindGroupEntry_uSamplerBase.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uSamplerBase.binding = 2;
|
|
||||||
bindGroupEntry_uSamplerBase.buffer = nullptr;
|
|
||||||
bindGroupEntry_uSamplerBase.offset = 0;
|
|
||||||
bindGroupEntry_uSamplerBase.size = 0;
|
|
||||||
bindGroupEntry_uSamplerBase.sampler = uSamplerBase;
|
|
||||||
bindGroupEntry_uSamplerBase.textureView = nullptr;
|
|
||||||
// bind group entry @binding(3) uTextureViewBase
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uTextureViewBase{};
|
|
||||||
bindGroupEntry_uTextureViewBase.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uTextureViewBase.binding = 3;
|
|
||||||
bindGroupEntry_uTextureViewBase.buffer = nullptr;
|
|
||||||
bindGroupEntry_uTextureViewBase.offset = 0;
|
|
||||||
bindGroupEntry_uTextureViewBase.size = 0;
|
|
||||||
bindGroupEntry_uTextureViewBase.sampler = nullptr;
|
|
||||||
bindGroupEntry_uTextureViewBase.textureView = uTextureViewBase;
|
|
||||||
// bind group entries
|
|
||||||
WGPUBindGroupEntry bindGroupEntries[] {
|
|
||||||
bindGroupEntry_uMatrix, // @binding(0) uMatrix
|
|
||||||
bindGroupEntry_uColorInfo, // @binding(1) uColorInfo
|
|
||||||
bindGroupEntry_uSamplerBase, // @binding(2) uSamplerBase
|
|
||||||
bindGroupEntry_uTextureViewBase // @binding(3) uTextureViewBase
|
|
||||||
};
|
|
||||||
// bind group descriptor
|
|
||||||
WGPUBindGroupDescriptor bindGroupDescPipeline{};
|
|
||||||
bindGroupDescPipeline.nextInChain = nullptr;
|
|
||||||
bindGroupDescPipeline.label = "The binding group pipeline image";
|
|
||||||
bindGroupDescPipeline.layout = pipelineImage.mBindGroupLayout;
|
|
||||||
bindGroupDescPipeline.entryCount = 4;
|
|
||||||
bindGroupDescPipeline.entries = bindGroupEntries;
|
|
||||||
mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline);
|
|
||||||
assert(mBindGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupImage::release() {
|
|
||||||
if (uTextureViewBase) {
|
|
||||||
wgpuTextureViewRelease(uTextureViewBase);
|
|
||||||
uTextureViewBase = nullptr;
|
|
||||||
}
|
|
||||||
if (mTextureBase) {
|
|
||||||
wgpuTextureDestroy(mTextureBase);
|
|
||||||
wgpuTextureRelease(mTextureBase);
|
|
||||||
mTextureBase = nullptr;
|
|
||||||
}
|
|
||||||
if (uSamplerBase) {
|
|
||||||
wgpuSamplerRelease(uSamplerBase);
|
|
||||||
uSamplerBase = nullptr;
|
|
||||||
}
|
|
||||||
if (uBufferColorInfo) {
|
|
||||||
wgpuBufferDestroy(uBufferColorInfo);
|
|
||||||
wgpuBufferRelease(uBufferColorInfo);
|
|
||||||
uBufferColorInfo = nullptr;
|
|
||||||
}
|
|
||||||
if (uBufferMatrix) {
|
|
||||||
wgpuBufferDestroy(uBufferMatrix);
|
|
||||||
wgpuBufferRelease(uBufferMatrix);
|
|
||||||
uBufferMatrix = nullptr;
|
|
||||||
}
|
|
||||||
if (mBindGroup) {
|
|
||||||
wgpuBindGroupRelease(mBindGroup);
|
|
||||||
mBindGroup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupImage::update(WGPUQueue queue, WgPipelineDataImage& pipelineDataImage, Surface* surface) {
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataImage.uMatrix, sizeof(pipelineDataImage.uMatrix));
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferColorInfo, 0, &pipelineDataImage.uColorInfo, sizeof(pipelineDataImage.uColorInfo));
|
|
||||||
WGPUImageCopyTexture imageCopyTexture{};
|
|
||||||
imageCopyTexture.nextInChain = nullptr;
|
|
||||||
imageCopyTexture.texture = mTextureBase;
|
|
||||||
imageCopyTexture.mipLevel = 0;
|
|
||||||
imageCopyTexture.origin = { 0, 0, 0 };
|
|
||||||
imageCopyTexture.aspect = WGPUTextureAspect_All;
|
|
||||||
WGPUTextureDataLayout textureDataLayout{};
|
|
||||||
textureDataLayout.nextInChain = nullptr;
|
|
||||||
textureDataLayout.offset = 0;
|
|
||||||
textureDataLayout.bytesPerRow = 4 * surface->w;
|
|
||||||
textureDataLayout.rowsPerImage = surface->h;
|
|
||||||
WGPUExtent3D writeSize{};
|
|
||||||
writeSize.width = surface->w;
|
|
||||||
writeSize.height = surface->h;
|
|
||||||
writeSize.depthOrArrayLayers = 1;
|
|
||||||
wgpuQueueWriteTexture(queue, &imageCopyTexture, surface->data, 4 * surface->w * surface->h, &textureDataLayout, &writeSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineImage
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineImage::initialize(WGPUDevice device) {
|
|
||||||
// bind group layout group 0
|
|
||||||
// bind group layout descriptor @group(0) @binding(0) uMatrix
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{};
|
|
||||||
bindGroupLayoutEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout descriptor @group(0) @binding(1) uColorInfo
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{};
|
|
||||||
bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.binding = 1;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout descriptor @group(0) @binding(2) uSamplerBase
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uSamplerBase{};
|
|
||||||
bindGroupLayoutEntry_uSamplerBase.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uSamplerBase.binding = 2;
|
|
||||||
bindGroupLayoutEntry_uSamplerBase.visibility = WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uSamplerBase.sampler.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uSamplerBase.sampler.type = WGPUSamplerBindingType_Filtering;
|
|
||||||
// bind group layout descriptor @group(0) @binding(3) uTextureViewBase
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uTextureViewBase{};
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase.binding = 3;
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase.visibility = WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase.texture.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase.texture.sampleType = WGPUTextureSampleType_Float;
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase.texture.viewDimension = WGPUTextureViewDimension_2D;
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase.texture.multisampled = false;
|
|
||||||
// bind group layout entries @group(0)
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
|
||||||
bindGroupLayoutEntry_uMatrix,
|
|
||||||
bindGroupLayoutEntry_uColorInfo,
|
|
||||||
bindGroupLayoutEntry_uSamplerBase,
|
|
||||||
bindGroupLayoutEntry_uTextureViewBase
|
|
||||||
};
|
|
||||||
// bind group layout descriptor scene @group(0)
|
|
||||||
WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{};
|
|
||||||
bindGroupLayoutDesc.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutDesc.label = "Bind group layout pipeline image";
|
|
||||||
bindGroupLayoutDesc.entryCount = 4;
|
|
||||||
bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding
|
|
||||||
mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
|
|
||||||
assert(mBindGroupLayout);
|
|
||||||
|
|
||||||
// pipeline layout
|
|
||||||
|
|
||||||
// bind group layout descriptors
|
|
||||||
WGPUBindGroupLayout mBindGroupLayouts[] {
|
|
||||||
mBindGroupLayout
|
|
||||||
};
|
|
||||||
// pipeline layout descriptor
|
|
||||||
WGPUPipelineLayoutDescriptor pipelineLayoutDesc{};
|
|
||||||
pipelineLayoutDesc.nextInChain = nullptr;
|
|
||||||
pipelineLayoutDesc.label = "Pipeline pipeline layout image";
|
|
||||||
pipelineLayoutDesc.bindGroupLayoutCount = 1;
|
|
||||||
pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts;
|
|
||||||
mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
|
|
||||||
assert(mPipelineLayout);
|
|
||||||
|
|
||||||
// depth stencil state
|
|
||||||
WGPUDepthStencilState depthStencilState{};
|
|
||||||
depthStencilState.nextInChain = nullptr;
|
|
||||||
depthStencilState.format = WGPUTextureFormat_Stencil8;
|
|
||||||
depthStencilState.depthWriteEnabled = false;
|
|
||||||
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
|
||||||
// depthStencilState.stencilFront
|
|
||||||
depthStencilState.stencilFront.compare = WGPUCompareFunction_Always;
|
|
||||||
depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// depthStencilState.stencilBack
|
|
||||||
depthStencilState.stencilBack.compare = WGPUCompareFunction_Always;
|
|
||||||
depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// stencil mask
|
|
||||||
depthStencilState.stencilReadMask = 0xFFFFFFFF;
|
|
||||||
depthStencilState.stencilWriteMask = 0xFFFFFFFF;
|
|
||||||
// depth bias
|
|
||||||
depthStencilState.depthBias = 0;
|
|
||||||
depthStencilState.depthBiasSlopeScale = 0.0f;
|
|
||||||
depthStencilState.depthBiasClamp = 0.0f;
|
|
||||||
|
|
||||||
// shader module wgsl descriptor
|
|
||||||
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
|
|
||||||
shaderModuleWGSLDesc.chain.next = nullptr;
|
|
||||||
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
|
||||||
shaderModuleWGSLDesc.code = cShaderSource_PipelineImage;
|
|
||||||
// shader module descriptor
|
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc{};
|
|
||||||
shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain;
|
|
||||||
shaderModuleDesc.label = "The shader module pipeline image";
|
|
||||||
shaderModuleDesc.hintCount = 0;
|
|
||||||
shaderModuleDesc.hints = nullptr;
|
|
||||||
mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
|
||||||
assert(mShaderModule);
|
|
||||||
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexAttribute vertexAttributesPos[] = {
|
|
||||||
{ WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 } // position
|
|
||||||
};
|
|
||||||
// vertex buffer layout position
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayoutPos{};
|
|
||||||
vertexBufferLayoutPos.arrayStride = sizeof(float) * 2; // position
|
|
||||||
vertexBufferLayoutPos.stepMode = WGPUVertexStepMode_Vertex;
|
|
||||||
vertexBufferLayoutPos.attributeCount = 1; // position
|
|
||||||
vertexBufferLayoutPos.attributes = vertexAttributesPos;
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexAttribute vertexAttributesTex[] = {
|
|
||||||
{ WGPUVertexFormat_Float32x2, sizeof(float) * 0, 1 } // tex coords
|
|
||||||
};
|
|
||||||
// vertex buffer layout tex coords
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayoutTex{};
|
|
||||||
vertexBufferLayoutTex.arrayStride = sizeof(float) * 2; // tex coords
|
|
||||||
vertexBufferLayoutTex.stepMode = WGPUVertexStepMode_Vertex;
|
|
||||||
vertexBufferLayoutTex.attributeCount = 1; // tex coords
|
|
||||||
vertexBufferLayoutTex.attributes = vertexAttributesTex;
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayouts[] = {
|
|
||||||
vertexBufferLayoutPos,
|
|
||||||
vertexBufferLayoutTex
|
|
||||||
};
|
|
||||||
|
|
||||||
// blend state
|
|
||||||
WGPUBlendState blendState{};
|
|
||||||
// blendState.color
|
|
||||||
blendState.color.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
|
||||||
// blendState.alpha
|
|
||||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.alpha.srcFactor = WGPUBlendFactor_Zero;
|
|
||||||
blendState.alpha.dstFactor = WGPUBlendFactor_One;
|
|
||||||
|
|
||||||
// color target state (WGPUTextureFormat_BGRA8UnormSrgb)
|
|
||||||
WGPUColorTargetState colorTargetState0{};
|
|
||||||
colorTargetState0.nextInChain = nullptr;
|
|
||||||
colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm;
|
|
||||||
//colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb;
|
|
||||||
colorTargetState0.blend = &blendState;
|
|
||||||
colorTargetState0.writeMask = WGPUColorWriteMask_All;
|
|
||||||
// color target states
|
|
||||||
WGPUColorTargetState colorTargetStates[] = {
|
|
||||||
colorTargetState0
|
|
||||||
};
|
|
||||||
// fragmanet state
|
|
||||||
WGPUFragmentState fragmentState{};
|
|
||||||
fragmentState.nextInChain = nullptr;
|
|
||||||
fragmentState.module = mShaderModule;
|
|
||||||
fragmentState.entryPoint = "fs_main";
|
|
||||||
fragmentState.constantCount = 0;
|
|
||||||
fragmentState.constants = nullptr;
|
|
||||||
fragmentState.targetCount = 1;
|
|
||||||
fragmentState.targets = colorTargetStates; // render target index
|
|
||||||
|
|
||||||
// render pipeline descriptor
|
|
||||||
WGPURenderPipelineDescriptor renderPipelineDesc{};
|
|
||||||
renderPipelineDesc.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.label = "Render pipeline pipeline image";
|
|
||||||
// renderPipelineDesc.layout
|
|
||||||
renderPipelineDesc.layout = mPipelineLayout;
|
|
||||||
// renderPipelineDesc.vertex
|
|
||||||
renderPipelineDesc.vertex.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.vertex.module = mShaderModule;
|
|
||||||
renderPipelineDesc.vertex.entryPoint = "vs_main";
|
|
||||||
renderPipelineDesc.vertex.constantCount = 0;
|
|
||||||
renderPipelineDesc.vertex.constants = nullptr;
|
|
||||||
renderPipelineDesc.vertex.bufferCount = 2;
|
|
||||||
renderPipelineDesc.vertex.buffers = vertexBufferLayouts; // buffer index
|
|
||||||
// renderPipelineDesc.primitive
|
|
||||||
renderPipelineDesc.primitive.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
|
||||||
renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
|
|
||||||
renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW;
|
|
||||||
renderPipelineDesc.primitive.cullMode = WGPUCullMode_None;
|
|
||||||
// renderPipelineDesc.depthStencil
|
|
||||||
renderPipelineDesc.depthStencil = &depthStencilState;
|
|
||||||
// renderPipelineDesc.multisample
|
|
||||||
renderPipelineDesc.multisample.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.multisample.count = 1;
|
|
||||||
renderPipelineDesc.multisample.mask = 0xFFFFFFFF;
|
|
||||||
renderPipelineDesc.multisample.alphaToCoverageEnabled = false;
|
|
||||||
// renderPipelineDesc.fragment
|
|
||||||
renderPipelineDesc.fragment = &fragmentState;
|
|
||||||
mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
|
||||||
assert(mRenderPipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineImage::release() {
|
|
||||||
wgpuRenderPipelineRelease(mRenderPipeline);
|
|
||||||
wgpuShaderModuleRelease(mShaderModule);
|
|
||||||
wgpuPipelineLayoutRelease(mPipelineLayout);
|
|
||||||
wgpuBindGroupLayoutRelease(mBindGroupLayout);
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TVG_WG_PIPELINE_IMAGE_H_
|
|
||||||
#define _TVG_WG_PIPELINE_IMAGE_H_
|
|
||||||
|
|
||||||
#include "tvgWgPipelineBase.h"
|
|
||||||
|
|
||||||
class WgPipelineImage;
|
|
||||||
|
|
||||||
struct WgPipelineImageColorInfo {
|
|
||||||
uint32_t format{};
|
|
||||||
float dummy0{};
|
|
||||||
float dummy1{};
|
|
||||||
float opacity{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WgPipelineDataImage: WgPipelineData {
|
|
||||||
WgPipelineImageColorInfo uColorInfo{}; // @binding(1)
|
|
||||||
|
|
||||||
void updateFormat(const ColorSpace format);
|
|
||||||
void updateOpacity(const uint8_t opacity);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineBindGroupImage: public WgPipelineBindGroup {
|
|
||||||
private:
|
|
||||||
WGPUBuffer uBufferColorInfo{}; // @binding(1)
|
|
||||||
WGPUSampler uSamplerBase{}; // @binding(2)
|
|
||||||
WGPUTextureView uTextureViewBase{}; // @binding(3)
|
|
||||||
WGPUTexture mTextureBase{}; // gpu texture data
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device, WgPipelineImage& pipelineImage, Surface* surface);
|
|
||||||
void release();
|
|
||||||
|
|
||||||
void update(WGPUQueue mQueue, WgPipelineDataImage& pipelineDataImage, Surface* surface);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineImage: public WgPipelineBase {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device) override;
|
|
||||||
void release() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_TVG_WG_PIPELINE_IMAGE_H_
|
|
|
@ -1,305 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tvgWgPipelineLinear.h"
|
|
||||||
#include "tvgWgShaderSrc.h"
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupLinear
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineDataLinear::updateGradient(LinearGradient* linearGradient) {
|
|
||||||
|
|
||||||
const Fill::ColorStop* stops = nullptr;
|
|
||||||
auto stopCnt = linearGradient->colorStops(&stops);
|
|
||||||
|
|
||||||
uGradientInfo.nStops[0] = stopCnt;
|
|
||||||
uGradientInfo.nStops[1] = 0.5f;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
|
||||||
uGradientInfo.stopPoints[i] = stops[i].offset;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
linearGradient->linear(
|
|
||||||
&uGradientInfo.startPos[0],
|
|
||||||
&uGradientInfo.startPos[1],
|
|
||||||
&uGradientInfo.endPos[0],
|
|
||||||
&uGradientInfo.endPos[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupLinear
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineBindGroupLinear::initialize(WGPUDevice device, WgPipelineLinear& pipelinePipelineLinear) {
|
|
||||||
// buffer uniform uMatrix
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uMatrix{};
|
|
||||||
bufferUniformDesc_uMatrix.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline linear uMatrix";
|
|
||||||
bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bufferUniformDesc_uMatrix.mappedAtCreation = false;
|
|
||||||
uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix);
|
|
||||||
assert(uBufferMatrix);
|
|
||||||
// buffer uniform uColorInfo
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uGradientInfo{};
|
|
||||||
bufferUniformDesc_uGradientInfo.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uGradientInfo.label = "Buffer uniform pipeline linear uGradientInfo";
|
|
||||||
bufferUniformDesc_uGradientInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uGradientInfo.size = sizeof(WgPipelineLinearGradientInfo);
|
|
||||||
bufferUniformDesc_uGradientInfo.mappedAtCreation = false;
|
|
||||||
uBufferGradientInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uGradientInfo);
|
|
||||||
assert(uBufferGradientInfo);
|
|
||||||
|
|
||||||
// bind group entry @binding(0) uMatrix
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uMatrix{};
|
|
||||||
bindGroupEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupEntry_uMatrix.buffer = uBufferMatrix;
|
|
||||||
bindGroupEntry_uMatrix.offset = 0;
|
|
||||||
bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bindGroupEntry_uMatrix.sampler = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.textureView = nullptr;
|
|
||||||
// bind group entry @binding(1) uGradientInfo
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uGradientInfo{};
|
|
||||||
bindGroupEntry_uGradientInfo.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uGradientInfo.binding = 1;
|
|
||||||
bindGroupEntry_uGradientInfo.buffer = uBufferGradientInfo;
|
|
||||||
bindGroupEntry_uGradientInfo.offset = 0;
|
|
||||||
bindGroupEntry_uGradientInfo.size = sizeof(WgPipelineLinearGradientInfo);
|
|
||||||
bindGroupEntry_uGradientInfo.sampler = nullptr;
|
|
||||||
bindGroupEntry_uGradientInfo.textureView = nullptr;
|
|
||||||
// bind group entries
|
|
||||||
WGPUBindGroupEntry bindGroupEntries[] {
|
|
||||||
bindGroupEntry_uMatrix, // @binding(0) uMatrix
|
|
||||||
bindGroupEntry_uGradientInfo // @binding(1) uGradientInfo
|
|
||||||
};
|
|
||||||
// bind group descriptor
|
|
||||||
WGPUBindGroupDescriptor bindGroupDescPipeline{};
|
|
||||||
bindGroupDescPipeline.nextInChain = nullptr;
|
|
||||||
bindGroupDescPipeline.label = "The binding group pipeline linear";
|
|
||||||
bindGroupDescPipeline.layout = pipelinePipelineLinear.mBindGroupLayout;
|
|
||||||
bindGroupDescPipeline.entryCount = 2;
|
|
||||||
bindGroupDescPipeline.entries = bindGroupEntries;
|
|
||||||
mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline);
|
|
||||||
assert(mBindGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupLinear::release() {
|
|
||||||
if (uBufferGradientInfo) {
|
|
||||||
wgpuBufferDestroy(uBufferGradientInfo);
|
|
||||||
wgpuBufferRelease(uBufferGradientInfo);
|
|
||||||
uBufferGradientInfo = nullptr;
|
|
||||||
}
|
|
||||||
if (uBufferMatrix) {
|
|
||||||
wgpuBufferDestroy(uBufferMatrix);
|
|
||||||
wgpuBufferRelease(uBufferMatrix);
|
|
||||||
uBufferMatrix = nullptr;
|
|
||||||
}
|
|
||||||
if (mBindGroup) {
|
|
||||||
wgpuBindGroupRelease(mBindGroup);
|
|
||||||
mBindGroup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupLinear::update(WGPUQueue queue, WgPipelineDataLinear& pipelineDataLinear) {
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataLinear.uMatrix, sizeof(pipelineDataLinear.uMatrix));
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferGradientInfo, 0, &pipelineDataLinear.uGradientInfo, sizeof(pipelineDataLinear.uGradientInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineLinear
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineLinear::initialize(WGPUDevice device) {
|
|
||||||
// bind group layout group 0
|
|
||||||
// bind group layout descriptor @group(0) @binding(0) uMatrix
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{};
|
|
||||||
bindGroupLayoutEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout descriptor @group(0) @binding(1) uColorInfo
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{};
|
|
||||||
bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.binding = 1;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout entries @group(0)
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
|
||||||
bindGroupLayoutEntry_uMatrix,
|
|
||||||
bindGroupLayoutEntry_uColorInfo
|
|
||||||
};
|
|
||||||
// bind group layout descriptor scene @group(0)
|
|
||||||
WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{};
|
|
||||||
bindGroupLayoutDesc.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutDesc.label = "Bind group layout pipeline linear";
|
|
||||||
bindGroupLayoutDesc.entryCount = 2;
|
|
||||||
bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding
|
|
||||||
mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
|
|
||||||
assert(mBindGroupLayout);
|
|
||||||
|
|
||||||
// pipeline layout
|
|
||||||
|
|
||||||
// bind group layout descriptors
|
|
||||||
WGPUBindGroupLayout mBindGroupLayouts[] {
|
|
||||||
mBindGroupLayout
|
|
||||||
};
|
|
||||||
// pipeline layout descriptor
|
|
||||||
WGPUPipelineLayoutDescriptor pipelineLayoutDesc{};
|
|
||||||
pipelineLayoutDesc.nextInChain = nullptr;
|
|
||||||
pipelineLayoutDesc.label = "Pipeline pipeline layout linear";
|
|
||||||
pipelineLayoutDesc.bindGroupLayoutCount = 1;
|
|
||||||
pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts;
|
|
||||||
mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
|
|
||||||
assert(mPipelineLayout);
|
|
||||||
|
|
||||||
// depth stencil state
|
|
||||||
WGPUDepthStencilState depthStencilState{};
|
|
||||||
depthStencilState.nextInChain = nullptr;
|
|
||||||
depthStencilState.format = WGPUTextureFormat_Stencil8;
|
|
||||||
depthStencilState.depthWriteEnabled = false;
|
|
||||||
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
|
||||||
// depthStencilState.stencilFront
|
|
||||||
depthStencilState.stencilFront.compare = WGPUCompareFunction_NotEqual;
|
|
||||||
depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// depthStencilState.stencilBack
|
|
||||||
depthStencilState.stencilBack.compare = WGPUCompareFunction_NotEqual;
|
|
||||||
depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// stencil mask
|
|
||||||
depthStencilState.stencilReadMask = 0xFFFFFFFF;
|
|
||||||
depthStencilState.stencilWriteMask = 0xFFFFFFFF;
|
|
||||||
// depth bias
|
|
||||||
depthStencilState.depthBias = 0;
|
|
||||||
depthStencilState.depthBiasSlopeScale = 0.0f;
|
|
||||||
depthStencilState.depthBiasClamp = 0.0f;
|
|
||||||
|
|
||||||
// shader module wgsl descriptor
|
|
||||||
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
|
|
||||||
shaderModuleWGSLDesc.chain.next = nullptr;
|
|
||||||
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
|
||||||
shaderModuleWGSLDesc.code = cShaderSource_PipelineLinear;
|
|
||||||
// shader module descriptor
|
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc{};
|
|
||||||
shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain;
|
|
||||||
shaderModuleDesc.label = "The shader module pipeline linear";
|
|
||||||
shaderModuleDesc.hintCount = 0;
|
|
||||||
shaderModuleDesc.hints = nullptr;
|
|
||||||
mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
|
||||||
assert(mShaderModule);
|
|
||||||
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexAttribute vertexAttributes[] = {
|
|
||||||
{ WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position
|
|
||||||
};
|
|
||||||
// vertex buffer layout
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayout{};
|
|
||||||
vertexBufferLayout.arrayStride = sizeof(float) * 2; // position
|
|
||||||
vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex;
|
|
||||||
vertexBufferLayout.attributeCount = 1; // position
|
|
||||||
vertexBufferLayout.attributes = vertexAttributes;
|
|
||||||
|
|
||||||
// blend state
|
|
||||||
WGPUBlendState blendState{};
|
|
||||||
// blendState.color
|
|
||||||
blendState.color.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
|
||||||
// blendState.alpha
|
|
||||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.alpha.srcFactor = WGPUBlendFactor_Zero;
|
|
||||||
blendState.alpha.dstFactor = WGPUBlendFactor_One;
|
|
||||||
|
|
||||||
// color target state (WGPUTextureFormat_BGRA8UnormSrgb)
|
|
||||||
WGPUColorTargetState colorTargetState0{};
|
|
||||||
colorTargetState0.nextInChain = nullptr;
|
|
||||||
colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm;
|
|
||||||
//colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb;
|
|
||||||
colorTargetState0.blend = &blendState;
|
|
||||||
colorTargetState0.writeMask = WGPUColorWriteMask_All;
|
|
||||||
// color target states
|
|
||||||
WGPUColorTargetState colorTargetStates[] = {
|
|
||||||
colorTargetState0
|
|
||||||
};
|
|
||||||
// fragmanet state
|
|
||||||
WGPUFragmentState fragmentState{};
|
|
||||||
fragmentState.nextInChain = nullptr;
|
|
||||||
fragmentState.module = mShaderModule;
|
|
||||||
fragmentState.entryPoint = "fs_main";
|
|
||||||
fragmentState.constantCount = 0;
|
|
||||||
fragmentState.constants = nullptr;
|
|
||||||
fragmentState.targetCount = 1;
|
|
||||||
fragmentState.targets = colorTargetStates; // render target index
|
|
||||||
|
|
||||||
// render pipeline descriptor
|
|
||||||
WGPURenderPipelineDescriptor renderPipelineDesc{};
|
|
||||||
renderPipelineDesc.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.label = "Render pipeline pipeline linear";
|
|
||||||
// renderPipelineDesc.layout
|
|
||||||
renderPipelineDesc.layout = mPipelineLayout;
|
|
||||||
// renderPipelineDesc.vertex
|
|
||||||
renderPipelineDesc.vertex.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.vertex.module = mShaderModule;
|
|
||||||
renderPipelineDesc.vertex.entryPoint = "vs_main";
|
|
||||||
renderPipelineDesc.vertex.constantCount = 0;
|
|
||||||
renderPipelineDesc.vertex.constants = nullptr;
|
|
||||||
renderPipelineDesc.vertex.bufferCount = 1;
|
|
||||||
renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index
|
|
||||||
// renderPipelineDesc.primitive
|
|
||||||
renderPipelineDesc.primitive.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
|
||||||
renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
|
|
||||||
renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW;
|
|
||||||
renderPipelineDesc.primitive.cullMode = WGPUCullMode_None;
|
|
||||||
// renderPipelineDesc.depthStencil
|
|
||||||
renderPipelineDesc.depthStencil = &depthStencilState;
|
|
||||||
// renderPipelineDesc.multisample
|
|
||||||
renderPipelineDesc.multisample.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.multisample.count = 1;
|
|
||||||
renderPipelineDesc.multisample.mask = 0xFFFFFFFF;
|
|
||||||
renderPipelineDesc.multisample.alphaToCoverageEnabled = false;
|
|
||||||
// renderPipelineDesc.fragment
|
|
||||||
renderPipelineDesc.fragment = &fragmentState;
|
|
||||||
mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
|
||||||
assert(mRenderPipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineLinear::release() {
|
|
||||||
wgpuRenderPipelineRelease(mRenderPipeline);
|
|
||||||
wgpuShaderModuleRelease(mShaderModule);
|
|
||||||
wgpuPipelineLayoutRelease(mPipelineLayout);
|
|
||||||
wgpuBindGroupLayoutRelease(mBindGroupLayout);
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TVG_WG_PIPELINE_LINEAR_H_
|
|
||||||
#define _TVG_WG_PIPELINE_LINEAR_H_
|
|
||||||
|
|
||||||
#include "tvgWgPipelineBase.h"
|
|
||||||
|
|
||||||
class WgPipelineLinear;
|
|
||||||
|
|
||||||
#define MAX_LINEAR_GRADIENT_STOPS 4
|
|
||||||
struct WgPipelineLinearGradientInfo {
|
|
||||||
alignas(16) float nStops[4]{};
|
|
||||||
alignas(16) float startPos[2]{};
|
|
||||||
alignas(8) float endPos[2]{};
|
|
||||||
alignas(8) float stopPoints[MAX_LINEAR_GRADIENT_STOPS]{};
|
|
||||||
alignas(16) float stopColors[4 * MAX_LINEAR_GRADIENT_STOPS]{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WgPipelineDataLinear: WgPipelineData {
|
|
||||||
WgPipelineLinearGradientInfo uGradientInfo{}; // @binding(1)
|
|
||||||
|
|
||||||
void updateGradient(LinearGradient* linearGradient);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineBindGroupLinear: public WgPipelineBindGroup {
|
|
||||||
private:
|
|
||||||
WGPUBuffer uBufferGradientInfo{}; // @binding(1)
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device, WgPipelineLinear& pipelinePipelineLinear);
|
|
||||||
void release();
|
|
||||||
|
|
||||||
void update(WGPUQueue mQueue, WgPipelineDataLinear& pipelineDataLinear);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineLinear: public WgPipelineBase {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device) override;
|
|
||||||
void release() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_TVG_WG_PIPELINE_LINEAR_H_
|
|
|
@ -1,303 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tvgWgPipelineRadial.h"
|
|
||||||
#include "tvgWgShaderSrc.h"
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupRadial
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineDataRadial::updateGradient(RadialGradient* radialGradient) {
|
|
||||||
const Fill::ColorStop* stops = nullptr;
|
|
||||||
auto stopCnt = radialGradient->colorStops(&stops);
|
|
||||||
|
|
||||||
uGradientInfo.nStops[0] = stopCnt;
|
|
||||||
uGradientInfo.nStops[1] = 0.5f;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
|
||||||
uGradientInfo.stopPoints[i] = stops[i].offset;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
|
||||||
uGradientInfo.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
radialGradient->radial(
|
|
||||||
&uGradientInfo.centerPos[0],
|
|
||||||
&uGradientInfo.centerPos[1],
|
|
||||||
&uGradientInfo.radius[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupRadial
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineBindGroupRadial::initialize(WGPUDevice device, WgPipelineRadial& pipelinePipelineRadial) {
|
|
||||||
// buffer uniform uMatrix
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uMatrix{};
|
|
||||||
bufferUniformDesc_uMatrix.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline radial uMatrix";
|
|
||||||
bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bufferUniformDesc_uMatrix.mappedAtCreation = false;
|
|
||||||
uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix);
|
|
||||||
assert(uBufferMatrix);
|
|
||||||
// buffer uniform uColorInfo
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uGradientInfo{};
|
|
||||||
bufferUniformDesc_uGradientInfo.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uGradientInfo.label = "Buffer uniform pipeline radial uGradientInfo";
|
|
||||||
bufferUniformDesc_uGradientInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uGradientInfo.size = sizeof(WgPipelineRadialGradientInfo);
|
|
||||||
bufferUniformDesc_uGradientInfo.mappedAtCreation = false;
|
|
||||||
uBufferGradientInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uGradientInfo);
|
|
||||||
assert(uBufferGradientInfo);
|
|
||||||
|
|
||||||
// bind group entry @binding(0) uMatrix
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uMatrix{};
|
|
||||||
bindGroupEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupEntry_uMatrix.buffer = uBufferMatrix;
|
|
||||||
bindGroupEntry_uMatrix.offset = 0;
|
|
||||||
bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bindGroupEntry_uMatrix.sampler = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.textureView = nullptr;
|
|
||||||
// bind group entry @binding(1) uGradientInfo
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uGradientInfo{};
|
|
||||||
bindGroupEntry_uGradientInfo.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uGradientInfo.binding = 1;
|
|
||||||
bindGroupEntry_uGradientInfo.buffer = uBufferGradientInfo;
|
|
||||||
bindGroupEntry_uGradientInfo.offset = 0;
|
|
||||||
bindGroupEntry_uGradientInfo.size = sizeof(WgPipelineRadialGradientInfo);
|
|
||||||
bindGroupEntry_uGradientInfo.sampler = nullptr;
|
|
||||||
bindGroupEntry_uGradientInfo.textureView = nullptr;
|
|
||||||
// bind group entries
|
|
||||||
WGPUBindGroupEntry bindGroupEntries[] {
|
|
||||||
bindGroupEntry_uMatrix, // @binding(0) uMatrix
|
|
||||||
bindGroupEntry_uGradientInfo // @binding(1) uGradientInfo
|
|
||||||
};
|
|
||||||
// bind group descriptor
|
|
||||||
WGPUBindGroupDescriptor bindGroupDescPipeline{};
|
|
||||||
bindGroupDescPipeline.nextInChain = nullptr;
|
|
||||||
bindGroupDescPipeline.label = "The binding group pipeline radial";
|
|
||||||
bindGroupDescPipeline.layout = pipelinePipelineRadial.mBindGroupLayout;
|
|
||||||
bindGroupDescPipeline.entryCount = 2;
|
|
||||||
bindGroupDescPipeline.entries = bindGroupEntries;
|
|
||||||
mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline);
|
|
||||||
assert(mBindGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupRadial::release() {
|
|
||||||
if (uBufferGradientInfo) {
|
|
||||||
wgpuBufferDestroy(uBufferGradientInfo);
|
|
||||||
wgpuBufferRelease(uBufferGradientInfo);
|
|
||||||
uBufferGradientInfo = nullptr;
|
|
||||||
}
|
|
||||||
if (uBufferMatrix) {
|
|
||||||
wgpuBufferDestroy(uBufferMatrix);
|
|
||||||
wgpuBufferRelease(uBufferMatrix);
|
|
||||||
uBufferMatrix = nullptr;
|
|
||||||
}
|
|
||||||
if (mBindGroup) {
|
|
||||||
wgpuBindGroupRelease(mBindGroup);
|
|
||||||
mBindGroup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupRadial::update(WGPUQueue queue, WgPipelineDataRadial& pipelineDataRadial) {
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataRadial.uMatrix, sizeof(pipelineDataRadial.uMatrix));
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferGradientInfo, 0, &pipelineDataRadial.uGradientInfo, sizeof(pipelineDataRadial.uGradientInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineRadial
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineRadial::initialize(WGPUDevice device) {
|
|
||||||
// bind group layout group 0
|
|
||||||
// bind group layout descriptor @group(0) @binding(0) uMatrix
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{};
|
|
||||||
bindGroupLayoutEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout descriptor @group(0) @binding(1) uColorInfo
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{};
|
|
||||||
bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.binding = 1;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout entries @group(0)
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
|
||||||
bindGroupLayoutEntry_uMatrix,
|
|
||||||
bindGroupLayoutEntry_uColorInfo
|
|
||||||
};
|
|
||||||
// bind group layout descriptor scene @group(0)
|
|
||||||
WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{};
|
|
||||||
bindGroupLayoutDesc.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutDesc.label = "Bind group layout pipeline radial";
|
|
||||||
bindGroupLayoutDesc.entryCount = 2;
|
|
||||||
bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding
|
|
||||||
mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
|
|
||||||
assert(mBindGroupLayout);
|
|
||||||
|
|
||||||
// pipeline layout
|
|
||||||
|
|
||||||
// bind group layout descriptors
|
|
||||||
WGPUBindGroupLayout mBindGroupLayouts[] {
|
|
||||||
mBindGroupLayout
|
|
||||||
};
|
|
||||||
// pipeline layout descriptor
|
|
||||||
WGPUPipelineLayoutDescriptor pipelineLayoutDesc{};
|
|
||||||
pipelineLayoutDesc.nextInChain = nullptr;
|
|
||||||
pipelineLayoutDesc.label = "Pipeline pipeline layout radial";
|
|
||||||
pipelineLayoutDesc.bindGroupLayoutCount = 1;
|
|
||||||
pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts;
|
|
||||||
mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
|
|
||||||
assert(mPipelineLayout);
|
|
||||||
|
|
||||||
// depth stencil state
|
|
||||||
WGPUDepthStencilState depthStencilState{};
|
|
||||||
depthStencilState.nextInChain = nullptr;
|
|
||||||
depthStencilState.format = WGPUTextureFormat_Stencil8;
|
|
||||||
depthStencilState.depthWriteEnabled = false;
|
|
||||||
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
|
||||||
// depthStencilState.stencilFront
|
|
||||||
depthStencilState.stencilFront.compare = WGPUCompareFunction_NotEqual;
|
|
||||||
depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// depthStencilState.stencilBack
|
|
||||||
depthStencilState.stencilBack.compare = WGPUCompareFunction_NotEqual;
|
|
||||||
depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// stencil mask
|
|
||||||
depthStencilState.stencilReadMask = 0xFFFFFFFF;
|
|
||||||
depthStencilState.stencilWriteMask = 0xFFFFFFFF;
|
|
||||||
// depth bias
|
|
||||||
depthStencilState.depthBias = 0;
|
|
||||||
depthStencilState.depthBiasSlopeScale = 0.0f;
|
|
||||||
depthStencilState.depthBiasClamp = 0.0f;
|
|
||||||
|
|
||||||
// shader module wgsl descriptor
|
|
||||||
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
|
|
||||||
shaderModuleWGSLDesc.chain.next = nullptr;
|
|
||||||
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
|
||||||
shaderModuleWGSLDesc.code = cShaderSource_PipelineRadial;
|
|
||||||
// shader module descriptor
|
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc{};
|
|
||||||
shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain;
|
|
||||||
shaderModuleDesc.label = "The shader module pipeline radial";
|
|
||||||
shaderModuleDesc.hintCount = 0;
|
|
||||||
shaderModuleDesc.hints = nullptr;
|
|
||||||
mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
|
||||||
assert(mShaderModule);
|
|
||||||
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexAttribute vertexAttributes[] = {
|
|
||||||
{ WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position
|
|
||||||
};
|
|
||||||
// vertex buffer layout
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayout{};
|
|
||||||
vertexBufferLayout.arrayStride = sizeof(float) * 2; // position
|
|
||||||
vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex;
|
|
||||||
vertexBufferLayout.attributeCount = 1; // position
|
|
||||||
vertexBufferLayout.attributes = vertexAttributes;
|
|
||||||
|
|
||||||
// blend state
|
|
||||||
WGPUBlendState blendState{};
|
|
||||||
// blendState.color
|
|
||||||
blendState.color.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
|
||||||
// blendState.alpha
|
|
||||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.alpha.srcFactor = WGPUBlendFactor_Zero;
|
|
||||||
blendState.alpha.dstFactor = WGPUBlendFactor_One;
|
|
||||||
|
|
||||||
// color target state (WGPUTextureFormat_BGRA8UnormSrgb)
|
|
||||||
WGPUColorTargetState colorTargetState0{};
|
|
||||||
colorTargetState0.nextInChain = nullptr;
|
|
||||||
colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm;
|
|
||||||
//colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb;
|
|
||||||
colorTargetState0.blend = &blendState;
|
|
||||||
colorTargetState0.writeMask = WGPUColorWriteMask_All;
|
|
||||||
// color target states
|
|
||||||
WGPUColorTargetState colorTargetStates[] = {
|
|
||||||
colorTargetState0
|
|
||||||
};
|
|
||||||
// fragmanet state
|
|
||||||
WGPUFragmentState fragmentState{};
|
|
||||||
fragmentState.nextInChain = nullptr;
|
|
||||||
fragmentState.module = mShaderModule;
|
|
||||||
fragmentState.entryPoint = "fs_main";
|
|
||||||
fragmentState.constantCount = 0;
|
|
||||||
fragmentState.constants = nullptr;
|
|
||||||
fragmentState.targetCount = 1;
|
|
||||||
fragmentState.targets = colorTargetStates; // render target index
|
|
||||||
|
|
||||||
// render pipeline descriptor
|
|
||||||
WGPURenderPipelineDescriptor renderPipelineDesc{};
|
|
||||||
renderPipelineDesc.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.label = "Render pipeline pipeline radial";
|
|
||||||
// renderPipelineDesc.layout
|
|
||||||
renderPipelineDesc.layout = mPipelineLayout;
|
|
||||||
// renderPipelineDesc.vertex
|
|
||||||
renderPipelineDesc.vertex.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.vertex.module = mShaderModule;
|
|
||||||
renderPipelineDesc.vertex.entryPoint = "vs_main";
|
|
||||||
renderPipelineDesc.vertex.constantCount = 0;
|
|
||||||
renderPipelineDesc.vertex.constants = nullptr;
|
|
||||||
renderPipelineDesc.vertex.bufferCount = 1;
|
|
||||||
renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index
|
|
||||||
// renderPipelineDesc.primitive
|
|
||||||
renderPipelineDesc.primitive.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
|
||||||
renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
|
|
||||||
renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW;
|
|
||||||
renderPipelineDesc.primitive.cullMode = WGPUCullMode_None;
|
|
||||||
// renderPipelineDesc.depthStencil
|
|
||||||
renderPipelineDesc.depthStencil = &depthStencilState;
|
|
||||||
// renderPipelineDesc.multisample
|
|
||||||
renderPipelineDesc.multisample.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.multisample.count = 1;
|
|
||||||
renderPipelineDesc.multisample.mask = 0xFFFFFFFF;
|
|
||||||
renderPipelineDesc.multisample.alphaToCoverageEnabled = false;
|
|
||||||
// renderPipelineDesc.fragment
|
|
||||||
renderPipelineDesc.fragment = &fragmentState;
|
|
||||||
mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
|
||||||
assert(mRenderPipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineRadial::release() {
|
|
||||||
wgpuRenderPipelineRelease(mRenderPipeline);
|
|
||||||
wgpuShaderModuleRelease(mShaderModule);
|
|
||||||
wgpuPipelineLayoutRelease(mPipelineLayout);
|
|
||||||
wgpuBindGroupLayoutRelease(mBindGroupLayout);
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TVG_WG_PIPELINE_RADIAL_H_
|
|
||||||
#define _TVG_WG_PIPELINE_RADIAL_H_
|
|
||||||
|
|
||||||
#include "tvgWgPipelineBase.h"
|
|
||||||
|
|
||||||
class WgPipelineRadial;
|
|
||||||
|
|
||||||
#define MAX_RADIAL_GRADIENT_STOPS 4
|
|
||||||
struct WgPipelineRadialGradientInfo {
|
|
||||||
alignas(16) float nStops[4]{};
|
|
||||||
alignas(16) float centerPos[2]{};
|
|
||||||
alignas(8) float radius[2]{};
|
|
||||||
alignas(8) float stopPoints[MAX_RADIAL_GRADIENT_STOPS]{};
|
|
||||||
alignas(16) float stopColors[4 * MAX_RADIAL_GRADIENT_STOPS]{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WgPipelineDataRadial: WgPipelineData {
|
|
||||||
WgPipelineRadialGradientInfo uGradientInfo{}; // @binding(1)
|
|
||||||
|
|
||||||
void updateGradient(RadialGradient* radialGradient);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineBindGroupRadial: public WgPipelineBindGroup {
|
|
||||||
private:
|
|
||||||
WGPUBuffer uBufferGradientInfo{}; // @binding(1)
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device, WgPipelineRadial& pipelinePipelineRadial);
|
|
||||||
void release();
|
|
||||||
|
|
||||||
void update(WGPUQueue mQueue, WgPipelineDataRadial& pipelineDataRadial);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineRadial: public WgPipelineBase {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device) override;
|
|
||||||
void release() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_TVG_WG_PIPELINE_RADIAL_H_
|
|
|
@ -1,289 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tvgWgPipelineSolid.h"
|
|
||||||
#include "tvgWgShaderSrc.h"
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineDataSolid
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineDataSolid::updateColor(const uint8_t* color) {
|
|
||||||
uColorInfo.color[0] = color[0] / 255.0f; // red
|
|
||||||
uColorInfo.color[1] = color[1] / 255.0f; // green
|
|
||||||
uColorInfo.color[2] = color[2] / 255.0f; // blue
|
|
||||||
uColorInfo.color[3] = color[3] / 255.0f; // alpha
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupSolid
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineBindGroupSolid::initialize(WGPUDevice device, WgPipelineSolid& pipelinePipelineSolid) {
|
|
||||||
// buffer uniform uMatrix
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uMatrix{};
|
|
||||||
bufferUniformDesc_uMatrix.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline solid uMatrix";
|
|
||||||
bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bufferUniformDesc_uMatrix.mappedAtCreation = false;
|
|
||||||
uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix);
|
|
||||||
assert(uBufferMatrix);
|
|
||||||
// buffer uniform uColorInfo
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uColorInfo{};
|
|
||||||
bufferUniformDesc_uColorInfo.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uColorInfo.label = "Buffer uniform pipeline solid uColorInfo";
|
|
||||||
bufferUniformDesc_uColorInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uColorInfo.size = sizeof(WgPipelineSolidColorInfo);
|
|
||||||
bufferUniformDesc_uColorInfo.mappedAtCreation = false;
|
|
||||||
uBufferColorInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uColorInfo);
|
|
||||||
assert(uBufferColorInfo);
|
|
||||||
|
|
||||||
// bind group entry @binding(0) uMatrix
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uMatrix{};
|
|
||||||
bindGroupEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupEntry_uMatrix.buffer = uBufferMatrix;
|
|
||||||
bindGroupEntry_uMatrix.offset = 0;
|
|
||||||
bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bindGroupEntry_uMatrix.sampler = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.textureView = nullptr;
|
|
||||||
// bind group entry @binding(1) uColorInfo
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uColorInfo{};
|
|
||||||
bindGroupEntry_uColorInfo.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uColorInfo.binding = 1;
|
|
||||||
bindGroupEntry_uColorInfo.buffer = uBufferColorInfo;
|
|
||||||
bindGroupEntry_uColorInfo.offset = 0;
|
|
||||||
bindGroupEntry_uColorInfo.size = sizeof(WgPipelineSolidColorInfo);
|
|
||||||
bindGroupEntry_uColorInfo.sampler = nullptr;
|
|
||||||
bindGroupEntry_uColorInfo.textureView = nullptr;
|
|
||||||
// bind group entries
|
|
||||||
WGPUBindGroupEntry bindGroupEntries[] {
|
|
||||||
bindGroupEntry_uMatrix, // @binding(0) uMatrix
|
|
||||||
bindGroupEntry_uColorInfo // @binding(1) uColorInfo
|
|
||||||
};
|
|
||||||
// bind group descriptor
|
|
||||||
WGPUBindGroupDescriptor bindGroupDescPipeline{};
|
|
||||||
bindGroupDescPipeline.nextInChain = nullptr;
|
|
||||||
bindGroupDescPipeline.label = "The binding group pipeline solid";
|
|
||||||
bindGroupDescPipeline.layout = pipelinePipelineSolid.mBindGroupLayout;
|
|
||||||
bindGroupDescPipeline.entryCount = 2;
|
|
||||||
bindGroupDescPipeline.entries = bindGroupEntries;
|
|
||||||
mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline);
|
|
||||||
assert(mBindGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupSolid::release() {
|
|
||||||
if (uBufferColorInfo) {
|
|
||||||
wgpuBufferDestroy(uBufferColorInfo);
|
|
||||||
wgpuBufferRelease(uBufferColorInfo);
|
|
||||||
uBufferColorInfo = nullptr;
|
|
||||||
}
|
|
||||||
if (uBufferMatrix) {
|
|
||||||
wgpuBufferDestroy(uBufferMatrix);
|
|
||||||
wgpuBufferRelease(uBufferMatrix);
|
|
||||||
uBufferMatrix = nullptr;
|
|
||||||
}
|
|
||||||
if (mBindGroup) {
|
|
||||||
wgpuBindGroupRelease(mBindGroup);
|
|
||||||
mBindGroup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupSolid::update(WGPUQueue queue, WgPipelineDataSolid& pipelineDataSolid) {
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataSolid.uMatrix, sizeof(pipelineDataSolid.uMatrix));
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferColorInfo, 0, &pipelineDataSolid.uColorInfo, sizeof(pipelineDataSolid.uColorInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineSolid
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineSolid::initialize(WGPUDevice device) {
|
|
||||||
// bind group layout group 0
|
|
||||||
// bind group layout descriptor @group(0) @binding(0) uMatrix
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{};
|
|
||||||
bindGroupLayoutEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout descriptor @group(0) @binding(1) uColorInfo
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{};
|
|
||||||
bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.binding = 1;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout entries @group(0)
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
|
||||||
bindGroupLayoutEntry_uMatrix,
|
|
||||||
bindGroupLayoutEntry_uColorInfo
|
|
||||||
};
|
|
||||||
// bind group layout descriptor scene @group(0)
|
|
||||||
WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{};
|
|
||||||
bindGroupLayoutDesc.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutDesc.label = "Bind group layout pipeline solid";
|
|
||||||
bindGroupLayoutDesc.entryCount = 2;
|
|
||||||
bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding
|
|
||||||
mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
|
|
||||||
assert(mBindGroupLayout);
|
|
||||||
|
|
||||||
// pipeline layout
|
|
||||||
|
|
||||||
// bind group layout descriptors
|
|
||||||
WGPUBindGroupLayout mBindGroupLayouts[] {
|
|
||||||
mBindGroupLayout
|
|
||||||
};
|
|
||||||
// pipeline layout descriptor
|
|
||||||
WGPUPipelineLayoutDescriptor pipelineLayoutDesc{};
|
|
||||||
pipelineLayoutDesc.nextInChain = nullptr;
|
|
||||||
pipelineLayoutDesc.label = "Pipeline pipeline layout solid";
|
|
||||||
pipelineLayoutDesc.bindGroupLayoutCount = 1;
|
|
||||||
pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts;
|
|
||||||
mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
|
|
||||||
assert(mPipelineLayout);
|
|
||||||
|
|
||||||
// depth stencil state
|
|
||||||
WGPUDepthStencilState depthStencilState{};
|
|
||||||
depthStencilState.nextInChain = nullptr;
|
|
||||||
depthStencilState.format = WGPUTextureFormat_Stencil8;
|
|
||||||
depthStencilState.depthWriteEnabled = false;
|
|
||||||
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
|
||||||
// depthStencilState.stencilFront
|
|
||||||
depthStencilState.stencilFront.compare = WGPUCompareFunction_NotEqual;
|
|
||||||
depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// depthStencilState.stencilBack
|
|
||||||
depthStencilState.stencilBack.compare = WGPUCompareFunction_NotEqual;
|
|
||||||
depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero;
|
|
||||||
depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero;
|
|
||||||
// stencil mask
|
|
||||||
depthStencilState.stencilReadMask = 0xFFFFFFFF;
|
|
||||||
depthStencilState.stencilWriteMask = 0xFFFFFFFF;
|
|
||||||
// depth bias
|
|
||||||
depthStencilState.depthBias = 0;
|
|
||||||
depthStencilState.depthBiasSlopeScale = 0.0f;
|
|
||||||
depthStencilState.depthBiasClamp = 0.0f;
|
|
||||||
|
|
||||||
// shader module wgsl descriptor
|
|
||||||
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
|
|
||||||
shaderModuleWGSLDesc.chain.next = nullptr;
|
|
||||||
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
|
||||||
shaderModuleWGSLDesc.code = cShaderSource_PipelineSolid;
|
|
||||||
// shader module descriptor
|
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc{};
|
|
||||||
shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain;
|
|
||||||
shaderModuleDesc.label = "The shader module pipeline solid";
|
|
||||||
shaderModuleDesc.hintCount = 0;
|
|
||||||
shaderModuleDesc.hints = nullptr;
|
|
||||||
mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
|
||||||
assert(mShaderModule);
|
|
||||||
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexAttribute vertexAttributes[] = {
|
|
||||||
{ WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position
|
|
||||||
};
|
|
||||||
// vertex buffer layout
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayout{};
|
|
||||||
vertexBufferLayout.arrayStride = sizeof(float) * 2; // position
|
|
||||||
vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex;
|
|
||||||
vertexBufferLayout.attributeCount = 1; // position
|
|
||||||
vertexBufferLayout.attributes = vertexAttributes;
|
|
||||||
|
|
||||||
// blend state
|
|
||||||
WGPUBlendState blendState{};
|
|
||||||
// blendState.color
|
|
||||||
blendState.color.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
|
||||||
// blendState.alpha
|
|
||||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.alpha.srcFactor = WGPUBlendFactor_Zero;
|
|
||||||
blendState.alpha.dstFactor = WGPUBlendFactor_One;
|
|
||||||
|
|
||||||
// color target state (WGPUTextureFormat_BGRA8UnormSrgb)
|
|
||||||
WGPUColorTargetState colorTargetState0{};
|
|
||||||
colorTargetState0.nextInChain = nullptr;
|
|
||||||
colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm;
|
|
||||||
//colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb;
|
|
||||||
colorTargetState0.blend = &blendState;
|
|
||||||
colorTargetState0.writeMask = WGPUColorWriteMask_All;
|
|
||||||
// color target states
|
|
||||||
WGPUColorTargetState colorTargetStates[] = {
|
|
||||||
colorTargetState0
|
|
||||||
};
|
|
||||||
// fragmanet state
|
|
||||||
WGPUFragmentState fragmentState{};
|
|
||||||
fragmentState.nextInChain = nullptr;
|
|
||||||
fragmentState.module = mShaderModule;
|
|
||||||
fragmentState.entryPoint = "fs_main";
|
|
||||||
fragmentState.constantCount = 0;
|
|
||||||
fragmentState.constants = nullptr;
|
|
||||||
fragmentState.targetCount = 1;
|
|
||||||
fragmentState.targets = colorTargetStates; // render target index
|
|
||||||
|
|
||||||
// render pipeline descriptor
|
|
||||||
WGPURenderPipelineDescriptor renderPipelineDesc{};
|
|
||||||
renderPipelineDesc.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.label = "Render pipeline pipeline solid";
|
|
||||||
// renderPipelineDesc.layout
|
|
||||||
renderPipelineDesc.layout = mPipelineLayout;
|
|
||||||
// renderPipelineDesc.vertex
|
|
||||||
renderPipelineDesc.vertex.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.vertex.module = mShaderModule;
|
|
||||||
renderPipelineDesc.vertex.entryPoint = "vs_main";
|
|
||||||
renderPipelineDesc.vertex.constantCount = 0;
|
|
||||||
renderPipelineDesc.vertex.constants = nullptr;
|
|
||||||
renderPipelineDesc.vertex.bufferCount = 1;
|
|
||||||
renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index
|
|
||||||
// renderPipelineDesc.primitive
|
|
||||||
renderPipelineDesc.primitive.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
|
||||||
renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
|
|
||||||
renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW;
|
|
||||||
renderPipelineDesc.primitive.cullMode = WGPUCullMode_None;
|
|
||||||
// renderPipelineDesc.depthStencil
|
|
||||||
renderPipelineDesc.depthStencil = &depthStencilState;
|
|
||||||
// renderPipelineDesc.multisample
|
|
||||||
renderPipelineDesc.multisample.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.multisample.count = 1;
|
|
||||||
renderPipelineDesc.multisample.mask = 0xFFFFFFFF;
|
|
||||||
renderPipelineDesc.multisample.alphaToCoverageEnabled = false;
|
|
||||||
// renderPipelineDesc.fragment
|
|
||||||
renderPipelineDesc.fragment = &fragmentState;
|
|
||||||
mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
|
||||||
assert(mRenderPipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineSolid::release() {
|
|
||||||
wgpuRenderPipelineRelease(mRenderPipeline);
|
|
||||||
wgpuShaderModuleRelease(mShaderModule);
|
|
||||||
wgpuPipelineLayoutRelease(mPipelineLayout);
|
|
||||||
wgpuBindGroupLayoutRelease(mBindGroupLayout);
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TVG_WG_PIPELINE_SOLID_H_
|
|
||||||
#define _TVG_WG_PIPELINE_SOLID_H_
|
|
||||||
|
|
||||||
#include "tvgWgPipelineBase.h"
|
|
||||||
|
|
||||||
class WgPipelineSolid;
|
|
||||||
|
|
||||||
struct WgPipelineSolidColorInfo {
|
|
||||||
float color[4]{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WgPipelineDataSolid: WgPipelineData {
|
|
||||||
WgPipelineSolidColorInfo uColorInfo{}; // @binding(1)
|
|
||||||
|
|
||||||
void updateColor(const uint8_t* color);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineBindGroupSolid: public WgPipelineBindGroup {
|
|
||||||
private:
|
|
||||||
WGPUBuffer uBufferColorInfo{}; // @binding(1)
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device, WgPipelineSolid& pipelinePipelineSolid);
|
|
||||||
void release();
|
|
||||||
|
|
||||||
void update(WGPUQueue mQueue, WgPipelineDataSolid& pipelineDataSolid);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineSolid: public WgPipelineBase {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device) override;
|
|
||||||
void release() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_TVG_WG_PIPELINE_SOLID_H_
|
|
|
@ -1,243 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tvgWgPipelineStroke.h"
|
|
||||||
#include "tvgWgShaderSrc.h"
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineBindGroupStroke
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineBindGroupStroke::initialize(WGPUDevice device, WgPipelineStroke& pipelinePipelineStroke) {
|
|
||||||
// buffer uniform uMatrix
|
|
||||||
WGPUBufferDescriptor bufferUniformDesc_uMatrix{};
|
|
||||||
bufferUniformDesc_uMatrix.nextInChain = nullptr;
|
|
||||||
bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline Stroke uMatrix";
|
|
||||||
bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
|
|
||||||
bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bufferUniformDesc_uMatrix.mappedAtCreation = false;
|
|
||||||
uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix);
|
|
||||||
assert(uBufferMatrix);
|
|
||||||
|
|
||||||
// bind group entry @binding(0) uMatrix
|
|
||||||
WGPUBindGroupEntry bindGroupEntry_uMatrix{};
|
|
||||||
bindGroupEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupEntry_uMatrix.buffer = uBufferMatrix;
|
|
||||||
bindGroupEntry_uMatrix.offset = 0;
|
|
||||||
bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix);
|
|
||||||
bindGroupEntry_uMatrix.sampler = nullptr;
|
|
||||||
bindGroupEntry_uMatrix.textureView = nullptr;
|
|
||||||
// bind group entries
|
|
||||||
WGPUBindGroupEntry bindGroupEntries[] {
|
|
||||||
bindGroupEntry_uMatrix // @binding(0) uMatrix
|
|
||||||
};
|
|
||||||
// bind group descriptor
|
|
||||||
WGPUBindGroupDescriptor bindGroupDescPipeline{};
|
|
||||||
bindGroupDescPipeline.nextInChain = nullptr;
|
|
||||||
bindGroupDescPipeline.label = "The binding group pipeline stroke";
|
|
||||||
bindGroupDescPipeline.layout = pipelinePipelineStroke.mBindGroupLayout;
|
|
||||||
bindGroupDescPipeline.entryCount = 1;
|
|
||||||
bindGroupDescPipeline.entries = bindGroupEntries;
|
|
||||||
mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline);
|
|
||||||
assert(mBindGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupStroke::release() {
|
|
||||||
if (uBufferMatrix) {
|
|
||||||
wgpuBufferDestroy(uBufferMatrix);
|
|
||||||
wgpuBufferRelease(uBufferMatrix);
|
|
||||||
uBufferMatrix = nullptr;
|
|
||||||
}
|
|
||||||
if (mBindGroup) {
|
|
||||||
wgpuBindGroupRelease(mBindGroup);
|
|
||||||
mBindGroup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineBindGroupStroke::update(WGPUQueue queue, WgPipelineDataStroke& pipelineDataStroke) {
|
|
||||||
wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataStroke.uMatrix, sizeof(pipelineDataStroke.uMatrix));
|
|
||||||
}
|
|
||||||
|
|
||||||
//************************************************************************
|
|
||||||
// WgPipelineStroke
|
|
||||||
//************************************************************************
|
|
||||||
|
|
||||||
void WgPipelineStroke::initialize(WGPUDevice device) {
|
|
||||||
// bind group layout group 0
|
|
||||||
// bind group layout descriptor @group(0) @binding(0) uMatrix
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{};
|
|
||||||
bindGroupLayoutEntry_uMatrix.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.binding = 0;
|
|
||||||
bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false;
|
|
||||||
bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0;
|
|
||||||
// bind group layout entries @group(0)
|
|
||||||
WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
|
|
||||||
bindGroupLayoutEntry_uMatrix
|
|
||||||
};
|
|
||||||
// bind group layout descriptor scene @group(0)
|
|
||||||
WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{};
|
|
||||||
bindGroupLayoutDesc.nextInChain = nullptr;
|
|
||||||
bindGroupLayoutDesc.label = "Bind group layout pipeline stroke";
|
|
||||||
bindGroupLayoutDesc.entryCount = 1;
|
|
||||||
bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding
|
|
||||||
mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc);
|
|
||||||
assert(mBindGroupLayout);
|
|
||||||
|
|
||||||
// pipeline layout
|
|
||||||
|
|
||||||
// bind group layout descriptors
|
|
||||||
WGPUBindGroupLayout mBindGroupLayouts[] {
|
|
||||||
mBindGroupLayout
|
|
||||||
};
|
|
||||||
// pipeline layout descriptor
|
|
||||||
WGPUPipelineLayoutDescriptor pipelineLayoutDesc{};
|
|
||||||
pipelineLayoutDesc.nextInChain = nullptr;
|
|
||||||
pipelineLayoutDesc.label = "Pipeline pipeline layout stroke";
|
|
||||||
pipelineLayoutDesc.bindGroupLayoutCount = 1;
|
|
||||||
pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts;
|
|
||||||
mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
|
|
||||||
assert(mPipelineLayout);
|
|
||||||
|
|
||||||
// depth stencil state
|
|
||||||
WGPUDepthStencilState depthStencilState{};
|
|
||||||
depthStencilState.nextInChain = nullptr;
|
|
||||||
depthStencilState.format = WGPUTextureFormat_Stencil8;
|
|
||||||
depthStencilState.depthWriteEnabled = false;
|
|
||||||
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
|
||||||
// depthStencilState.stencilFront
|
|
||||||
depthStencilState.stencilFront.compare = WGPUCompareFunction_Always;
|
|
||||||
depthStencilState.stencilFront.failOp = WGPUStencilOperation_Replace;
|
|
||||||
depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Replace;
|
|
||||||
depthStencilState.stencilFront.passOp = WGPUStencilOperation_Replace;
|
|
||||||
// depthStencilState.stencilBack
|
|
||||||
depthStencilState.stencilBack.compare = WGPUCompareFunction_Always;
|
|
||||||
depthStencilState.stencilBack.failOp = WGPUStencilOperation_Replace;
|
|
||||||
depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Replace;
|
|
||||||
depthStencilState.stencilBack.passOp = WGPUStencilOperation_Replace;
|
|
||||||
// stencil mask
|
|
||||||
depthStencilState.stencilReadMask = 0xFFFFFFFF;
|
|
||||||
depthStencilState.stencilWriteMask = 0xFFFFFFFF;
|
|
||||||
// depth bias
|
|
||||||
depthStencilState.depthBias = 0;
|
|
||||||
depthStencilState.depthBiasSlopeScale = 0.0f;
|
|
||||||
depthStencilState.depthBiasClamp = 0.0f;
|
|
||||||
|
|
||||||
// shader module wgsl descriptor
|
|
||||||
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
|
|
||||||
shaderModuleWGSLDesc.chain.next = nullptr;
|
|
||||||
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
|
||||||
shaderModuleWGSLDesc.code = cShaderSource_PipelineEmpty;
|
|
||||||
// shader module descriptor
|
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc{};
|
|
||||||
shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain;
|
|
||||||
shaderModuleDesc.label = "The shader module pipeline Stroke";
|
|
||||||
shaderModuleDesc.hintCount = 0;
|
|
||||||
shaderModuleDesc.hints = nullptr;
|
|
||||||
mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
|
||||||
assert(mShaderModule);
|
|
||||||
|
|
||||||
// vertex attributes
|
|
||||||
WGPUVertexAttribute vertexAttributes[] = {
|
|
||||||
{ WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position
|
|
||||||
};
|
|
||||||
// vertex buffer layout
|
|
||||||
WGPUVertexBufferLayout vertexBufferLayout{};
|
|
||||||
vertexBufferLayout.arrayStride = sizeof(float) * 2; // position
|
|
||||||
vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex;
|
|
||||||
vertexBufferLayout.attributeCount = 1; // position
|
|
||||||
vertexBufferLayout.attributes = vertexAttributes;
|
|
||||||
|
|
||||||
// blend state
|
|
||||||
WGPUBlendState blendState{};
|
|
||||||
// blendState.color
|
|
||||||
blendState.color.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
|
||||||
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
|
||||||
// blendState.alpha
|
|
||||||
blendState.alpha.operation = WGPUBlendOperation_Add;
|
|
||||||
blendState.alpha.srcFactor = WGPUBlendFactor_Zero;
|
|
||||||
blendState.alpha.dstFactor = WGPUBlendFactor_One;
|
|
||||||
|
|
||||||
// color target state (WGPUTextureFormat_BGRA8UnormSrgb)
|
|
||||||
WGPUColorTargetState colorTargetState0{};
|
|
||||||
colorTargetState0.nextInChain = nullptr;
|
|
||||||
colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm;
|
|
||||||
//colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb;
|
|
||||||
colorTargetState0.blend = &blendState;
|
|
||||||
colorTargetState0.writeMask = WGPUColorWriteMask_All;
|
|
||||||
// color target states
|
|
||||||
WGPUColorTargetState colorTargetStates[] = {
|
|
||||||
colorTargetState0
|
|
||||||
};
|
|
||||||
// fragmanet state
|
|
||||||
WGPUFragmentState fragmentState{};
|
|
||||||
fragmentState.nextInChain = nullptr;
|
|
||||||
fragmentState.module = mShaderModule;
|
|
||||||
fragmentState.entryPoint = "fs_main";
|
|
||||||
fragmentState.constantCount = 0;
|
|
||||||
fragmentState.constants = nullptr;
|
|
||||||
fragmentState.targetCount = 1;
|
|
||||||
fragmentState.targets = colorTargetStates; // render target index
|
|
||||||
|
|
||||||
// render pipeline descriptor
|
|
||||||
WGPURenderPipelineDescriptor renderPipelineDesc{};
|
|
||||||
renderPipelineDesc.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.label = "Render pipeline pipeline stroke";
|
|
||||||
// renderPipelineDesc.layout
|
|
||||||
renderPipelineDesc.layout = mPipelineLayout;
|
|
||||||
// renderPipelineDesc.vertex
|
|
||||||
renderPipelineDesc.vertex.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.vertex.module = mShaderModule;
|
|
||||||
renderPipelineDesc.vertex.entryPoint = "vs_main";
|
|
||||||
renderPipelineDesc.vertex.constantCount = 0;
|
|
||||||
renderPipelineDesc.vertex.constants = nullptr;
|
|
||||||
renderPipelineDesc.vertex.bufferCount = 1;
|
|
||||||
renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index
|
|
||||||
// renderPipelineDesc.primitive
|
|
||||||
renderPipelineDesc.primitive.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
|
||||||
renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
|
|
||||||
renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW;
|
|
||||||
renderPipelineDesc.primitive.cullMode = WGPUCullMode_None;
|
|
||||||
// renderPipelineDesc.depthStencil
|
|
||||||
renderPipelineDesc.depthStencil = &depthStencilState;
|
|
||||||
// renderPipelineDesc.multisample
|
|
||||||
renderPipelineDesc.multisample.nextInChain = nullptr;
|
|
||||||
renderPipelineDesc.multisample.count = 1;
|
|
||||||
renderPipelineDesc.multisample.mask = 0xFFFFFFFF;
|
|
||||||
renderPipelineDesc.multisample.alphaToCoverageEnabled = false;
|
|
||||||
// renderPipelineDesc.fragment
|
|
||||||
renderPipelineDesc.fragment = &fragmentState;
|
|
||||||
mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
|
||||||
assert(mRenderPipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelineStroke::release() {
|
|
||||||
wgpuRenderPipelineRelease(mRenderPipeline);
|
|
||||||
wgpuShaderModuleRelease(mShaderModule);
|
|
||||||
wgpuPipelineLayoutRelease(mPipelineLayout);
|
|
||||||
wgpuBindGroupLayoutRelease(mBindGroupLayout);
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TVG_WG_PIPELINE_STROKE_H_
|
|
||||||
#define _TVG_WG_PIPELINE_STROKE_H_
|
|
||||||
|
|
||||||
#include "tvgWgPipelineBase.h"
|
|
||||||
|
|
||||||
class WgPipelineStroke;
|
|
||||||
|
|
||||||
struct WgPipelineDataStroke: WgPipelineData {};
|
|
||||||
|
|
||||||
class WgPipelineBindGroupStroke: public WgPipelineBindGroup {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device, WgPipelineStroke& pipelinePipelineStroke);
|
|
||||||
void release();
|
|
||||||
|
|
||||||
void update(WGPUQueue mQueue, WgPipelineDataStroke& pipelineDataSolid);
|
|
||||||
};
|
|
||||||
|
|
||||||
class WgPipelineStroke: public WgPipelineBase {
|
|
||||||
public:
|
|
||||||
void initialize(WGPUDevice device) override;
|
|
||||||
void release() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _TVG_WG_PIPELINE_STROKE_H_
|
|
246
src/renderer/wg_engine/tvgWgPipelines.cpp
Normal file
246
src/renderer/wg_engine/tvgWgPipelines.cpp
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tvgWgPipelines.h"
|
||||||
|
#include "tvgWgShaderSrc.h"
|
||||||
|
|
||||||
|
#define ARRAY_ELEMENTS_COUNT(arr) sizeof(arr)/sizeof(arr[0])
|
||||||
|
|
||||||
|
void WgPipelineFillShape::initialize(WGPUDevice device) {
|
||||||
|
// vertex attributes settings
|
||||||
|
WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 };
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[] = {
|
||||||
|
makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// bind groups
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||||
|
WgBindGroupCanvas::getLayout(device),
|
||||||
|
WgBindGroupPaint::getLayout(device)
|
||||||
|
};
|
||||||
|
|
||||||
|
// stencil function
|
||||||
|
WGPUCompareFunction stencilFuncion = WGPUCompareFunction_Always;
|
||||||
|
WGPUStencilOperation stencilOperation = WGPUStencilOperation_Invert;
|
||||||
|
|
||||||
|
// sheder source and labels
|
||||||
|
const char* shaderSource = cShaderSource_PipelineFill;
|
||||||
|
const char* shaderLabel = "The shader fill";
|
||||||
|
const char* pipelineLabel = "The render pipeline fill shape";
|
||||||
|
|
||||||
|
// allocate all pipeline handles
|
||||||
|
allocate(
|
||||||
|
device,
|
||||||
|
vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts),
|
||||||
|
bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts),
|
||||||
|
stencilFuncion, stencilOperation,
|
||||||
|
shaderSource, shaderLabel, pipelineLabel);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgPipelineFillStroke::initialize(WGPUDevice device) {
|
||||||
|
// vertex and buffers settings
|
||||||
|
WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 };
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[] = {
|
||||||
|
makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// bind groups and layouts
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||||
|
WgBindGroupCanvas::getLayout(device),
|
||||||
|
WgBindGroupPaint::getLayout(device)
|
||||||
|
};
|
||||||
|
|
||||||
|
// stencil function
|
||||||
|
WGPUCompareFunction stencilFuncion = WGPUCompareFunction_Always;
|
||||||
|
WGPUStencilOperation stencilOperation = WGPUStencilOperation_Replace;
|
||||||
|
|
||||||
|
// sheder source and labels
|
||||||
|
const char* shaderSource = cShaderSource_PipelineFill;
|
||||||
|
const char* shaderLabel = "The shader fill";
|
||||||
|
const char* pipelineLabel = "The render pipeline fill stroke";
|
||||||
|
|
||||||
|
// allocate all pipeline handles
|
||||||
|
allocate(
|
||||||
|
device,
|
||||||
|
vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts),
|
||||||
|
bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts),
|
||||||
|
stencilFuncion, stencilOperation,
|
||||||
|
shaderSource, shaderLabel, pipelineLabel);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgPipelineSolid::initialize(WGPUDevice device) {
|
||||||
|
// vertex and buffers settings
|
||||||
|
WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 };
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[] = {
|
||||||
|
makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// bind groups and layouts
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||||
|
WgBindGroupCanvas::getLayout(device),
|
||||||
|
WgBindGroupPaint::getLayout(device),
|
||||||
|
WgBindGroupSolidColor::getLayout(device)
|
||||||
|
};
|
||||||
|
|
||||||
|
// stencil function
|
||||||
|
WGPUCompareFunction stencilFuncion = WGPUCompareFunction_NotEqual;
|
||||||
|
WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero;
|
||||||
|
|
||||||
|
// sheder source and labels
|
||||||
|
const char* shaderSource = cShaderSource_PipelineSolid;
|
||||||
|
const char* shaderLabel = "The shader solid color";
|
||||||
|
const char* pipelineLabel = "The render pipeline solid color";
|
||||||
|
|
||||||
|
// allocate all pipeline handles
|
||||||
|
allocate(
|
||||||
|
device,
|
||||||
|
vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts),
|
||||||
|
bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts),
|
||||||
|
stencilFuncion, stencilOperation,
|
||||||
|
shaderSource, shaderLabel, pipelineLabel);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgPipelineLinear::initialize(WGPUDevice device) {
|
||||||
|
// vertex and buffers settings
|
||||||
|
WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 };
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[] = {
|
||||||
|
makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// bind groups and layouts
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||||
|
WgBindGroupCanvas::getLayout(device),
|
||||||
|
WgBindGroupPaint::getLayout(device),
|
||||||
|
WgBindGroupLinearGradient::getLayout(device)
|
||||||
|
};
|
||||||
|
|
||||||
|
// stencil function
|
||||||
|
WGPUCompareFunction stencilFuncion = WGPUCompareFunction_NotEqual;
|
||||||
|
WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero;
|
||||||
|
|
||||||
|
// sheder source and labels
|
||||||
|
const char* shaderSource = cShaderSource_PipelineLinear;
|
||||||
|
const char* shaderLabel = "The shader linear gradient";
|
||||||
|
const char* pipelineLabel = "The render pipeline linear gradient";
|
||||||
|
|
||||||
|
// allocate all pipeline handles
|
||||||
|
allocate(
|
||||||
|
device,
|
||||||
|
vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts),
|
||||||
|
bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts),
|
||||||
|
stencilFuncion, stencilOperation,
|
||||||
|
shaderSource, shaderLabel, pipelineLabel);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgPipelineRadial::initialize(WGPUDevice device) {
|
||||||
|
// vertex and buffers settings
|
||||||
|
WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 };
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[] = {
|
||||||
|
makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// bind groups and layouts
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||||
|
WgBindGroupCanvas::getLayout(device),
|
||||||
|
WgBindGroupPaint::getLayout(device),
|
||||||
|
WgBindGroupRadialGradient::getLayout(device)
|
||||||
|
};
|
||||||
|
|
||||||
|
// stencil function
|
||||||
|
WGPUCompareFunction stencilFuncion = WGPUCompareFunction_NotEqual;
|
||||||
|
WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero;
|
||||||
|
|
||||||
|
// sheder source and labels
|
||||||
|
const char* shaderSource = cShaderSource_PipelineRadial;
|
||||||
|
const char* shaderLabel = "The shader radial gradient";
|
||||||
|
const char* pipelineLabel = "The render pipeline radial gradient";
|
||||||
|
|
||||||
|
// allocate all pipeline handles
|
||||||
|
allocate(
|
||||||
|
device,
|
||||||
|
vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts),
|
||||||
|
bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts),
|
||||||
|
stencilFuncion, stencilOperation,
|
||||||
|
shaderSource, shaderLabel, pipelineLabel);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgPipelineImage::initialize(WGPUDevice device) {
|
||||||
|
// vertex and buffers settings
|
||||||
|
WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 };
|
||||||
|
WGPUVertexAttribute vertexAttributesTex = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 1 };
|
||||||
|
WGPUVertexBufferLayout vertexBufferLayouts[] = {
|
||||||
|
makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2),
|
||||||
|
makeVertexBufferLayout(&vertexAttributesTex, 1, sizeof(float) * 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// bind groups and layouts
|
||||||
|
WGPUBindGroupLayout bindGroupLayouts[] = {
|
||||||
|
WgBindGroupCanvas::getLayout(device),
|
||||||
|
WgBindGroupPaint::getLayout(device),
|
||||||
|
WgBindGroupPicture::getLayout(device)
|
||||||
|
};
|
||||||
|
|
||||||
|
// stencil function
|
||||||
|
WGPUCompareFunction stencilFuncion = WGPUCompareFunction_Always;
|
||||||
|
WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero;
|
||||||
|
|
||||||
|
// sheder source and labels
|
||||||
|
const char* shaderSource = cShaderSource_PipelineImage;
|
||||||
|
const char* shaderLabel = "The shader image";
|
||||||
|
const char* pipelineLabel = "The render pipeline image";
|
||||||
|
|
||||||
|
// allocate all pipeline handles
|
||||||
|
allocate(
|
||||||
|
device,
|
||||||
|
vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts),
|
||||||
|
bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts),
|
||||||
|
stencilFuncion, stencilOperation,
|
||||||
|
shaderSource, shaderLabel, pipelineLabel);
|
||||||
|
};
|
||||||
|
|
||||||
|
//************************************************************************
|
||||||
|
// pipelines
|
||||||
|
//************************************************************************
|
||||||
|
|
||||||
|
void WgPipelines::initialize(WGPUDevice device) {
|
||||||
|
mPipelineFillShape.initialize(device);
|
||||||
|
mPipelineFillStroke.initialize(device);
|
||||||
|
mPipelineSolid.initialize(device);
|
||||||
|
mPipelineLinear.initialize(device);
|
||||||
|
mPipelineRadial.initialize(device);
|
||||||
|
mPipelineImage.initialize(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgPipelines::release() {
|
||||||
|
WgBindGroupCompose::releaseLayout();
|
||||||
|
WgBindGroupPicture::releaseLayout();
|
||||||
|
WgBindGroupRadialGradient::releaseLayout();
|
||||||
|
WgBindGroupLinearGradient::releaseLayout();
|
||||||
|
WgBindGroupSolidColor::releaseLayout();
|
||||||
|
WgBindGroupCanvas::releaseLayout();
|
||||||
|
mPipelineImage.release();
|
||||||
|
mPipelineRadial.release();
|
||||||
|
mPipelineLinear.release();
|
||||||
|
mPipelineSolid.release();
|
||||||
|
mPipelineFillStroke.release();
|
||||||
|
mPipelineFillShape.release();
|
||||||
|
}
|
114
src/renderer/wg_engine/tvgWgPipelines.h
Normal file
114
src/renderer/wg_engine/tvgWgPipelines.h
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TVG_WG_PIPELINES_H_
|
||||||
|
#define _TVG_WG_PIPELINES_H_
|
||||||
|
|
||||||
|
#include "tvgWgBindGroups.h"
|
||||||
|
|
||||||
|
struct WgPipelineFillShape: public WgPipeline {
|
||||||
|
void initialize(WGPUDevice device) override;
|
||||||
|
void use(WGPURenderPassEncoder encoder,
|
||||||
|
WgBindGroupCanvas& groupCanvas,
|
||||||
|
WgBindGroupPaint& groupPaint) {
|
||||||
|
set(encoder);
|
||||||
|
groupCanvas.set(encoder, 0);
|
||||||
|
groupPaint.set(encoder, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WgPipelineFillStroke: public WgPipeline {
|
||||||
|
void initialize(WGPUDevice device) override;
|
||||||
|
void use(WGPURenderPassEncoder encoder,
|
||||||
|
WgBindGroupCanvas& groupCanvas,
|
||||||
|
WgBindGroupPaint& groupPaint) {
|
||||||
|
set(encoder);
|
||||||
|
groupCanvas.set(encoder, 0);
|
||||||
|
groupPaint.set(encoder, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WgPipelineSolid: public WgPipeline {
|
||||||
|
void initialize(WGPUDevice device) override;
|
||||||
|
void use(WGPURenderPassEncoder encoder,
|
||||||
|
WgBindGroupCanvas& groupCanvas,
|
||||||
|
WgBindGroupPaint& groupPaint,
|
||||||
|
WgBindGroupSolidColor& groupSolid) {
|
||||||
|
set(encoder);
|
||||||
|
groupCanvas.set(encoder, 0);
|
||||||
|
groupPaint.set(encoder, 1);
|
||||||
|
groupSolid.set(encoder, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WgPipelineLinear: public WgPipeline {
|
||||||
|
void initialize(WGPUDevice device) override;
|
||||||
|
void use(WGPURenderPassEncoder encoder,
|
||||||
|
WgBindGroupCanvas& groupCanvas,
|
||||||
|
WgBindGroupPaint& groupPaint,
|
||||||
|
WgBindGroupLinearGradient& groupLinear) {
|
||||||
|
set(encoder);
|
||||||
|
groupCanvas.set(encoder, 0);
|
||||||
|
groupPaint.set(encoder, 1);
|
||||||
|
groupLinear.set(encoder, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WgPipelineRadial: public WgPipeline {
|
||||||
|
void initialize(WGPUDevice device) override;
|
||||||
|
void use(WGPURenderPassEncoder encoder,
|
||||||
|
WgBindGroupCanvas& groupCanvas,
|
||||||
|
WgBindGroupPaint& groupPaint,
|
||||||
|
WgBindGroupRadialGradient& groupRadial) {
|
||||||
|
set(encoder);
|
||||||
|
groupCanvas.set(encoder, 0);
|
||||||
|
groupPaint.set(encoder, 1);
|
||||||
|
groupRadial.set(encoder, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WgPipelineImage: public WgPipeline {
|
||||||
|
void initialize(WGPUDevice device) override;
|
||||||
|
void use(WGPURenderPassEncoder encoder,
|
||||||
|
WgBindGroupCanvas& groupCanvas,
|
||||||
|
WgBindGroupPaint& groupPaint,
|
||||||
|
WgBindGroupPicture& groupPicture) {
|
||||||
|
set(encoder);
|
||||||
|
groupCanvas.set(encoder, 0);
|
||||||
|
groupPaint.set(encoder, 1);
|
||||||
|
groupPicture.set(encoder, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WgPipelines {
|
||||||
|
WgPipelineFillShape mPipelineFillShape;
|
||||||
|
WgPipelineFillStroke mPipelineFillStroke;
|
||||||
|
WgPipelineSolid mPipelineSolid;
|
||||||
|
WgPipelineLinear mPipelineLinear;
|
||||||
|
WgPipelineRadial mPipelineRadial;
|
||||||
|
WgPipelineImage mPipelineImage;
|
||||||
|
|
||||||
|
void initialize(WGPUDevice device);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _TVG_WG_PIPELINES_H_
|
|
@ -108,51 +108,121 @@ void WgGeometryData::release() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//***********************************************************************
|
||||||
|
// WgImageData
|
||||||
|
//***********************************************************************
|
||||||
|
|
||||||
|
void WgImageData::update(WGPUDevice device, WGPUQueue queue, Surface* surface) {
|
||||||
|
release();
|
||||||
|
// sampler descriptor
|
||||||
|
WGPUSamplerDescriptor samplerDesc{};
|
||||||
|
samplerDesc.nextInChain = nullptr;
|
||||||
|
samplerDesc.label = "The shape sampler";
|
||||||
|
samplerDesc.addressModeU = WGPUAddressMode_ClampToEdge;
|
||||||
|
samplerDesc.addressModeV = WGPUAddressMode_ClampToEdge;
|
||||||
|
samplerDesc.addressModeW = WGPUAddressMode_ClampToEdge;
|
||||||
|
samplerDesc.magFilter = WGPUFilterMode_Nearest;
|
||||||
|
samplerDesc.minFilter = WGPUFilterMode_Nearest;
|
||||||
|
samplerDesc.mipmapFilter = WGPUMipmapFilterMode_Nearest;
|
||||||
|
samplerDesc.lodMinClamp = 0.0f;
|
||||||
|
samplerDesc.lodMaxClamp = 32.0f;
|
||||||
|
samplerDesc.compare = WGPUCompareFunction_Undefined;
|
||||||
|
samplerDesc.maxAnisotropy = 1;
|
||||||
|
mSampler = wgpuDeviceCreateSampler(device, &samplerDesc);
|
||||||
|
assert(mSampler);
|
||||||
|
// texture descriptor
|
||||||
|
WGPUTextureDescriptor textureDesc{};
|
||||||
|
textureDesc.nextInChain = nullptr;
|
||||||
|
textureDesc.label = "The shape texture";
|
||||||
|
textureDesc.usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst;
|
||||||
|
textureDesc.dimension = WGPUTextureDimension_2D;
|
||||||
|
textureDesc.size = { surface->w, surface->h, 1 };
|
||||||
|
textureDesc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||||
|
textureDesc.mipLevelCount = 1;
|
||||||
|
textureDesc.sampleCount = 1;
|
||||||
|
textureDesc.viewFormatCount = 0;
|
||||||
|
textureDesc.viewFormats = nullptr;
|
||||||
|
mTexture = wgpuDeviceCreateTexture(device, &textureDesc);
|
||||||
|
assert(mTexture);
|
||||||
|
// texture view descriptor
|
||||||
|
WGPUTextureViewDescriptor textureViewDesc{};
|
||||||
|
textureViewDesc.nextInChain = nullptr;
|
||||||
|
textureViewDesc.label = "The shape texture view";
|
||||||
|
textureViewDesc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||||
|
textureViewDesc.dimension = WGPUTextureViewDimension_2D;
|
||||||
|
textureViewDesc.baseMipLevel = 0;
|
||||||
|
textureViewDesc.mipLevelCount = 1;
|
||||||
|
textureViewDesc.baseArrayLayer = 0;
|
||||||
|
textureViewDesc.arrayLayerCount = 1;
|
||||||
|
textureViewDesc.aspect = WGPUTextureAspect_All;
|
||||||
|
mTextureView = wgpuTextureCreateView(mTexture, &textureViewDesc);
|
||||||
|
assert(mTextureView);
|
||||||
|
// update texture data
|
||||||
|
WGPUImageCopyTexture imageCopyTexture{};
|
||||||
|
imageCopyTexture.nextInChain = nullptr;
|
||||||
|
imageCopyTexture.texture = mTexture;
|
||||||
|
imageCopyTexture.mipLevel = 0;
|
||||||
|
imageCopyTexture.origin = { 0, 0, 0 };
|
||||||
|
imageCopyTexture.aspect = WGPUTextureAspect_All;
|
||||||
|
WGPUTextureDataLayout textureDataLayout{};
|
||||||
|
textureDataLayout.nextInChain = nullptr;
|
||||||
|
textureDataLayout.offset = 0;
|
||||||
|
textureDataLayout.bytesPerRow = 4 * surface->w;
|
||||||
|
textureDataLayout.rowsPerImage = surface->h;
|
||||||
|
WGPUExtent3D writeSize{};
|
||||||
|
writeSize.width = surface->w;
|
||||||
|
writeSize.height = surface->h;
|
||||||
|
writeSize.depthOrArrayLayers = 1;
|
||||||
|
wgpuQueueWriteTexture(queue, &imageCopyTexture, surface->data, 4 * surface->w * surface->h, &textureDataLayout, &writeSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgImageData::release() {
|
||||||
|
if (mTexture) {
|
||||||
|
wgpuTextureDestroy(mTexture);
|
||||||
|
wgpuTextureRelease(mTexture);
|
||||||
|
mTexture = nullptr;
|
||||||
|
}
|
||||||
|
if (mTextureView) {
|
||||||
|
wgpuTextureViewRelease(mTextureView);
|
||||||
|
mTextureView = nullptr;
|
||||||
|
}
|
||||||
|
if (mSampler) {
|
||||||
|
wgpuSamplerRelease(mSampler);
|
||||||
|
mSampler = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
// WgRenderDataShapeSettings
|
// WgRenderDataShapeSettings
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
|
||||||
void WgRenderDataShapeSettings::update(WGPUQueue queue, const Fill* fill, const RenderUpdateFlag flags,
|
void WgRenderDataShapeSettings::update(WGPUDevice device, WGPUQueue queue,
|
||||||
const RenderTransform* transform, const float* viewMatrix, const uint8_t* color,
|
const Fill* fill, const uint8_t* color,
|
||||||
WgPipelineLinear& linear, WgPipelineRadial& radial, WgPipelineSolid& solid)
|
const RenderUpdateFlag flags)
|
||||||
{
|
{
|
||||||
// setup fill properties
|
// setup fill properties
|
||||||
if ((flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) && fill) {
|
if ((flags & (RenderUpdateFlag::Gradient)) && fill) {
|
||||||
// setup linear fill properties
|
// setup linear fill properties
|
||||||
if (fill->identifier() == TVG_CLASS_ID_LINEAR) {
|
if (fill->identifier() == TVG_CLASS_ID_LINEAR) {
|
||||||
WgPipelineDataLinear brushDataLinear{};
|
WgShaderTypeLinearGradient linearGradient((LinearGradient*)fill);
|
||||||
brushDataLinear.updateMatrix(viewMatrix, transform);
|
mBindGroupLinear.initialize(device, queue, linearGradient);
|
||||||
brushDataLinear.updateGradient((LinearGradient*)fill);
|
mFillType = WgRenderDataShapeFillType::Linear;
|
||||||
mPipelineBindGroupLinear.update(queue, brushDataLinear);
|
} else if (fill->identifier() == TVG_CLASS_ID_RADIAL) {
|
||||||
|
WgShaderTypeRadialGradient radialGradient((RadialGradient*)fill);
|
||||||
mPipelineBindGroup = &mPipelineBindGroupLinear;
|
mBindGroupRadial.initialize(device, queue, radialGradient);
|
||||||
mPipelineBase = &linear;
|
mFillType = WgRenderDataShapeFillType::Radial;
|
||||||
} // setup radial fill properties
|
|
||||||
else if (fill->identifier() == TVG_CLASS_ID_RADIAL) {
|
|
||||||
WgPipelineDataRadial brushDataRadial{};
|
|
||||||
brushDataRadial.updateMatrix(viewMatrix, transform);
|
|
||||||
brushDataRadial.updateGradient((RadialGradient*)fill);
|
|
||||||
mPipelineBindGroupRadial.update(queue, brushDataRadial);
|
|
||||||
|
|
||||||
mPipelineBindGroup = &mPipelineBindGroupRadial;
|
|
||||||
mPipelineBase = &radial;
|
|
||||||
}
|
}
|
||||||
} // setup solid fill properties
|
} else if ((flags & (RenderUpdateFlag::Color)) && !fill) {
|
||||||
else if ((flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Transform)) && !fill) {
|
WgShaderTypeSolidColor solidColor(color);
|
||||||
WgPipelineDataSolid pipelineDataSolid{};
|
mBindGroupSolid.initialize(device, queue, solidColor);
|
||||||
pipelineDataSolid.updateMatrix(viewMatrix, transform);
|
mFillType = WgRenderDataShapeFillType::Solid;
|
||||||
pipelineDataSolid.updateColor(color);
|
|
||||||
mPipelineBindGroupSolid.update(queue, pipelineDataSolid);
|
|
||||||
|
|
||||||
mPipelineBindGroup = &mPipelineBindGroupSolid;
|
|
||||||
mPipelineBase = &solid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgRenderDataShapeSettings::release() {
|
void WgRenderDataShapeSettings::release() {
|
||||||
mPipelineBindGroupSolid.release();
|
mBindGroupSolid.release();
|
||||||
mPipelineBindGroupLinear.release();
|
mBindGroupLinear.release();
|
||||||
mPipelineBindGroupRadial.release();
|
mBindGroupRadial.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
@ -161,9 +231,11 @@ void WgRenderDataShapeSettings::release() {
|
||||||
|
|
||||||
void WgRenderDataShape::release() {
|
void WgRenderDataShape::release() {
|
||||||
releaseRenderData();
|
releaseRenderData();
|
||||||
|
mImageData.release();
|
||||||
|
mBindGroupPaint.release();
|
||||||
mRenderSettingsShape.release();
|
mRenderSettingsShape.release();
|
||||||
mRenderSettingsStroke.release();
|
mRenderSettingsStroke.release();
|
||||||
mPipelineBindGroupImage.release();
|
mBindGroupPicture.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgRenderDataShape::releaseRenderData() {
|
void WgRenderDataShape::releaseRenderData() {
|
||||||
|
@ -227,6 +299,9 @@ void WgRenderDataShape::tesselate(WGPUDevice device, WGPUQueue queue, Surface* s
|
||||||
(float *)vertexList.data, (float *)texCoordsList.data, vertexList.count,
|
(float *)vertexList.data, (float *)texCoordsList.data, vertexList.count,
|
||||||
indexList.data, indexList.count);
|
indexList.data, indexList.count);
|
||||||
mGeometryDataImage.push(geometryData);
|
mGeometryDataImage.push(geometryData);
|
||||||
|
|
||||||
|
// update image data
|
||||||
|
mImageData.update(device, queue, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgRenderDataShape::tesselate(WGPUDevice device, WGPUQueue queue, const RenderShape& rshape) {
|
void WgRenderDataShape::tesselate(WGPUDevice device, WGPUQueue queue, const RenderShape& rshape) {
|
||||||
|
@ -479,4 +554,4 @@ void WgRenderDataShape::strokeSublines(const RenderShape& rshape, Array<WgVertex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,20 +23,16 @@
|
||||||
#ifndef _TVG_WG_RENDER_DATA_H_
|
#ifndef _TVG_WG_RENDER_DATA_H_
|
||||||
#define _TVG_WG_RENDER_DATA_H_
|
#define _TVG_WG_RENDER_DATA_H_
|
||||||
|
|
||||||
#include "tvgWgPipelineSolid.h"
|
#include "tvgWgPipelines.h"
|
||||||
#include "tvgWgPipelineLinear.h"
|
|
||||||
#include "tvgWgPipelineRadial.h"
|
|
||||||
#include "tvgWgPipelineImage.h"
|
|
||||||
#include "tvgWgGeometry.h"
|
#include "tvgWgGeometry.h"
|
||||||
|
|
||||||
class WgGeometryData {
|
struct WgGeometryData {
|
||||||
public:
|
|
||||||
WGPUBuffer mBufferVertex{};
|
WGPUBuffer mBufferVertex{};
|
||||||
WGPUBuffer mBufferTexCoords{};
|
WGPUBuffer mBufferTexCoords{};
|
||||||
WGPUBuffer mBufferIndex{};
|
WGPUBuffer mBufferIndex{};
|
||||||
size_t mVertexCount{};
|
size_t mVertexCount{};
|
||||||
size_t mIndexCount{};
|
size_t mIndexCount{};
|
||||||
public:
|
|
||||||
WgGeometryData() {}
|
WgGeometryData() {}
|
||||||
virtual ~WgGeometryData() { release(); }
|
virtual ~WgGeometryData() { release(); }
|
||||||
|
|
||||||
|
@ -49,36 +45,51 @@ public:
|
||||||
void release();
|
void release();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WgImageData {
|
||||||
|
WGPUSampler mSampler{};
|
||||||
|
WGPUTexture mTexture{};
|
||||||
|
WGPUTextureView mTextureView{};
|
||||||
|
|
||||||
|
WgImageData() {}
|
||||||
|
virtual ~WgImageData() { release(); }
|
||||||
|
|
||||||
|
void initialize(WGPUDevice device) {};
|
||||||
|
void update(WGPUDevice device, WGPUQueue queue, Surface* surface);
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
class WgRenderData {
|
class WgRenderData {
|
||||||
public:
|
public:
|
||||||
virtual void initialize(WGPUDevice device) {};
|
virtual void initialize(WGPUDevice device) {};
|
||||||
virtual void release() = 0;
|
virtual void release() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class WgRenderDataShapeFillType { None = 0, Solid = 1, Linear = 2, Radial = 3 };
|
||||||
struct WgRenderDataShapeSettings {
|
struct WgRenderDataShapeSettings {
|
||||||
WgPipelineBindGroupSolid mPipelineBindGroupSolid{};
|
WgBindGroupSolidColor mBindGroupSolid{};
|
||||||
WgPipelineBindGroupLinear mPipelineBindGroupLinear{};
|
WgBindGroupLinearGradient mBindGroupLinear{};
|
||||||
WgPipelineBindGroupRadial mPipelineBindGroupRadial{};
|
WgBindGroupRadialGradient mBindGroupRadial{};
|
||||||
|
WgRenderDataShapeFillType mFillType{}; // Default: None
|
||||||
WgPipelineBase* mPipelineBase{}; // external
|
|
||||||
WgPipelineBindGroup* mPipelineBindGroup{}; // external
|
|
||||||
|
|
||||||
// update render shape settings defined by flags and fill settings
|
// update render shape settings defined by flags and fill settings
|
||||||
void update(WGPUQueue queue, const Fill* fill, const RenderUpdateFlag flags,
|
void update(WGPUDevice device, WGPUQueue queue,
|
||||||
const RenderTransform* transform, const float* viewMatrix, const uint8_t* color,
|
const Fill* fill, const uint8_t* color, const RenderUpdateFlag flags);
|
||||||
WgPipelineLinear& linear, WgPipelineRadial& radial, WgPipelineSolid& solid);
|
|
||||||
void release();
|
void release();
|
||||||
};
|
};
|
||||||
|
|
||||||
class WgRenderDataShape: public WgRenderData {
|
class WgRenderDataShape: public WgRenderData {
|
||||||
public:
|
public:
|
||||||
|
// geometry data for shapes, strokes and image
|
||||||
Array<WgGeometryData*> mGeometryDataShape;
|
Array<WgGeometryData*> mGeometryDataShape;
|
||||||
Array<WgGeometryData*> mGeometryDataStroke;
|
Array<WgGeometryData*> mGeometryDataStroke;
|
||||||
Array<WgGeometryData*> mGeometryDataImage;
|
Array<WgGeometryData*> mGeometryDataImage;
|
||||||
|
WgImageData mImageData;
|
||||||
|
|
||||||
|
// shader settings
|
||||||
|
WgBindGroupPaint mBindGroupPaint;
|
||||||
WgRenderDataShapeSettings mRenderSettingsShape;
|
WgRenderDataShapeSettings mRenderSettingsShape;
|
||||||
WgRenderDataShapeSettings mRenderSettingsStroke;
|
WgRenderDataShapeSettings mRenderSettingsStroke;
|
||||||
WgPipelineBindGroupImage mPipelineBindGroupImage;
|
WgBindGroupPicture mBindGroupPicture;
|
||||||
public:
|
public:
|
||||||
WgRenderDataShape() {}
|
WgRenderDataShape() {}
|
||||||
|
|
||||||
|
|
|
@ -103,15 +103,7 @@ void WgRenderer::initialize() {
|
||||||
assert(mQueue);
|
assert(mQueue);
|
||||||
|
|
||||||
// create pipelines
|
// create pipelines
|
||||||
mPipelineEmpty.initialize(mDevice);
|
mPipelines.initialize(mDevice);
|
||||||
mPipelineStroke.initialize(mDevice);
|
|
||||||
mPipelineSolid.initialize(mDevice);
|
|
||||||
mPipelineLinear.initialize(mDevice);
|
|
||||||
mPipelineRadial.initialize(mDevice);
|
|
||||||
mPipelineImage.initialize(mDevice);
|
|
||||||
mPipelineBindGroupEmpty.initialize(mDevice, mPipelineEmpty);
|
|
||||||
mPipelineBindGroupStroke.initialize(mDevice, mPipelineStroke);
|
|
||||||
mGeometryDataWindow.initialize(mDevice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgRenderer::release() {
|
void WgRenderer::release() {
|
||||||
|
@ -122,15 +114,10 @@ void WgRenderer::release() {
|
||||||
if (mStencilTexView) wgpuTextureViewRelease(mStencilTexView);
|
if (mStencilTexView) wgpuTextureViewRelease(mStencilTexView);
|
||||||
if (mSwapChain) wgpuSwapChainRelease(mSwapChain);
|
if (mSwapChain) wgpuSwapChainRelease(mSwapChain);
|
||||||
if (mSurface) wgpuSurfaceRelease(mSurface);
|
if (mSurface) wgpuSurfaceRelease(mSurface);
|
||||||
mGeometryDataWindow.release();
|
mBindGroupCanvasWnd.release();
|
||||||
mPipelineBindGroupStroke.release();
|
mBindGroupPaintWnd.release();
|
||||||
mPipelineBindGroupEmpty.release();
|
mGeometryDataWnd.release();
|
||||||
mPipelineImage.release();
|
mPipelines.release();
|
||||||
mPipelineRadial.release();
|
|
||||||
mPipelineLinear.release();
|
|
||||||
mPipelineSolid.release();
|
|
||||||
mPipelineStroke.release();
|
|
||||||
mPipelineEmpty.release();
|
|
||||||
if (mDevice) {
|
if (mDevice) {
|
||||||
wgpuDeviceDestroy(mDevice);
|
wgpuDeviceDestroy(mDevice);
|
||||||
wgpuDeviceRelease(mDevice);
|
wgpuDeviceRelease(mDevice);
|
||||||
|
@ -145,31 +132,26 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
||||||
if (!renderDataShape) {
|
if (!renderDataShape) {
|
||||||
renderDataShape = new WgRenderDataShape();
|
renderDataShape = new WgRenderDataShape();
|
||||||
renderDataShape->initialize(mDevice);
|
renderDataShape->initialize(mDevice);
|
||||||
renderDataShape->mRenderSettingsShape.mPipelineBindGroupSolid.initialize(mDevice, mPipelineSolid);
|
|
||||||
renderDataShape->mRenderSettingsShape.mPipelineBindGroupLinear.initialize(mDevice, mPipelineLinear);
|
|
||||||
renderDataShape->mRenderSettingsShape.mPipelineBindGroupRadial.initialize(mDevice, mPipelineRadial);
|
|
||||||
renderDataShape->mRenderSettingsStroke.mPipelineBindGroupSolid.initialize(mDevice, mPipelineSolid);
|
|
||||||
renderDataShape->mRenderSettingsStroke.mPipelineBindGroupLinear.initialize(mDevice, mPipelineLinear);
|
|
||||||
renderDataShape->mRenderSettingsStroke.mPipelineBindGroupRadial.initialize(mDevice, mPipelineRadial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke))
|
// update geometry
|
||||||
|
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke)) {
|
||||||
renderDataShape->releaseRenderData();
|
renderDataShape->releaseRenderData();
|
||||||
|
|
||||||
if (flags & RenderUpdateFlag::Path)
|
|
||||||
renderDataShape->tesselate(mDevice, mQueue, rshape);
|
renderDataShape->tesselate(mDevice, mQueue, rshape);
|
||||||
|
|
||||||
if (flags & RenderUpdateFlag::Stroke)
|
|
||||||
renderDataShape->stroke(mDevice, mQueue, rshape);
|
renderDataShape->stroke(mDevice, mQueue, rshape);
|
||||||
|
}
|
||||||
|
|
||||||
// setup shape fill properties
|
// update paint settings
|
||||||
renderDataShape->mRenderSettingsShape.update(mQueue, rshape.fill, flags, transform, mViewMatrix, rshape.color,
|
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
|
||||||
mPipelineLinear, mPipelineRadial, mPipelineSolid);
|
WgShaderTypeMat4x4f modelMat(transform);
|
||||||
|
WgShaderTypeBlendSettings blendSettings(mTargetSurface.cs);
|
||||||
|
renderDataShape->mBindGroupPaint.initialize(mDevice, mQueue, modelMat, blendSettings);
|
||||||
|
}
|
||||||
|
|
||||||
// setup stroke fill properties
|
// setup fill settings
|
||||||
|
renderDataShape->mRenderSettingsShape.update(mDevice, mQueue, rshape.fill, rshape.color, flags);
|
||||||
if (rshape.stroke)
|
if (rshape.stroke)
|
||||||
renderDataShape->mRenderSettingsStroke.update(mQueue, rshape.stroke->fill, flags, transform, mViewMatrix, rshape.stroke->color,
|
renderDataShape->mRenderSettingsStroke.update(mDevice, mQueue, rshape.stroke->fill, rshape.stroke->color, flags);
|
||||||
mPipelineLinear, mPipelineRadial, mPipelineSolid);
|
|
||||||
|
|
||||||
return renderDataShape;
|
return renderDataShape;
|
||||||
}
|
}
|
||||||
|
@ -184,16 +166,25 @@ RenderData WgRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderD
|
||||||
if (!renderDataShape) {
|
if (!renderDataShape) {
|
||||||
renderDataShape = new WgRenderDataShape();
|
renderDataShape = new WgRenderDataShape();
|
||||||
renderDataShape->initialize(mDevice);
|
renderDataShape->initialize(mDevice);
|
||||||
renderDataShape->mPipelineBindGroupImage.initialize(mDevice, mPipelineImage, surface);
|
|
||||||
}
|
}
|
||||||
if (flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Image | RenderUpdateFlag::Transform)) {
|
|
||||||
WgPipelineDataImage pipelineDataImage{};
|
// update paint settings
|
||||||
pipelineDataImage.updateMatrix(mViewMatrix, transform);
|
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
|
||||||
pipelineDataImage.updateFormat(surface->cs);
|
WgShaderTypeMat4x4f modelMat(transform);
|
||||||
pipelineDataImage.updateOpacity(opacity);
|
WgShaderTypeBlendSettings blendSettings(surface->cs);
|
||||||
renderDataShape->mPipelineBindGroupImage.update(mQueue, pipelineDataImage, surface);
|
renderDataShape->mBindGroupPaint.initialize(mDevice, mQueue, modelMat, blendSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update image data
|
||||||
|
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Image)) {
|
||||||
|
renderDataShape->releaseRenderData();
|
||||||
renderDataShape->tesselate(mDevice, mQueue, surface, mesh);
|
renderDataShape->tesselate(mDevice, mQueue, surface, mesh);
|
||||||
|
renderDataShape->mBindGroupPicture.initialize(
|
||||||
|
mDevice, mQueue,
|
||||||
|
renderDataShape->mImageData.mSampler,
|
||||||
|
renderDataShape->mImageData.mTextureView);
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderDataShape;
|
return renderDataShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +265,12 @@ bool WgRenderer::sync() {
|
||||||
WGPURenderPassColorAttachment colorAttachment{};
|
WGPURenderPassColorAttachment colorAttachment{};
|
||||||
colorAttachment.view = backBufferView;
|
colorAttachment.view = backBufferView;
|
||||||
colorAttachment.resolveTarget = nullptr;
|
colorAttachment.resolveTarget = nullptr;
|
||||||
colorAttachment.loadOp = WGPULoadOp_Clear;
|
if (mClearBuffer) {
|
||||||
|
colorAttachment.loadOp = WGPULoadOp_Clear;
|
||||||
|
colorAttachment.clearValue = {0, 0, 0, 0};
|
||||||
|
} else {
|
||||||
|
colorAttachment.loadOp = WGPULoadOp_Load;
|
||||||
|
}
|
||||||
colorAttachment.storeOp = WGPUStoreOp_Store;
|
colorAttachment.storeOp = WGPUStoreOp_Store;
|
||||||
colorAttachment.clearValue = { 0.0f, 0.0f, 0.0f, 1.0 };
|
colorAttachment.clearValue = { 0.0f, 0.0f, 0.0f, 1.0 };
|
||||||
// render pass descriptor
|
// render pass descriptor
|
||||||
|
@ -298,39 +294,50 @@ bool WgRenderer::sync() {
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
for (uint32_t j = 0; j < renderData->mGeometryDataShape.count; j++) {
|
for (uint32_t j = 0; j < renderData->mGeometryDataShape.count; j++) {
|
||||||
// draw to stencil (first pass)
|
// draw to stencil (first pass)
|
||||||
mPipelineEmpty.set(renderPassEncoder);
|
mPipelines.mPipelineFillShape.use(renderPassEncoder, mBindGroupCanvasWnd, renderData->mBindGroupPaint);
|
||||||
mPipelineBindGroupEmpty.bind(renderPassEncoder, 0);
|
|
||||||
renderData->mGeometryDataShape[j]->draw(renderPassEncoder);
|
renderData->mGeometryDataShape[j]->draw(renderPassEncoder);
|
||||||
|
|
||||||
// fill shape (second pass)
|
// fill shape (second pass)
|
||||||
renderData->mRenderSettingsShape.mPipelineBase->set(renderPassEncoder);
|
WgRenderDataShapeSettings& settings = renderData->mRenderSettingsShape;
|
||||||
renderData->mRenderSettingsShape.mPipelineBindGroup->bind(renderPassEncoder, 0);
|
if (settings.mFillType == WgRenderDataShapeFillType::Solid)
|
||||||
mGeometryDataWindow.draw(renderPassEncoder);
|
mPipelines.mPipelineSolid.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupSolid);
|
||||||
|
else if (settings.mFillType == WgRenderDataShapeFillType::Linear)
|
||||||
|
mPipelines.mPipelineLinear.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupLinear);
|
||||||
|
else if (settings.mFillType == WgRenderDataShapeFillType::Radial)
|
||||||
|
mPipelines.mPipelineRadial.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupRadial);
|
||||||
|
mGeometryDataWnd.draw(renderPassEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw stroke geometry
|
// draw stroke geometry
|
||||||
if (renderData->mRenderSettingsStroke.mPipelineBase) {
|
if (renderData->mGeometryDataStroke.count > 0) {
|
||||||
// draw strokes to stencil (first pass)
|
// draw strokes to stencil (first pass)
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
for (uint32_t j = 0; j < renderData->mGeometryDataStroke.count; j++) {
|
for (uint32_t j = 0; j < renderData->mGeometryDataStroke.count; j++) {
|
||||||
mPipelineStroke.set(renderPassEncoder);
|
mPipelines.mPipelineFillStroke.use(renderPassEncoder, mBindGroupCanvasWnd, renderData->mBindGroupPaint);
|
||||||
mPipelineBindGroupStroke.bind(renderPassEncoder, 0);
|
|
||||||
renderData->mGeometryDataStroke[j]->draw(renderPassEncoder);
|
renderData->mGeometryDataStroke[j]->draw(renderPassEncoder);
|
||||||
}
|
}
|
||||||
|
// fill shape (second pass)
|
||||||
// fill strokes (second pass)
|
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
renderData->mRenderSettingsStroke.mPipelineBase->set(renderPassEncoder);
|
WgRenderDataShapeSettings& settings = renderData->mRenderSettingsStroke;
|
||||||
renderData->mRenderSettingsStroke.mPipelineBindGroup->bind(renderPassEncoder, 0);
|
if (settings.mFillType == WgRenderDataShapeFillType::Solid)
|
||||||
mGeometryDataWindow.draw(renderPassEncoder);
|
mPipelines.mPipelineSolid.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupSolid);
|
||||||
|
else if (settings.mFillType == WgRenderDataShapeFillType::Linear)
|
||||||
|
mPipelines.mPipelineLinear.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupLinear);
|
||||||
|
else if (settings.mFillType == WgRenderDataShapeFillType::Radial)
|
||||||
|
mPipelines.mPipelineRadial.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupRadial);
|
||||||
|
mGeometryDataWnd.draw(renderPassEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw image geometry
|
// render image
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
if (renderData->mGeometryDataImage.count > 0) {
|
||||||
for (uint32_t j = 0; j < renderData->mGeometryDataImage.count; j++) {
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
mPipelineImage.set(renderPassEncoder);
|
for (uint32_t j = 0; j < renderData->mGeometryDataImage.count; j++) {
|
||||||
renderData->mPipelineBindGroupImage.bind(renderPassEncoder, 0);
|
mPipelines.mPipelineImage.use(
|
||||||
renderData->mGeometryDataImage[j]->drawImage(renderPassEncoder);
|
renderPassEncoder,
|
||||||
|
mBindGroupCanvasWnd,
|
||||||
|
renderData->mBindGroupPaint,
|
||||||
|
renderData->mBindGroupPicture);
|
||||||
|
renderData->mGeometryDataImage[j]->drawImage(renderPassEncoder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,22 +446,16 @@ bool WgRenderer::target(void* window, uint32_t w, uint32_t h) {
|
||||||
mStencilTexView = wgpuTextureCreateView(mStencilTex, &textureViewDesc);
|
mStencilTexView = wgpuTextureCreateView(mStencilTex, &textureViewDesc);
|
||||||
assert(mStencilTexView);
|
assert(mStencilTexView);
|
||||||
|
|
||||||
|
// initialize window binding groups
|
||||||
|
WgShaderTypeMat4x4f viewMat(w, h);
|
||||||
|
mBindGroupCanvasWnd.initialize(mDevice, mQueue, viewMat);
|
||||||
|
WgShaderTypeMat4x4f modelMat;
|
||||||
|
WgShaderTypeBlendSettings blendSettings(ColorSpace::ABGR8888);
|
||||||
|
mBindGroupPaintWnd.initialize(mDevice, mQueue, modelMat, blendSettings);
|
||||||
// update pipeline geometry data
|
// update pipeline geometry data
|
||||||
WgVertexList wnd;
|
WgVertexList wnd;
|
||||||
wnd.appendRect(
|
wnd.appendRect(WgPoint(0.0f, 0.0f), WgPoint(w, 0.0f), WgPoint(0.0f, h), WgPoint(w, h));
|
||||||
WgPoint(0.0f, 0.0f), WgPoint(w, 0.0f),
|
mGeometryDataWnd.update(mDevice, mQueue, &wnd);
|
||||||
WgPoint(0.0f, h), WgPoint(w, h)
|
|
||||||
);
|
|
||||||
// update render data pipeline empty and stroke
|
|
||||||
mGeometryDataWindow.update(mDevice, mQueue, &wnd);
|
|
||||||
// update bind group pipeline empty
|
|
||||||
WgPipelineDataEmpty pipelineDataEmpty{};
|
|
||||||
pipelineDataEmpty.updateMatrix(mViewMatrix, nullptr);
|
|
||||||
mPipelineBindGroupEmpty.update(mQueue, pipelineDataEmpty);
|
|
||||||
// update bind group pipeline stroke
|
|
||||||
WgPipelineDataStroke pipelineDataStroke{};
|
|
||||||
pipelineDataStroke.updateMatrix(mViewMatrix, nullptr);
|
|
||||||
mPipelineBindGroupStroke.update(mQueue, pipelineDataStroke);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#ifndef _TVG_WG_RENDERER_H_
|
#ifndef _TVG_WG_RENDERER_H_
|
||||||
#define _TVG_WG_RENDERER_H_
|
#define _TVG_WG_RENDERER_H_
|
||||||
|
|
||||||
#include "tvgWgPipelineEmpty.h"
|
|
||||||
#include "tvgWgPipelineStroke.h"
|
|
||||||
#include "tvgWgRenderData.h"
|
#include "tvgWgRenderData.h"
|
||||||
|
|
||||||
class WgRenderer : public RenderMethod
|
class WgRenderer : public RenderMethod
|
||||||
|
@ -77,16 +75,13 @@ private:
|
||||||
WGPUSwapChain mSwapChain{};
|
WGPUSwapChain mSwapChain{};
|
||||||
WGPUTexture mStencilTex{};
|
WGPUTexture mStencilTex{};
|
||||||
WGPUTextureView mStencilTexView{};
|
WGPUTextureView mStencilTexView{};
|
||||||
|
WgBindGroupCanvas mBindGroupCanvasWnd;
|
||||||
|
WgBindGroupPaint mBindGroupPaintWnd;
|
||||||
|
WgGeometryData mGeometryDataWnd;
|
||||||
private:
|
private:
|
||||||
WgPipelineEmpty mPipelineEmpty;
|
WgPipelines mPipelines;
|
||||||
WgPipelineStroke mPipelineStroke;
|
|
||||||
WgPipelineSolid mPipelineSolid;
|
bool mClearBuffer;
|
||||||
WgPipelineLinear mPipelineLinear;
|
|
||||||
WgPipelineRadial mPipelineRadial;
|
|
||||||
WgPipelineImage mPipelineImage;
|
|
||||||
WgGeometryData mGeometryDataWindow;
|
|
||||||
WgPipelineBindGroupEmpty mPipelineBindGroupEmpty;
|
|
||||||
WgPipelineBindGroupStroke mPipelineBindGroupStroke;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _TVG_WG_RENDERER_H_ */
|
#endif /* _TVG_WG_RENDERER_H_ */
|
||||||
|
|
|
@ -24,18 +24,21 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
// cShaderSource_PipelineEmpty
|
// shader pipeline fill
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
|
|
||||||
const char* cShaderSource_PipelineEmpty = R"(
|
const char* cShaderSource_PipelineFill = R"(
|
||||||
// vertex input
|
// vertex input
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
@location(0) position: vec2f
|
@location(0) position: vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// Matrix
|
// BlendSettigs
|
||||||
struct Matrix {
|
struct BlendSettigs {
|
||||||
transform: mat4x4f
|
format : u32, // ColorSpace
|
||||||
|
dummy0 : f32,
|
||||||
|
dummy1 : f32,
|
||||||
|
dummy2 : f32
|
||||||
};
|
};
|
||||||
|
|
||||||
// vertex output
|
// vertex output
|
||||||
|
@ -43,24 +46,27 @@ struct VertexOutput {
|
||||||
@builtin(position) position: vec4f
|
@builtin(position) position: vec4f
|
||||||
};
|
};
|
||||||
|
|
||||||
// uMatrix
|
// uniforms
|
||||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
|
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||||
|
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
// fill output
|
// fill output
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0);
|
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> void {
|
fn fs_main(in: VertexOutput) -> void {
|
||||||
// nothing to draw, just stencil value
|
// nothing to draw, just stencil value
|
||||||
})";
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
// cShaderSource_PipelineSolid
|
// shader pipeline solid
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
|
|
||||||
const char* cShaderSource_PipelineSolid = R"(
|
const char* cShaderSource_PipelineSolid = R"(
|
||||||
|
@ -69,14 +75,12 @@ struct VertexInput {
|
||||||
@location(0) position: vec2f
|
@location(0) position: vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// Matrix
|
// BlendSettigs
|
||||||
struct Matrix {
|
struct BlendSettigs {
|
||||||
transform: mat4x4f
|
format : u32, // ColorSpace
|
||||||
};
|
dummy0 : f32,
|
||||||
|
dummy1 : f32,
|
||||||
// ColorInfo
|
dummy2 : f32
|
||||||
struct ColorInfo {
|
|
||||||
color: vec4f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// vertex output
|
// vertex output
|
||||||
|
@ -84,27 +88,34 @@ struct VertexOutput {
|
||||||
@builtin(position) position: vec4f
|
@builtin(position) position: vec4f
|
||||||
};
|
};
|
||||||
|
|
||||||
// uMatrix
|
// uniforms
|
||||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
// uColorInfo
|
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||||
@group(0) @binding(1) var<uniform> uColorInfo: ColorInfo;
|
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||||
|
@group(2) @binding(0) var<uniform> uSolidColor : vec4f;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
// fill output
|
// fill output
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0);
|
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
//out.position = vec4f(in.position.xy, 0.0, 1.0);
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
return uColorInfo.color;
|
// resulting color
|
||||||
})";
|
var color = vec4(1.0);
|
||||||
|
|
||||||
|
// get color
|
||||||
|
color = uSolidColor;
|
||||||
|
|
||||||
|
return vec4f(color.rgb, color.a);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
// cShaderSource_PipelineLinear
|
// shader pipeline linear
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
|
|
||||||
const char* cShaderSource_PipelineLinear = R"(
|
const char* cShaderSource_PipelineLinear = R"(
|
||||||
|
@ -113,46 +124,53 @@ struct VertexInput {
|
||||||
@location(0) position: vec2f
|
@location(0) position: vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// Matrix
|
// BlendSettigs
|
||||||
struct Matrix {
|
struct BlendSettigs {
|
||||||
transform: mat4x4f
|
format : u32, // ColorSpace
|
||||||
|
dummy0 : f32,
|
||||||
|
dummy1 : f32,
|
||||||
|
dummy2 : f32
|
||||||
};
|
};
|
||||||
|
|
||||||
// GradientInfo
|
// LinearGradient
|
||||||
const MAX_STOP_COUNT = 4;
|
const MAX_LINEAR_GRADIENT_STOPS = 4;
|
||||||
struct GradientInfo {
|
struct LinearGradient {
|
||||||
nStops : vec4f,
|
nStops : vec4f,
|
||||||
gradStartPos : vec2f,
|
gradStartPos : vec2f,
|
||||||
gradEndPos : vec2f,
|
gradEndPos : vec2f,
|
||||||
stopPoints : vec4f,
|
stopPoints : vec4f,
|
||||||
stopColors : array<vec4f, MAX_STOP_COUNT>
|
stopColors : array<vec4f, MAX_LINEAR_GRADIENT_STOPS>
|
||||||
};
|
};
|
||||||
|
|
||||||
// vertex output
|
// vertex output
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
@builtin(position) position: vec4f,
|
@builtin(position) position : vec4f,
|
||||||
@location(0) vScreenCoord: vec2f
|
@location(0) vScreenCoord : vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// uMatrix
|
// uniforms
|
||||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
// uGradientInfo
|
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||||
@group(0) @binding(1) var<uniform> uGradientInfo: GradientInfo;
|
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||||
|
@group(2) @binding(0) var<uniform> uLinearGradient : LinearGradient;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
// fill output
|
// fill output
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0);
|
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
out.vScreenCoord = in.position.xy;
|
out.vScreenCoord = in.position.xy;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
|
// resulting color
|
||||||
|
var color = vec4(1.0);
|
||||||
|
|
||||||
let pos: vec2f = in.vScreenCoord;
|
let pos: vec2f = in.vScreenCoord;
|
||||||
let st: vec2f = uGradientInfo.gradStartPos;
|
let st: vec2f = uLinearGradient.gradStartPos;
|
||||||
let ed: vec2f = uGradientInfo.gradEndPos;
|
let ed: vec2f = uLinearGradient.gradEndPos;
|
||||||
|
|
||||||
let ba: vec2f = ed - st;
|
let ba: vec2f = ed - st;
|
||||||
|
|
||||||
|
@ -160,36 +178,34 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
let t: f32 = clamp(dot(pos - st, ba) / dot(ba, ba), 0.0, 1.0);
|
let t: f32 = clamp(dot(pos - st, ba) / dot(ba, ba), 0.0, 1.0);
|
||||||
|
|
||||||
// get stops count
|
// get stops count
|
||||||
let last: i32 = i32(uGradientInfo.nStops[0]) - 1;
|
let last: i32 = i32(uLinearGradient.nStops[0]) - 1;
|
||||||
|
|
||||||
// resulting color
|
|
||||||
var color = vec4(1.0);
|
|
||||||
|
|
||||||
// closer than first stop
|
// closer than first stop
|
||||||
if (t <= uGradientInfo.stopPoints[0]) {
|
if (t <= uLinearGradient.stopPoints[0]) {
|
||||||
color = uGradientInfo.stopColors[0];
|
color = uLinearGradient.stopColors[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// further than last stop
|
// further than last stop
|
||||||
if (t >= uGradientInfo.stopPoints[last]) {
|
if (t >= uLinearGradient.stopPoints[last]) {
|
||||||
color = uGradientInfo.stopColors[last];
|
color = uLinearGradient.stopColors[last];
|
||||||
}
|
}
|
||||||
|
|
||||||
// look in the middle
|
// look in the middle
|
||||||
for (var i = 0i; i < last; i++) {
|
for (var i = 0i; i < last; i++) {
|
||||||
let strt = uGradientInfo.stopPoints[i];
|
let strt = uLinearGradient.stopPoints[i];
|
||||||
let stop = uGradientInfo.stopPoints[i+1];
|
let stop = uLinearGradient.stopPoints[i+1];
|
||||||
if ((t > strt) && (t < stop)) {
|
if ((t > strt) && (t < stop)) {
|
||||||
let step: f32 = (t - strt) / (stop - strt);
|
let step: f32 = (t - strt) / (stop - strt);
|
||||||
color = mix(uGradientInfo.stopColors[i], uGradientInfo.stopColors[i+1], step);
|
color = mix(uLinearGradient.stopColors[i], uLinearGradient.stopColors[i+1], step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return color;
|
return vec4f(color.rgb, color.a);
|
||||||
})";
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
// cShaderSource_PipelineRadial
|
// shader pipeline radial
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
|
|
||||||
const char* cShaderSource_PipelineRadial = R"(
|
const char* cShaderSource_PipelineRadial = R"(
|
||||||
|
@ -198,125 +214,125 @@ struct VertexInput {
|
||||||
@location(0) position: vec2f
|
@location(0) position: vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// Matrix
|
// BlendSettigs
|
||||||
struct Matrix {
|
struct BlendSettigs {
|
||||||
transform: mat4x4f
|
format : u32, // ColorSpace
|
||||||
|
dummy0 : f32,
|
||||||
|
dummy1 : f32,
|
||||||
|
dummy2 : f32
|
||||||
};
|
};
|
||||||
|
|
||||||
// GradientInfo
|
// RadialGradient
|
||||||
const MAX_STOP_COUNT = 4;
|
const MAX_RADIAL_GRADIENT_STOPS = 4;
|
||||||
struct GradientInfo {
|
struct RadialGradient {
|
||||||
nStops : vec4f,
|
nStops : vec4f,
|
||||||
centerPos : vec2f,
|
centerPos : vec2f,
|
||||||
radius : vec2f,
|
radius : vec2f,
|
||||||
stopPoints : vec4f,
|
stopPoints : vec4f,
|
||||||
stopColors : array<vec4f, MAX_STOP_COUNT>
|
stopColors : array<vec4f, MAX_RADIAL_GRADIENT_STOPS>
|
||||||
};
|
};
|
||||||
|
|
||||||
// vertex output
|
// vertex output
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
@builtin(position) position: vec4f,
|
@builtin(position) position : vec4f,
|
||||||
@location(0) vScreenCoord: vec2f
|
@location(0) vScreenCoord : vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// uMatrix
|
// uniforms
|
||||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
// uGradientInfo
|
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||||
@group(0) @binding(1) var<uniform> uGradientInfo: GradientInfo;
|
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||||
|
@group(2) @binding(0) var<uniform> uRadialGradient : RadialGradient;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
// fill output
|
// fill output
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0);
|
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
out.vScreenCoord = in.position.xy;
|
out.vScreenCoord = in.position.xy;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
// get interpolation factor
|
|
||||||
let t: f32 = clamp(distance(uGradientInfo.centerPos, in.vScreenCoord) / uGradientInfo.radius.x, 0.0, 1.0);
|
|
||||||
|
|
||||||
// get stops count
|
|
||||||
let last: i32 = i32(uGradientInfo.nStops[0]) - 1;
|
|
||||||
|
|
||||||
// resulting color
|
// resulting color
|
||||||
var color = vec4(1.0);
|
var color = vec4(1.0);
|
||||||
|
|
||||||
|
// get interpolation factor
|
||||||
|
let t: f32 = clamp(distance(uRadialGradient.centerPos, in.vScreenCoord) / uRadialGradient.radius.x, 0.0, 1.0);
|
||||||
|
|
||||||
|
// get stops count
|
||||||
|
let last: i32 = i32(uRadialGradient.nStops[0]) - 1;
|
||||||
|
|
||||||
// closer than first stop
|
// closer than first stop
|
||||||
if (t <= uGradientInfo.stopPoints[0]) {
|
if (t <= uRadialGradient.stopPoints[0]) {
|
||||||
color = uGradientInfo.stopColors[0];
|
color = uRadialGradient.stopColors[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// further than last stop
|
// further than last stop
|
||||||
if (t >= uGradientInfo.stopPoints[last]) {
|
if (t >= uRadialGradient.stopPoints[last]) {
|
||||||
color = uGradientInfo.stopColors[last];
|
color = uRadialGradient.stopColors[last];
|
||||||
}
|
}
|
||||||
|
|
||||||
// look in the middle
|
// look in the middle
|
||||||
for (var i = 0i; i < last; i++) {
|
for (var i = 0i; i < last; i++) {
|
||||||
let strt = uGradientInfo.stopPoints[i];
|
let strt = uRadialGradient.stopPoints[i];
|
||||||
let stop = uGradientInfo.stopPoints[i+1];
|
let stop = uRadialGradient.stopPoints[i+1];
|
||||||
if ((t > strt) && (t < stop)) {
|
if ((t > strt) && (t < stop)) {
|
||||||
let step: f32 = (t - strt) / (stop - strt);
|
let step: f32 = (t - strt) / (stop - strt);
|
||||||
color = mix(uGradientInfo.stopColors[i], uGradientInfo.stopColors[i+1], step);
|
color = mix(uRadialGradient.stopColors[i], uRadialGradient.stopColors[i+1], step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return color;
|
return vec4f(color.rgb, color.a);
|
||||||
})";
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
//************************************************************************
|
||||||
|
// cShaderSource_PipelineImage
|
||||||
|
//************************************************************************
|
||||||
|
|
||||||
const char* cShaderSource_PipelineImage = R"(
|
const char* cShaderSource_PipelineImage = R"(
|
||||||
// vertex input
|
// vertex input
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
@location(0) position: vec2f,
|
@location(0) position: vec2f,
|
||||||
@location(1) texCoords: vec2f
|
@location(1) texCoord: vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// Matrix
|
// BlendSettigs
|
||||||
struct Matrix {
|
struct BlendSettigs {
|
||||||
transform: mat4x4f
|
format : u32, // ColorSpace
|
||||||
};
|
dummy0 : f32,
|
||||||
|
dummy1 : f32,
|
||||||
// ColorInfo
|
dummy2 : f32
|
||||||
struct ColorInfo {
|
|
||||||
format: u32,
|
|
||||||
dummy0: f32,
|
|
||||||
dummy1: f32,
|
|
||||||
opacity: f32
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// vertex output
|
// vertex output
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
@builtin(position) position: vec4f,
|
@builtin(position) position: vec4f,
|
||||||
@location(0) texCoords: vec2f,
|
@location(0) texCoord: vec2f
|
||||||
};
|
};
|
||||||
|
|
||||||
// uMatrix
|
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||||
// uColorInfo
|
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||||
@group(0) @binding(1) var<uniform> uColorInfo: ColorInfo;
|
@group(2) @binding(0) var uSampler : sampler;
|
||||||
// uSamplerBase
|
@group(2) @binding(1) var uTextureView : texture_2d<f32>;
|
||||||
@group(0) @binding(2) var uSamplerBase: sampler;
|
|
||||||
// uTextureViewBase
|
|
||||||
@group(0) @binding(3) var uTextureViewBase: texture_2d<f32>;
|
|
||||||
|
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
// fill output
|
// fill output
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0);
|
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
out.texCoords = in.texCoords;
|
out.texCoord = in.texCoord;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
var color: vec4f = textureSample(uTextureViewBase, uSamplerBase, in.texCoords.xy);
|
var color: vec4f = textureSample(uTextureView, uSampler, in.texCoord.xy);
|
||||||
var result: vec4f = color;
|
var result: vec4f = color;
|
||||||
var format: u32 = uColorInfo.format;
|
var format: u32 = uBlendSettigs.format;
|
||||||
if (format == 1u) { /* FMT_ARGB8888 */
|
if (format == 1u) { /* FMT_ARGB8888 */
|
||||||
result = color.bgra;
|
result = color.bgra;
|
||||||
} else if (format == 2u) { /* FMT_ABGR8888S */
|
} else if (format == 2u) { /* FMT_ABGR8888S */
|
||||||
|
@ -324,5 +340,6 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
} else if (format == 3u) { /* FMT_ARGB8888S */
|
} else if (format == 3u) { /* FMT_ARGB8888S */
|
||||||
result = vec4(color.bgr * color.a, color.a);
|
result = vec4(color.bgr * color.a, color.a);
|
||||||
}
|
}
|
||||||
return vec4f(result.rgb, result.a * uColorInfo.opacity);
|
return vec4f(result.rgb, result.a);
|
||||||
})";
|
};
|
||||||
|
)";
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
#ifndef _TVG_WG_SHADER_SRC_H_
|
#ifndef _TVG_WG_SHADER_SRC_H_
|
||||||
#define _TVG_WG_SHADER_SRC_H_
|
#define _TVG_WG_SHADER_SRC_H_
|
||||||
|
|
||||||
// pipeline shader module empty
|
// pipeline shader module fill
|
||||||
extern const char* cShaderSource_PipelineEmpty;
|
extern const char* cShaderSource_PipelineFill;
|
||||||
|
|
||||||
// pipeline shader module solid
|
// pipeline shader module solid
|
||||||
extern const char* cShaderSource_PipelineSolid;
|
extern const char* cShaderSource_PipelineSolid;
|
||||||
|
@ -40,4 +40,16 @@ extern const char* cShaderSource_PipelineRadial;
|
||||||
// pipeline shader module image
|
// pipeline shader module image
|
||||||
extern const char* cShaderSource_PipelineImage;
|
extern const char* cShaderSource_PipelineImage;
|
||||||
|
|
||||||
|
extern const char* MASK_ALPHA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_INV_ALPHA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_LUMA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_INV_LUMA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_ADD_FRAG_SHADER;
|
||||||
|
extern const char* MASK_SUB_FRAG_SHADER;
|
||||||
|
extern const char* MASK_INTERSECT_FRAG_SHADER;
|
||||||
|
extern const char* MASK_DIFF_FRAG_SHADER;
|
||||||
|
|
||||||
|
// pipeline shader module compose
|
||||||
|
extern const char* cShaderSource_Pipeline;
|
||||||
|
|
||||||
#endif // _TVG_WG_SHADER_SRC_H_
|
#endif // _TVG_WG_SHADER_SRC_H_
|
||||||
|
|
141
src/renderer/wg_engine/tvgWgShaderTypes.cpp
Normal file
141
src/renderer/wg_engine/tvgWgShaderTypes.cpp
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tvgWgShaderTypes.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// shader types
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
WgShaderTypeMat4x4f::WgShaderTypeMat4x4f() {
|
||||||
|
identity();
|
||||||
|
}
|
||||||
|
|
||||||
|
WgShaderTypeMat4x4f::WgShaderTypeMat4x4f(const RenderTransform* transform) {
|
||||||
|
update(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgShaderTypeMat4x4f::identity() {
|
||||||
|
mat[0] = 1.0f; mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f;
|
||||||
|
mat[4] = 0.0f; mat[5] = 1.0f; mat[6] = 0.0f; mat[7] = 0.0f;
|
||||||
|
mat[8] = 0.0f; mat[9] = 0.0f; mat[10] = 1.0f; mat[11] = 0.0f;
|
||||||
|
mat[12] = 0.0f; mat[13] = 0.0f; mat[14] = 0.0f; mat[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
WgShaderTypeMat4x4f::WgShaderTypeMat4x4f(size_t w, size_t h) {
|
||||||
|
update(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgShaderTypeMat4x4f::update(const RenderTransform* transform) {
|
||||||
|
identity();
|
||||||
|
if (transform) {
|
||||||
|
mat[0] = transform->m.e11;
|
||||||
|
mat[1] = transform->m.e21;
|
||||||
|
mat[2] = 0.0f;
|
||||||
|
mat[3] = transform->m.e31;
|
||||||
|
mat[4] = transform->m.e12;
|
||||||
|
mat[5] = transform->m.e22;
|
||||||
|
mat[6] = 0.0f;
|
||||||
|
mat[7] = transform->m.e32;
|
||||||
|
mat[8] = 0.0f;
|
||||||
|
mat[9] = 0.0f;
|
||||||
|
mat[10] = 1.0f;
|
||||||
|
mat[11] = 0.0f;
|
||||||
|
mat[12] = transform->m.e13;
|
||||||
|
mat[13] = transform->m.e23;
|
||||||
|
mat[14] = 0.0f;
|
||||||
|
mat[15] = transform->m.e33;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void WgShaderTypeMat4x4f::update(size_t w, size_t h) {
|
||||||
|
mat[0] = +2.0f / w; mat[1] = +0.0f; mat[2] = +0.0f; mat[3] = +0.0f;
|
||||||
|
mat[4] = +0.0f; mat[5] = -2.0f / h; mat[6] = +0.0f; mat[7] = +0.0f;
|
||||||
|
mat[8] = +0.0f; mat[9] = +0.0f; mat[10] = -1.0f; mat[11] = +0.0f;
|
||||||
|
mat[12] = -1.0f; mat[13] = +1.0f; mat[14] = +0.0f; mat[15] = +1.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
WgShaderTypeBlendSettings::WgShaderTypeBlendSettings(const ColorSpace colorSpace) {
|
||||||
|
update(colorSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgShaderTypeBlendSettings::update(const ColorSpace colorSpace) {
|
||||||
|
format = (uint32_t)colorSpace;
|
||||||
|
dummy0 = 0.0f;
|
||||||
|
dummy1 = 0.0f;
|
||||||
|
dummy2 = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
WgShaderTypeSolidColor::WgShaderTypeSolidColor(const uint8_t* c) {
|
||||||
|
update(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgShaderTypeSolidColor::update(const uint8_t* c) {
|
||||||
|
color[0] = c[0] / 255.0f; // red
|
||||||
|
color[1] = c[1] / 255.0f; // green
|
||||||
|
color[2] = c[2] / 255.0f; // blue
|
||||||
|
color[3] = c[3] / 255.0f; // alpha
|
||||||
|
};
|
||||||
|
|
||||||
|
WgShaderTypeLinearGradient::WgShaderTypeLinearGradient(const LinearGradient* linearGradient) {
|
||||||
|
update(linearGradient);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgShaderTypeLinearGradient::update(const LinearGradient* linearGradient) {
|
||||||
|
const Fill::ColorStop* stops = nullptr;
|
||||||
|
auto stopCnt = linearGradient->colorStops(&stops);
|
||||||
|
|
||||||
|
nStops[0] = stopCnt;
|
||||||
|
nStops[1] = 0.5f;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < stopCnt; ++i) {
|
||||||
|
stopPoints[i] = stops[i].offset;
|
||||||
|
stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||||
|
stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
||||||
|
stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
||||||
|
stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
linearGradient->linear(&startPos[0], &startPos[1], &endPos[0], &endPos[1]);
|
||||||
|
};
|
||||||
|
|
||||||
|
WgShaderTypeRadialGradient::WgShaderTypeRadialGradient(const RadialGradient* radialGradient) {
|
||||||
|
update(radialGradient);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WgShaderTypeRadialGradient::update(const RadialGradient* radialGradient) {
|
||||||
|
const Fill::ColorStop* stops = nullptr;
|
||||||
|
auto stopCnt = radialGradient->colorStops(&stops);
|
||||||
|
|
||||||
|
nStops[0] = stopCnt;
|
||||||
|
nStops[1] = 0.5f;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < stopCnt; ++i) {
|
||||||
|
stopPoints[i] = stops[i].offset;
|
||||||
|
stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||||
|
stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
||||||
|
stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
||||||
|
stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
radialGradient->radial(¢erPos[0], ¢erPos[1], &radius[0]);
|
||||||
|
};
|
111
src/renderer/wg_engine/tvgWgShaderTypes.h
Normal file
111
src/renderer/wg_engine/tvgWgShaderTypes.h
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TVG_WG_SHADER_TYPES_H_
|
||||||
|
#define _TVG_WG_SHADER_TYPES_H_
|
||||||
|
|
||||||
|
#include "tvgWgCommon.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// shader types
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// mat4x4f
|
||||||
|
struct WgShaderTypeMat4x4f {
|
||||||
|
float mat[16]{};
|
||||||
|
|
||||||
|
WgShaderTypeMat4x4f();
|
||||||
|
WgShaderTypeMat4x4f(const RenderTransform* transform);
|
||||||
|
WgShaderTypeMat4x4f(size_t w, size_t h);
|
||||||
|
void identity();
|
||||||
|
void update(const RenderTransform* transform);
|
||||||
|
void update(size_t w, size_t h);
|
||||||
|
};
|
||||||
|
|
||||||
|
// struct BlendSettigs {
|
||||||
|
// format : u32, // ColorSpace
|
||||||
|
// dummy0 : f32,
|
||||||
|
// dummy1 : f32,
|
||||||
|
// opacity : f32
|
||||||
|
// };
|
||||||
|
struct WgShaderTypeBlendSettings {
|
||||||
|
uint32_t format{}; // ColorSpace
|
||||||
|
float dummy0{};
|
||||||
|
float dummy1{};
|
||||||
|
float dummy2{};
|
||||||
|
|
||||||
|
WgShaderTypeBlendSettings() {};
|
||||||
|
WgShaderTypeBlendSettings(const ColorSpace colorSpace);
|
||||||
|
void update(const ColorSpace colorSpace);
|
||||||
|
};
|
||||||
|
|
||||||
|
// struct SolidColor {
|
||||||
|
// color: vec4f
|
||||||
|
// };
|
||||||
|
struct WgShaderTypeSolidColor {
|
||||||
|
float color[4]{};
|
||||||
|
|
||||||
|
WgShaderTypeSolidColor(const uint8_t* c);
|
||||||
|
void update(const uint8_t* c);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const MAX_LINEAR_GRADIENT_STOPS = 4;
|
||||||
|
// struct LinearGradient {
|
||||||
|
// nStops : vec4f,
|
||||||
|
// gradStartPos : vec2f,
|
||||||
|
// gradEndPos : vec2f,
|
||||||
|
// stopPoints : vec4f,
|
||||||
|
// stopColors : array<vec4f, MAX_LINEAR_GRADIENT_STOPS>
|
||||||
|
// };
|
||||||
|
#define MAX_LINEAR_GRADIENT_STOPS 4
|
||||||
|
struct WgShaderTypeLinearGradient {
|
||||||
|
alignas(16) float nStops[4]{};
|
||||||
|
alignas(16) float startPos[2]{};
|
||||||
|
alignas(8) float endPos[2]{};
|
||||||
|
alignas(8) float stopPoints[MAX_LINEAR_GRADIENT_STOPS]{};
|
||||||
|
alignas(16) float stopColors[4 * MAX_LINEAR_GRADIENT_STOPS]{};
|
||||||
|
|
||||||
|
WgShaderTypeLinearGradient(const LinearGradient* linearGradient);
|
||||||
|
void update(const LinearGradient* linearGradient);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const MAX_RADIAL_GRADIENT_STOPS = 4;
|
||||||
|
// struct RadialGradient {
|
||||||
|
// nStops : vec4f,
|
||||||
|
// centerPos : vec2f,
|
||||||
|
// radius : vec2f,
|
||||||
|
// stopPoints : vec4f,
|
||||||
|
// stopColors : array<vec4f, MAX_RADIAL_GRADIENT_STOPS>
|
||||||
|
// };
|
||||||
|
#define MAX_RADIAL_GRADIENT_STOPS 4
|
||||||
|
struct WgShaderTypeRadialGradient {
|
||||||
|
alignas(16) float nStops[4]{};
|
||||||
|
alignas(16) float centerPos[2]{};
|
||||||
|
alignas(8) float radius[2]{};
|
||||||
|
alignas(8) float stopPoints[MAX_RADIAL_GRADIENT_STOPS]{};
|
||||||
|
alignas(16) float stopColors[4 * MAX_RADIAL_GRADIENT_STOPS]{};
|
||||||
|
|
||||||
|
WgShaderTypeRadialGradient(const RadialGradient* radialGradient);
|
||||||
|
void update(const RadialGradient* radialGradient);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _TVG_WG_SHADER_TYPES_H_
|
Loading…
Add table
Reference in a new issue