mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 19:44:28 +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 = [
|
||||
'tvgWgBindGroups.h',
|
||||
'tvgWgCommon.h',
|
||||
'tvgWgGeometry.h',
|
||||
'tvgWgPipelines.h',
|
||||
'tvgWgRenderData.h',
|
||||
'tvgWgRenderer.h',
|
||||
'tvgWgShaderSrc.h',
|
||||
'tvgWgShaderTypes.h'
|
||||
'tvgWgBindGroups.cpp',
|
||||
'tvgWgCommon.cpp',
|
||||
'tvgWgGeometry.cpp',
|
||||
'tvgWgPipelineBase.cpp',
|
||||
'tvgWgPipelineEmpty.cpp',
|
||||
'tvgWgPipelineLinear.cpp',
|
||||
'tvgWgPipelineSolid.cpp',
|
||||
'tvgWgPipelineRadial.cpp',
|
||||
'tvgWgPipelineStroke.cpp',
|
||||
'tvgWgPipelines.cpp',
|
||||
'tvgWgRenderData.cpp',
|
||||
'tvgWgRenderer.cpp',
|
||||
'tvgWgShaderSrc.cpp'
|
||||
'tvgWgShaderSrc.cpp',
|
||||
'tvgWgShaderTypes.cpp'
|
||||
]
|
||||
|
||||
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 "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_
|
||||
|
|
|
@ -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
|
||||
//***********************************************************************
|
||||
|
||||
void WgRenderDataShapeSettings::update(WGPUQueue queue, const Fill* fill, const RenderUpdateFlag flags,
|
||||
const RenderTransform* transform, const float* viewMatrix, const uint8_t* color,
|
||||
WgPipelineLinear& linear, WgPipelineRadial& radial, WgPipelineSolid& solid)
|
||||
void WgRenderDataShapeSettings::update(WGPUDevice device, WGPUQueue queue,
|
||||
const Fill* fill, const uint8_t* color,
|
||||
const RenderUpdateFlag flags)
|
||||
{
|
||||
// setup fill properties
|
||||
if ((flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) && fill) {
|
||||
if ((flags & (RenderUpdateFlag::Gradient)) && fill) {
|
||||
// setup linear fill properties
|
||||
if (fill->identifier() == TVG_CLASS_ID_LINEAR) {
|
||||
WgPipelineDataLinear brushDataLinear{};
|
||||
brushDataLinear.updateMatrix(viewMatrix, transform);
|
||||
brushDataLinear.updateGradient((LinearGradient*)fill);
|
||||
mPipelineBindGroupLinear.update(queue, brushDataLinear);
|
||||
|
||||
mPipelineBindGroup = &mPipelineBindGroupLinear;
|
||||
mPipelineBase = &linear;
|
||||
} // 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;
|
||||
WgShaderTypeLinearGradient linearGradient((LinearGradient*)fill);
|
||||
mBindGroupLinear.initialize(device, queue, linearGradient);
|
||||
mFillType = WgRenderDataShapeFillType::Linear;
|
||||
} else if (fill->identifier() == TVG_CLASS_ID_RADIAL) {
|
||||
WgShaderTypeRadialGradient radialGradient((RadialGradient*)fill);
|
||||
mBindGroupRadial.initialize(device, queue, radialGradient);
|
||||
mFillType = WgRenderDataShapeFillType::Radial;
|
||||
}
|
||||
} // setup solid fill properties
|
||||
else if ((flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Transform)) && !fill) {
|
||||
WgPipelineDataSolid pipelineDataSolid{};
|
||||
pipelineDataSolid.updateMatrix(viewMatrix, transform);
|
||||
pipelineDataSolid.updateColor(color);
|
||||
mPipelineBindGroupSolid.update(queue, pipelineDataSolid);
|
||||
|
||||
mPipelineBindGroup = &mPipelineBindGroupSolid;
|
||||
mPipelineBase = &solid;
|
||||
} else if ((flags & (RenderUpdateFlag::Color)) && !fill) {
|
||||
WgShaderTypeSolidColor solidColor(color);
|
||||
mBindGroupSolid.initialize(device, queue, solidColor);
|
||||
mFillType = WgRenderDataShapeFillType::Solid;
|
||||
}
|
||||
}
|
||||
|
||||
void WgRenderDataShapeSettings::release() {
|
||||
mPipelineBindGroupSolid.release();
|
||||
mPipelineBindGroupLinear.release();
|
||||
mPipelineBindGroupRadial.release();
|
||||
mBindGroupSolid.release();
|
||||
mBindGroupLinear.release();
|
||||
mBindGroupRadial.release();
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
|
@ -161,9 +231,11 @@ void WgRenderDataShapeSettings::release() {
|
|||
|
||||
void WgRenderDataShape::release() {
|
||||
releaseRenderData();
|
||||
mImageData.release();
|
||||
mBindGroupPaint.release();
|
||||
mRenderSettingsShape.release();
|
||||
mRenderSettingsStroke.release();
|
||||
mPipelineBindGroupImage.release();
|
||||
mBindGroupPicture.release();
|
||||
}
|
||||
|
||||
void WgRenderDataShape::releaseRenderData() {
|
||||
|
@ -227,6 +299,9 @@ void WgRenderDataShape::tesselate(WGPUDevice device, WGPUQueue queue, Surface* s
|
|||
(float *)vertexList.data, (float *)texCoordsList.data, vertexList.count,
|
||||
indexList.data, indexList.count);
|
||||
mGeometryDataImage.push(geometryData);
|
||||
|
||||
// update image data
|
||||
mImageData.update(device, queue, surface);
|
||||
}
|
||||
|
||||
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_
|
||||
#define _TVG_WG_RENDER_DATA_H_
|
||||
|
||||
#include "tvgWgPipelineSolid.h"
|
||||
#include "tvgWgPipelineLinear.h"
|
||||
#include "tvgWgPipelineRadial.h"
|
||||
#include "tvgWgPipelineImage.h"
|
||||
#include "tvgWgPipelines.h"
|
||||
#include "tvgWgGeometry.h"
|
||||
|
||||
class WgGeometryData {
|
||||
public:
|
||||
struct WgGeometryData {
|
||||
WGPUBuffer mBufferVertex{};
|
||||
WGPUBuffer mBufferTexCoords{};
|
||||
WGPUBuffer mBufferIndex{};
|
||||
size_t mVertexCount{};
|
||||
size_t mIndexCount{};
|
||||
public:
|
||||
|
||||
WgGeometryData() {}
|
||||
virtual ~WgGeometryData() { release(); }
|
||||
|
||||
|
@ -49,36 +45,51 @@ public:
|
|||
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 {
|
||||
public:
|
||||
virtual void initialize(WGPUDevice device) {};
|
||||
virtual void release() = 0;
|
||||
};
|
||||
|
||||
enum class WgRenderDataShapeFillType { None = 0, Solid = 1, Linear = 2, Radial = 3 };
|
||||
struct WgRenderDataShapeSettings {
|
||||
WgPipelineBindGroupSolid mPipelineBindGroupSolid{};
|
||||
WgPipelineBindGroupLinear mPipelineBindGroupLinear{};
|
||||
WgPipelineBindGroupRadial mPipelineBindGroupRadial{};
|
||||
|
||||
WgPipelineBase* mPipelineBase{}; // external
|
||||
WgPipelineBindGroup* mPipelineBindGroup{}; // external
|
||||
WgBindGroupSolidColor mBindGroupSolid{};
|
||||
WgBindGroupLinearGradient mBindGroupLinear{};
|
||||
WgBindGroupRadialGradient mBindGroupRadial{};
|
||||
WgRenderDataShapeFillType mFillType{}; // Default: None
|
||||
|
||||
// update render shape settings defined by flags and fill settings
|
||||
void update(WGPUQueue queue, const Fill* fill, const RenderUpdateFlag flags,
|
||||
const RenderTransform* transform, const float* viewMatrix, const uint8_t* color,
|
||||
WgPipelineLinear& linear, WgPipelineRadial& radial, WgPipelineSolid& solid);
|
||||
void update(WGPUDevice device, WGPUQueue queue,
|
||||
const Fill* fill, const uint8_t* color, const RenderUpdateFlag flags);
|
||||
void release();
|
||||
};
|
||||
|
||||
class WgRenderDataShape: public WgRenderData {
|
||||
public:
|
||||
// geometry data for shapes, strokes and image
|
||||
Array<WgGeometryData*> mGeometryDataShape;
|
||||
Array<WgGeometryData*> mGeometryDataStroke;
|
||||
Array<WgGeometryData*> mGeometryDataImage;
|
||||
WgImageData mImageData;
|
||||
|
||||
// shader settings
|
||||
WgBindGroupPaint mBindGroupPaint;
|
||||
WgRenderDataShapeSettings mRenderSettingsShape;
|
||||
WgRenderDataShapeSettings mRenderSettingsStroke;
|
||||
WgPipelineBindGroupImage mPipelineBindGroupImage;
|
||||
WgBindGroupPicture mBindGroupPicture;
|
||||
public:
|
||||
WgRenderDataShape() {}
|
||||
|
||||
|
|
|
@ -103,15 +103,7 @@ void WgRenderer::initialize() {
|
|||
assert(mQueue);
|
||||
|
||||
// create pipelines
|
||||
mPipelineEmpty.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);
|
||||
mPipelines.initialize(mDevice);
|
||||
}
|
||||
|
||||
void WgRenderer::release() {
|
||||
|
@ -122,15 +114,10 @@ void WgRenderer::release() {
|
|||
if (mStencilTexView) wgpuTextureViewRelease(mStencilTexView);
|
||||
if (mSwapChain) wgpuSwapChainRelease(mSwapChain);
|
||||
if (mSurface) wgpuSurfaceRelease(mSurface);
|
||||
mGeometryDataWindow.release();
|
||||
mPipelineBindGroupStroke.release();
|
||||
mPipelineBindGroupEmpty.release();
|
||||
mPipelineImage.release();
|
||||
mPipelineRadial.release();
|
||||
mPipelineLinear.release();
|
||||
mPipelineSolid.release();
|
||||
mPipelineStroke.release();
|
||||
mPipelineEmpty.release();
|
||||
mBindGroupCanvasWnd.release();
|
||||
mBindGroupPaintWnd.release();
|
||||
mGeometryDataWnd.release();
|
||||
mPipelines.release();
|
||||
if (mDevice) {
|
||||
wgpuDeviceDestroy(mDevice);
|
||||
wgpuDeviceRelease(mDevice);
|
||||
|
@ -145,31 +132,26 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
if (!renderDataShape) {
|
||||
renderDataShape = new WgRenderDataShape();
|
||||
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();
|
||||
|
||||
if (flags & RenderUpdateFlag::Path)
|
||||
renderDataShape->tesselate(mDevice, mQueue, rshape);
|
||||
|
||||
if (flags & RenderUpdateFlag::Stroke)
|
||||
renderDataShape->stroke(mDevice, mQueue, rshape);
|
||||
}
|
||||
|
||||
// setup shape fill properties
|
||||
renderDataShape->mRenderSettingsShape.update(mQueue, rshape.fill, flags, transform, mViewMatrix, rshape.color,
|
||||
mPipelineLinear, mPipelineRadial, mPipelineSolid);
|
||||
// update paint settings
|
||||
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
|
||||
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)
|
||||
renderDataShape->mRenderSettingsStroke.update(mQueue, rshape.stroke->fill, flags, transform, mViewMatrix, rshape.stroke->color,
|
||||
mPipelineLinear, mPipelineRadial, mPipelineSolid);
|
||||
renderDataShape->mRenderSettingsStroke.update(mDevice, mQueue, rshape.stroke->fill, rshape.stroke->color, flags);
|
||||
|
||||
return renderDataShape;
|
||||
}
|
||||
|
@ -184,16 +166,25 @@ RenderData WgRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderD
|
|||
if (!renderDataShape) {
|
||||
renderDataShape = new WgRenderDataShape();
|
||||
renderDataShape->initialize(mDevice);
|
||||
renderDataShape->mPipelineBindGroupImage.initialize(mDevice, mPipelineImage, surface);
|
||||
}
|
||||
if (flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Image | RenderUpdateFlag::Transform)) {
|
||||
WgPipelineDataImage pipelineDataImage{};
|
||||
pipelineDataImage.updateMatrix(mViewMatrix, transform);
|
||||
pipelineDataImage.updateFormat(surface->cs);
|
||||
pipelineDataImage.updateOpacity(opacity);
|
||||
renderDataShape->mPipelineBindGroupImage.update(mQueue, pipelineDataImage, surface);
|
||||
|
||||
// update paint settings
|
||||
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
|
||||
WgShaderTypeMat4x4f modelMat(transform);
|
||||
WgShaderTypeBlendSettings blendSettings(surface->cs);
|
||||
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->mBindGroupPicture.initialize(
|
||||
mDevice, mQueue,
|
||||
renderDataShape->mImageData.mSampler,
|
||||
renderDataShape->mImageData.mTextureView);
|
||||
}
|
||||
|
||||
return renderDataShape;
|
||||
}
|
||||
|
||||
|
@ -274,7 +265,12 @@ bool WgRenderer::sync() {
|
|||
WGPURenderPassColorAttachment colorAttachment{};
|
||||
colorAttachment.view = backBufferView;
|
||||
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.clearValue = { 0.0f, 0.0f, 0.0f, 1.0 };
|
||||
// render pass descriptor
|
||||
|
@ -298,39 +294,50 @@ bool WgRenderer::sync() {
|
|||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
for (uint32_t j = 0; j < renderData->mGeometryDataShape.count; j++) {
|
||||
// draw to stencil (first pass)
|
||||
mPipelineEmpty.set(renderPassEncoder);
|
||||
mPipelineBindGroupEmpty.bind(renderPassEncoder, 0);
|
||||
mPipelines.mPipelineFillShape.use(renderPassEncoder, mBindGroupCanvasWnd, renderData->mBindGroupPaint);
|
||||
renderData->mGeometryDataShape[j]->draw(renderPassEncoder);
|
||||
|
||||
// fill shape (second pass)
|
||||
renderData->mRenderSettingsShape.mPipelineBase->set(renderPassEncoder);
|
||||
renderData->mRenderSettingsShape.mPipelineBindGroup->bind(renderPassEncoder, 0);
|
||||
mGeometryDataWindow.draw(renderPassEncoder);
|
||||
WgRenderDataShapeSettings& settings = renderData->mRenderSettingsShape;
|
||||
if (settings.mFillType == WgRenderDataShapeFillType::Solid)
|
||||
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
|
||||
if (renderData->mRenderSettingsStroke.mPipelineBase) {
|
||||
if (renderData->mGeometryDataStroke.count > 0) {
|
||||
// draw strokes to stencil (first pass)
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||
for (uint32_t j = 0; j < renderData->mGeometryDataStroke.count; j++) {
|
||||
mPipelineStroke.set(renderPassEncoder);
|
||||
mPipelineBindGroupStroke.bind(renderPassEncoder, 0);
|
||||
mPipelines.mPipelineFillStroke.use(renderPassEncoder, mBindGroupCanvasWnd, renderData->mBindGroupPaint);
|
||||
renderData->mGeometryDataStroke[j]->draw(renderPassEncoder);
|
||||
}
|
||||
|
||||
// fill strokes (second pass)
|
||||
// fill shape (second pass)
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
renderData->mRenderSettingsStroke.mPipelineBase->set(renderPassEncoder);
|
||||
renderData->mRenderSettingsStroke.mPipelineBindGroup->bind(renderPassEncoder, 0);
|
||||
mGeometryDataWindow.draw(renderPassEncoder);
|
||||
WgRenderDataShapeSettings& settings = renderData->mRenderSettingsStroke;
|
||||
if (settings.mFillType == WgRenderDataShapeFillType::Solid)
|
||||
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
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
for (uint32_t j = 0; j < renderData->mGeometryDataImage.count; j++) {
|
||||
mPipelineImage.set(renderPassEncoder);
|
||||
renderData->mPipelineBindGroupImage.bind(renderPassEncoder, 0);
|
||||
renderData->mGeometryDataImage[j]->drawImage(renderPassEncoder);
|
||||
// render image
|
||||
if (renderData->mGeometryDataImage.count > 0) {
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
for (uint32_t j = 0; j < renderData->mGeometryDataImage.count; j++) {
|
||||
mPipelines.mPipelineImage.use(
|
||||
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);
|
||||
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
|
||||
WgVertexList wnd;
|
||||
wnd.appendRect(
|
||||
WgPoint(0.0f, 0.0f), WgPoint(w, 0.0f),
|
||||
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);
|
||||
wnd.appendRect(WgPoint(0.0f, 0.0f), WgPoint(w, 0.0f), WgPoint(0.0f, h), WgPoint(w, h));
|
||||
mGeometryDataWnd.update(mDevice, mQueue, &wnd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#ifndef _TVG_WG_RENDERER_H_
|
||||
#define _TVG_WG_RENDERER_H_
|
||||
|
||||
#include "tvgWgPipelineEmpty.h"
|
||||
#include "tvgWgPipelineStroke.h"
|
||||
#include "tvgWgRenderData.h"
|
||||
|
||||
class WgRenderer : public RenderMethod
|
||||
|
@ -77,16 +75,13 @@ private:
|
|||
WGPUSwapChain mSwapChain{};
|
||||
WGPUTexture mStencilTex{};
|
||||
WGPUTextureView mStencilTexView{};
|
||||
WgBindGroupCanvas mBindGroupCanvasWnd;
|
||||
WgBindGroupPaint mBindGroupPaintWnd;
|
||||
WgGeometryData mGeometryDataWnd;
|
||||
private:
|
||||
WgPipelineEmpty mPipelineEmpty;
|
||||
WgPipelineStroke mPipelineStroke;
|
||||
WgPipelineSolid mPipelineSolid;
|
||||
WgPipelineLinear mPipelineLinear;
|
||||
WgPipelineRadial mPipelineRadial;
|
||||
WgPipelineImage mPipelineImage;
|
||||
WgGeometryData mGeometryDataWindow;
|
||||
WgPipelineBindGroupEmpty mPipelineBindGroupEmpty;
|
||||
WgPipelineBindGroupStroke mPipelineBindGroupStroke;
|
||||
WgPipelines mPipelines;
|
||||
|
||||
bool mClearBuffer;
|
||||
};
|
||||
|
||||
#endif /* _TVG_WG_RENDERER_H_ */
|
||||
|
|
|
@ -24,18 +24,21 @@
|
|||
#include <string>
|
||||
|
||||
//************************************************************************
|
||||
// cShaderSource_PipelineEmpty
|
||||
// shader pipeline fill
|
||||
//************************************************************************
|
||||
|
||||
const char* cShaderSource_PipelineEmpty = R"(
|
||||
const char* cShaderSource_PipelineFill = R"(
|
||||
// vertex input
|
||||
struct VertexInput {
|
||||
@location(0) position: vec2f
|
||||
};
|
||||
|
||||
// Matrix
|
||||
struct Matrix {
|
||||
transform: mat4x4f
|
||||
// BlendSettigs
|
||||
struct BlendSettigs {
|
||||
format : u32, // ColorSpace
|
||||
dummy0 : f32,
|
||||
dummy1 : f32,
|
||||
dummy2 : f32
|
||||
};
|
||||
|
||||
// vertex output
|
||||
|
@ -43,24 +46,27 @@ struct VertexOutput {
|
|||
@builtin(position) position: vec4f
|
||||
};
|
||||
|
||||
// uMatrix
|
||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
||||
// uniforms
|
||||
@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
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
// fill output
|
||||
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;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> void {
|
||||
// nothing to draw, just stencil value
|
||||
})";
|
||||
}
|
||||
)";
|
||||
|
||||
//************************************************************************
|
||||
// cShaderSource_PipelineSolid
|
||||
// shader pipeline solid
|
||||
//************************************************************************
|
||||
|
||||
const char* cShaderSource_PipelineSolid = R"(
|
||||
|
@ -69,14 +75,12 @@ struct VertexInput {
|
|||
@location(0) position: vec2f
|
||||
};
|
||||
|
||||
// Matrix
|
||||
struct Matrix {
|
||||
transform: mat4x4f
|
||||
};
|
||||
|
||||
// ColorInfo
|
||||
struct ColorInfo {
|
||||
color: vec4f
|
||||
// BlendSettigs
|
||||
struct BlendSettigs {
|
||||
format : u32, // ColorSpace
|
||||
dummy0 : f32,
|
||||
dummy1 : f32,
|
||||
dummy2 : f32
|
||||
};
|
||||
|
||||
// vertex output
|
||||
|
@ -84,27 +88,34 @@ struct VertexOutput {
|
|||
@builtin(position) position: vec4f
|
||||
};
|
||||
|
||||
// uMatrix
|
||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
||||
// uColorInfo
|
||||
@group(0) @binding(1) var<uniform> uColorInfo: ColorInfo;
|
||||
// uniforms
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||
@group(2) @binding(0) var<uniform> uSolidColor : vec4f;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
// fill output
|
||||
var out: VertexOutput;
|
||||
out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
//out.position = vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
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"(
|
||||
|
@ -113,46 +124,53 @@ struct VertexInput {
|
|||
@location(0) position: vec2f
|
||||
};
|
||||
|
||||
// Matrix
|
||||
struct Matrix {
|
||||
transform: mat4x4f
|
||||
// BlendSettigs
|
||||
struct BlendSettigs {
|
||||
format : u32, // ColorSpace
|
||||
dummy0 : f32,
|
||||
dummy1 : f32,
|
||||
dummy2 : f32
|
||||
};
|
||||
|
||||
// GradientInfo
|
||||
const MAX_STOP_COUNT = 4;
|
||||
struct GradientInfo {
|
||||
// LinearGradient
|
||||
const MAX_LINEAR_GRADIENT_STOPS = 4;
|
||||
struct LinearGradient {
|
||||
nStops : vec4f,
|
||||
gradStartPos : vec2f,
|
||||
gradEndPos : vec2f,
|
||||
stopPoints : vec4f,
|
||||
stopColors : array<vec4f, MAX_STOP_COUNT>
|
||||
stopColors : array<vec4f, MAX_LINEAR_GRADIENT_STOPS>
|
||||
};
|
||||
|
||||
// vertex output
|
||||
struct VertexOutput {
|
||||
@builtin(position) position: vec4f,
|
||||
@location(0) vScreenCoord: vec2f
|
||||
@builtin(position) position : vec4f,
|
||||
@location(0) vScreenCoord : vec2f
|
||||
};
|
||||
|
||||
// uMatrix
|
||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
||||
// uGradientInfo
|
||||
@group(0) @binding(1) var<uniform> uGradientInfo: GradientInfo;
|
||||
// uniforms
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||
@group(2) @binding(0) var<uniform> uLinearGradient : LinearGradient;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
// fill output
|
||||
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;
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||
// resulting color
|
||||
var color = vec4(1.0);
|
||||
|
||||
let pos: vec2f = in.vScreenCoord;
|
||||
let st: vec2f = uGradientInfo.gradStartPos;
|
||||
let ed: vec2f = uGradientInfo.gradEndPos;
|
||||
let st: vec2f = uLinearGradient.gradStartPos;
|
||||
let ed: vec2f = uLinearGradient.gradEndPos;
|
||||
|
||||
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);
|
||||
|
||||
// get stops count
|
||||
let last: i32 = i32(uGradientInfo.nStops[0]) - 1;
|
||||
|
||||
// resulting color
|
||||
var color = vec4(1.0);
|
||||
let last: i32 = i32(uLinearGradient.nStops[0]) - 1;
|
||||
|
||||
// closer than first stop
|
||||
if (t <= uGradientInfo.stopPoints[0]) {
|
||||
color = uGradientInfo.stopColors[0];
|
||||
if (t <= uLinearGradient.stopPoints[0]) {
|
||||
color = uLinearGradient.stopColors[0];
|
||||
}
|
||||
|
||||
// further than last stop
|
||||
if (t >= uGradientInfo.stopPoints[last]) {
|
||||
color = uGradientInfo.stopColors[last];
|
||||
if (t >= uLinearGradient.stopPoints[last]) {
|
||||
color = uLinearGradient.stopColors[last];
|
||||
}
|
||||
|
||||
// look in the middle
|
||||
for (var i = 0i; i < last; i++) {
|
||||
let strt = uGradientInfo.stopPoints[i];
|
||||
let stop = uGradientInfo.stopPoints[i+1];
|
||||
let strt = uLinearGradient.stopPoints[i];
|
||||
let stop = uLinearGradient.stopPoints[i+1];
|
||||
if ((t > strt) && (t < stop)) {
|
||||
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"(
|
||||
|
@ -198,125 +214,125 @@ struct VertexInput {
|
|||
@location(0) position: vec2f
|
||||
};
|
||||
|
||||
// Matrix
|
||||
struct Matrix {
|
||||
transform: mat4x4f
|
||||
// BlendSettigs
|
||||
struct BlendSettigs {
|
||||
format : u32, // ColorSpace
|
||||
dummy0 : f32,
|
||||
dummy1 : f32,
|
||||
dummy2 : f32
|
||||
};
|
||||
|
||||
// GradientInfo
|
||||
const MAX_STOP_COUNT = 4;
|
||||
struct GradientInfo {
|
||||
// RadialGradient
|
||||
const MAX_RADIAL_GRADIENT_STOPS = 4;
|
||||
struct RadialGradient {
|
||||
nStops : vec4f,
|
||||
centerPos : vec2f,
|
||||
radius : vec2f,
|
||||
stopPoints : vec4f,
|
||||
stopColors : array<vec4f, MAX_STOP_COUNT>
|
||||
stopColors : array<vec4f, MAX_RADIAL_GRADIENT_STOPS>
|
||||
};
|
||||
|
||||
// vertex output
|
||||
struct VertexOutput {
|
||||
@builtin(position) position: vec4f,
|
||||
@location(0) vScreenCoord: vec2f
|
||||
@builtin(position) position : vec4f,
|
||||
@location(0) vScreenCoord : vec2f
|
||||
};
|
||||
|
||||
// uMatrix
|
||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
||||
// uGradientInfo
|
||||
@group(0) @binding(1) var<uniform> uGradientInfo: GradientInfo;
|
||||
// uniforms
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||
@group(2) @binding(0) var<uniform> uRadialGradient : RadialGradient;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
// fill output
|
||||
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;
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
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
|
||||
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
|
||||
if (t <= uGradientInfo.stopPoints[0]) {
|
||||
color = uGradientInfo.stopColors[0];
|
||||
if (t <= uRadialGradient.stopPoints[0]) {
|
||||
color = uRadialGradient.stopColors[0];
|
||||
}
|
||||
|
||||
// further than last stop
|
||||
if (t >= uGradientInfo.stopPoints[last]) {
|
||||
color = uGradientInfo.stopColors[last];
|
||||
if (t >= uRadialGradient.stopPoints[last]) {
|
||||
color = uRadialGradient.stopColors[last];
|
||||
}
|
||||
|
||||
// look in the middle
|
||||
for (var i = 0i; i < last; i++) {
|
||||
let strt = uGradientInfo.stopPoints[i];
|
||||
let stop = uGradientInfo.stopPoints[i+1];
|
||||
let strt = uRadialGradient.stopPoints[i];
|
||||
let stop = uRadialGradient.stopPoints[i+1];
|
||||
if ((t > strt) && (t < stop)) {
|
||||
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"(
|
||||
// vertex input
|
||||
struct VertexInput {
|
||||
@location(0) position: vec2f,
|
||||
@location(1) texCoords: vec2f
|
||||
@location(1) texCoord: vec2f
|
||||
};
|
||||
|
||||
// Matrix
|
||||
struct Matrix {
|
||||
transform: mat4x4f
|
||||
};
|
||||
|
||||
// ColorInfo
|
||||
struct ColorInfo {
|
||||
format: u32,
|
||||
dummy0: f32,
|
||||
dummy1: f32,
|
||||
opacity: f32
|
||||
// BlendSettigs
|
||||
struct BlendSettigs {
|
||||
format : u32, // ColorSpace
|
||||
dummy0 : f32,
|
||||
dummy1 : f32,
|
||||
dummy2 : f32
|
||||
};
|
||||
|
||||
// vertex output
|
||||
struct VertexOutput {
|
||||
@builtin(position) position: vec4f,
|
||||
@location(0) texCoords: vec2f,
|
||||
@location(0) texCoord: vec2f
|
||||
};
|
||||
|
||||
// uMatrix
|
||||
@group(0) @binding(0) var<uniform> uMatrix: Matrix;
|
||||
// uColorInfo
|
||||
@group(0) @binding(1) var<uniform> uColorInfo: ColorInfo;
|
||||
// uSamplerBase
|
||||
@group(0) @binding(2) var uSamplerBase: sampler;
|
||||
// uTextureViewBase
|
||||
@group(0) @binding(3) var uTextureViewBase: texture_2d<f32>;
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
|
||||
@group(2) @binding(0) var uSampler : sampler;
|
||||
@group(2) @binding(1) var uTextureView : texture_2d<f32>;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
// fill output
|
||||
var out: VertexOutput;
|
||||
out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.texCoords = in.texCoords;
|
||||
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.texCoord = in.texCoord;
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
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 format: u32 = uColorInfo.format;
|
||||
var format: u32 = uBlendSettigs.format;
|
||||
if (format == 1u) { /* FMT_ARGB8888 */
|
||||
result = color.bgra;
|
||||
} else if (format == 2u) { /* FMT_ABGR8888S */
|
||||
|
@ -324,5 +340,6 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
} else if (format == 3u) { /* FMT_ARGB8888S */
|
||||
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_
|
||||
#define _TVG_WG_SHADER_SRC_H_
|
||||
|
||||
// pipeline shader module empty
|
||||
extern const char* cShaderSource_PipelineEmpty;
|
||||
// pipeline shader module fill
|
||||
extern const char* cShaderSource_PipelineFill;
|
||||
|
||||
// pipeline shader module solid
|
||||
extern const char* cShaderSource_PipelineSolid;
|
||||
|
@ -40,4 +40,16 @@ extern const char* cShaderSource_PipelineRadial;
|
|||
// pipeline shader module image
|
||||
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_
|
||||
|
|
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