From eadf66e17885da4a361424ae68c1d4431ffa6a1b Mon Sep 17 00:00:00 2001 From: Sergii Liebodkin Date: Fri, 31 May 2024 13:51:46 +0300 Subject: [PATCH] wg_engine: fix color buffer corruption with wgpu-opengl wrapper (linux) In a case of usage stencil buffer only we need to turn off an color target writes. In other case color buffer fill be filled by unxepcted color if fragment shader did not return any value. It happens in a case on OpenGL realization of webgpu, that used in linux Befire: After: --- src/renderer/wg_engine/tvgWgCommon.cpp | 28 ++++++++++++-------- src/renderer/wg_engine/tvgWgCommon.h | 6 ++--- src/renderer/wg_engine/tvgWgPipelines.cpp | 14 +++++----- src/renderer/wg_engine/tvgWgRenderData.cpp | 4 +-- src/renderer/wg_engine/tvgWgRenderTarget.cpp | 4 +-- src/renderer/wg_engine/tvgWgRenderer.cpp | 7 +++-- src/renderer/wg_engine/tvgWgShaderSrc.cpp | 20 +++++++------- 7 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/renderer/wg_engine/tvgWgCommon.cpp b/src/renderer/wg_engine/tvgWgCommon.cpp index 08f216ea..0152a89a 100644 --- a/src/renderer/wg_engine/tvgWgCommon.cpp +++ b/src/renderer/wg_engine/tvgWgCommon.cpp @@ -107,9 +107,16 @@ void WgContext::release() if (device) { wgpuDeviceDestroy(device); wgpuDeviceRelease(device); + device = nullptr; + } + if (adapter) { + wgpuAdapterRelease(adapter); + adapter = nullptr; + } + if (instance) { + wgpuInstanceRelease(instance); + instance = nullptr; } - if (adapter) wgpuAdapterRelease(adapter); - if (instance) wgpuInstanceRelease(instance); } @@ -426,7 +433,7 @@ WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryStorageTexture(uin bindGroupLayoutEntry.visibility = WGPUShaderStage_Fragment | WGPUShaderStage_Compute; bindGroupLayoutEntry.storageTexture.nextInChain = nullptr; bindGroupLayoutEntry.storageTexture.access = access; - bindGroupLayoutEntry.storageTexture.format = WGPUTextureFormat_RGBA8Unorm; + bindGroupLayoutEntry.storageTexture.format = WGPUTextureFormat_BGRA8Unorm; bindGroupLayoutEntry.storageTexture.viewDimension = WGPUTextureViewDimension_2D; return bindGroupLayoutEntry; } @@ -547,7 +554,7 @@ void WgPipeline::destroyShaderModule(WGPUShaderModule& shaderModule) // render pipeline //***************************************************************************** -void WgRenderPipeline::allocate(WGPUDevice device, WgPipelineBlendType blendType, +void WgRenderPipeline::allocate(WGPUDevice device, WgPipelineBlendType blendType, WGPUColorWriteMask writeMask, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, @@ -560,7 +567,7 @@ void WgRenderPipeline::allocate(WGPUDevice device, WgPipelineBlendType blendType mPipelineLayout = createPipelineLayout(device, bindGroupLayouts, bindGroupsCount); assert(mPipelineLayout); - mRenderPipeline = createRenderPipeline(device, blendType, + mRenderPipeline = createRenderPipeline(device, blendType, writeMask, vertexBufferLayouts, attribsCount, compareFront, operationFront, compareBack, operationBack, @@ -623,14 +630,13 @@ WGPUBlendState WgRenderPipeline::makeBlendState(WgPipelineBlendType blendType) } -WGPUColorTargetState WgRenderPipeline::makeColorTargetState(const WGPUBlendState* blendState) +WGPUColorTargetState WgRenderPipeline::makeColorTargetState(const WGPUBlendState* blendState, const WGPUColorWriteMask writeMask) { WGPUColorTargetState colorTargetState{}; colorTargetState.nextInChain = nullptr; - //colorTargetState.format = WGPUTextureFormat_BGRA8Unorm; // (WGPUTextureFormat_BGRA8UnormSrgb) - colorTargetState.format = WGPUTextureFormat_RGBA8Unorm; // (WGPUTextureFormat_BGRA8UnormSrgb) + colorTargetState.format = WGPUTextureFormat_BGRA8Unorm; colorTargetState.blend = blendState; - colorTargetState.writeMask = WGPUColorWriteMask_All; + colorTargetState.writeMask = writeMask; return colorTargetState; } @@ -721,7 +727,7 @@ WGPUFragmentState WgRenderPipeline::makeFragmentState(WGPUShaderModule shaderMod } -WGPURenderPipeline WgRenderPipeline::createRenderPipeline(WGPUDevice device, WgPipelineBlendType blendType, +WGPURenderPipeline WgRenderPipeline::createRenderPipeline(WGPUDevice device, WgPipelineBlendType blendType, WGPUColorWriteMask writeMask, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, WGPUCompareFunction compareBack, WGPUStencilOperation operationBack, @@ -730,7 +736,7 @@ WGPURenderPipeline WgRenderPipeline::createRenderPipeline(WGPUDevice device, WgP { WGPUBlendState blendState = makeBlendState(blendType); WGPUColorTargetState colorTargetStates[] = { - makeColorTargetState(&blendState) + makeColorTargetState(&blendState, writeMask) }; WGPUVertexState vertexState = makeVertexState(shaderModule, vertexBufferLayouts, attribsCount); diff --git a/src/renderer/wg_engine/tvgWgCommon.h b/src/renderer/wg_engine/tvgWgCommon.h index 41410108..0e471d23 100644 --- a/src/renderer/wg_engine/tvgWgCommon.h +++ b/src/renderer/wg_engine/tvgWgCommon.h @@ -125,7 +125,7 @@ struct WgRenderPipeline: public WgPipeline { protected: WGPURenderPipeline mRenderPipeline{}; - void allocate(WGPUDevice device, WgPipelineBlendType blendType, + void allocate(WGPUDevice device, WgPipelineBlendType blendType, WGPUColorWriteMask writeMask, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, @@ -136,7 +136,7 @@ public: void set(WGPURenderPassEncoder renderPassEncoder); static WGPUBlendState makeBlendState(WgPipelineBlendType blendType); - static WGPUColorTargetState makeColorTargetState(const WGPUBlendState* blendState); + static WGPUColorTargetState makeColorTargetState(const WGPUBlendState* blendState, const WGPUColorWriteMask writeMask); 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(); @@ -144,7 +144,7 @@ public: static WGPUMultisampleState makeMultisampleState(); static WGPUFragmentState makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size); - static WGPURenderPipeline createRenderPipeline(WGPUDevice device, WgPipelineBlendType blendType, + static WGPURenderPipeline createRenderPipeline(WGPUDevice device, WgPipelineBlendType blendType, WGPUColorWriteMask writeMask, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, WGPUCompareFunction compareBack, WGPUStencilOperation operationBack, diff --git a/src/renderer/wg_engine/tvgWgPipelines.cpp b/src/renderer/wg_engine/tvgWgPipelines.cpp index b9e03851..70e6fc68 100644 --- a/src/renderer/wg_engine/tvgWgPipelines.cpp +++ b/src/renderer/wg_engine/tvgWgPipelines.cpp @@ -55,7 +55,7 @@ void WgPipelineFillShapeWinding::initialize(WGPUDevice device) auto pipelineLabel = "The render pipeline fill shape winding"; // allocate all pipeline handles - allocate(device, WgPipelineBlendType::Src, + allocate(device, WgPipelineBlendType::Add, WGPUColorWriteMask_None, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), stencilFuncionFront, stencilOperationFront, stencilFuncionBack, stencilOperationBack, @@ -89,7 +89,7 @@ void WgPipelineFillShapeEvenOdd::initialize(WGPUDevice device) auto pipelineLabel = "The render pipeline fill shape Even Odd"; // allocate all pipeline handles - allocate(device, WgPipelineBlendType::Src, + allocate(device, WgPipelineBlendType::Add, WGPUColorWriteMask_None, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), stencilFuncionFront, stencilOperationFront, stencilFuncionBack, stencilOperationBack, @@ -121,7 +121,7 @@ void WgPipelineFillStroke::initialize(WGPUDevice device) auto pipelineLabel = "The render pipeline fill stroke"; // allocate all pipeline handles - allocate(device, WgPipelineBlendType::Src, + allocate(device, WgPipelineBlendType::Add, WGPUColorWriteMask_None, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, @@ -154,7 +154,7 @@ void WgPipelineSolid::initialize(WGPUDevice device, WgPipelineBlendType blendTyp auto pipelineLabel = "The render pipeline solid color"; // allocate all pipeline handles - allocate(device, blendType, + allocate(device, blendType, WGPUColorWriteMask_All, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, @@ -187,7 +187,7 @@ void WgPipelineLinear::initialize(WGPUDevice device, WgPipelineBlendType blendTy auto pipelineLabel = "The render pipeline linear gradient"; // allocate all pipeline handles - allocate(device, blendType, + allocate(device, blendType, WGPUColorWriteMask_All, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, @@ -220,7 +220,7 @@ void WgPipelineRadial::initialize(WGPUDevice device, WgPipelineBlendType blendTy auto pipelineLabel = "The render pipeline radial gradient"; // allocate all pipeline handles - allocate(device, blendType, + allocate(device, blendType, WGPUColorWriteMask_All, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, @@ -255,7 +255,7 @@ void WgPipelineImage::initialize(WGPUDevice device, WgPipelineBlendType blendTyp auto pipelineLabel = "The render pipeline image"; // allocate all pipeline handles - allocate(device, blendType, + allocate(device, blendType, WGPUColorWriteMask_All, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, diff --git a/src/renderer/wg_engine/tvgWgRenderData.cpp b/src/renderer/wg_engine/tvgWgRenderData.cpp index ef8e0d75..8f45dbc0 100644 --- a/src/renderer/wg_engine/tvgWgRenderData.cpp +++ b/src/renderer/wg_engine/tvgWgRenderData.cpp @@ -353,8 +353,8 @@ void WgRenderDataShape::releaseMeshes(WgContext &context) meshGroupStrokes.release(context); meshGroupShapesBBox.release(context); meshGroupShapes.release(context); - pMin = {0.0f, 0.0f }; - pMax = {0.0f, 0.0f }; + pMin = {FLT_MAX, FLT_MAX}; + pMax = {0.0f, 0.0f}; } diff --git a/src/renderer/wg_engine/tvgWgRenderTarget.cpp b/src/renderer/wg_engine/tvgWgRenderTarget.cpp index e11ef2bf..13b651b8 100644 --- a/src/renderer/wg_engine/tvgWgRenderTarget.cpp +++ b/src/renderer/wg_engine/tvgWgRenderTarget.cpp @@ -41,7 +41,7 @@ WGPUTextureUsage_TextureBinding | WGPUTextureUsage_StorageBinding | WGPUTextureUsage_RenderAttachment, - WGPUTextureFormat_RGBA8Unorm, + WGPUTextureFormat_BGRA8Unorm, width, height, "The target texture color"); texStencil = context.createTexture2d( WGPUTextureUsage_RenderAttachment, @@ -266,7 +266,7 @@ void WgRenderStorage::beginRenderPass(WGPUCommandEncoder commandEncoder, bool cl depthStencilAttachment.depthClearValue = 1.0f; depthStencilAttachment.depthReadOnly = false; depthStencilAttachment.stencilLoadOp = WGPULoadOp_Clear; - depthStencilAttachment.stencilStoreOp = WGPUStoreOp_Store; + depthStencilAttachment.stencilStoreOp = WGPUStoreOp_Discard; depthStencilAttachment.stencilClearValue = 0; depthStencilAttachment.stencilReadOnly = false; // render pass color attachment diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 95ae02b6..6e1a198e 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -320,8 +320,7 @@ bool WgRenderer::target(void* window, uint32_t w, uint32_t h) mTargetSurface.stride = w; mTargetSurface.w = w > 0 ? w : 1; mTargetSurface.h = h > 0 ? h : 1; - - // TODO: replace solution to cross-platform realization + // surface descriptor from windows hwnd WGPUSurfaceDescriptorFromWindowsHWND surfaceDescHwnd{}; surfaceDescHwnd.chain.next = nullptr; @@ -337,8 +336,8 @@ bool WgRenderer::target(void* window, uint32_t w, uint32_t h) WGPUSurfaceConfiguration surfaceConfiguration{}; surfaceConfiguration.nextInChain = nullptr; surfaceConfiguration.device = mContext.device; - surfaceConfiguration.format = WGPUTextureFormat_RGBA8Unorm; - surfaceConfiguration.usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopyDst; + surfaceConfiguration.format = WGPUTextureFormat_BGRA8Unorm; + surfaceConfiguration.usage = WGPUTextureUsage_CopyDst; surfaceConfiguration.viewFormatCount = 0; surfaceConfiguration.viewFormats = nullptr; surfaceConfiguration.alphaMode = WGPUCompositeAlphaMode_Auto; diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.cpp b/src/renderer/wg_engine/tvgWgShaderSrc.cpp index 00841183..8e9d8e7f 100644 --- a/src/renderer/wg_engine/tvgWgShaderSrc.cpp +++ b/src/renderer/wg_engine/tvgWgShaderSrc.cpp @@ -365,7 +365,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { // pipeline shader modules clear const char* cShaderSource_PipelineComputeClear = R"( -@group(0) @binding(0) var imageDst : texture_storage_2d; +@group(0) @binding(0) var imageDst : texture_storage_2d; @compute @workgroup_size(8, 8) fn cs_main( @builtin(global_invocation_id) id: vec3u) { @@ -376,8 +376,8 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) { // pipeline shader modules blend const char* cShaderSource_PipelineComputeBlend = R"( -@group(0) @binding(0) var imageSrc : texture_storage_2d; -@group(1) @binding(0) var imageDst : texture_storage_2d; +@group(0) @binding(0) var imageSrc : texture_storage_2d; +@group(1) @binding(0) var imageDst : texture_storage_2d; @group(2) @binding(0) var blendMethod : u32; @compute @workgroup_size(8, 8) @@ -420,8 +420,8 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) { // pipeline shader modules compose const char* cShaderSource_PipelineComputeCompose = R"( -@group(0) @binding(0) var imageSrc : texture_storage_2d; -@group(1) @binding(0) var imageMsk : texture_storage_2d; +@group(0) @binding(0) var imageSrc : texture_storage_2d; +@group(1) @binding(0) var imageMsk : texture_storage_2d; @group(2) @binding(0) var composeMethod : u32; @group(3) @binding(0) var opacity : f32; @@ -455,9 +455,9 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) { // pipeline shader modules compose blend const char* cShaderSource_PipelineComputeComposeBlend = R"( -@group(0) @binding(0) var imageSrc : texture_storage_2d; -@group(0) @binding(1) var imageMsk : texture_storage_2d; -@group(0) @binding(2) var imageDst : texture_storage_2d; +@group(0) @binding(0) var imageSrc : texture_storage_2d; +@group(0) @binding(1) var imageMsk : texture_storage_2d; +@group(0) @binding(2) var imageDst : texture_storage_2d; @group(1) @binding(0) var composeMethod : u32; @group(2) @binding(0) var blendMethod : u32; @group(3) @binding(0) var opacity : f32; @@ -517,8 +517,8 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) { // pipeline shader modules anti-aliasing const char* cShaderSource_PipelineComputeAntiAlias = R"( -@group(0) @binding(0) var imageSrc : texture_storage_2d; -@group(1) @binding(0) var imageDst : texture_storage_2d; +@group(0) @binding(0) var imageSrc : texture_storage_2d; +@group(1) @binding(0) var imageDst : texture_storage_2d; @compute @workgroup_size(8, 8) fn cs_main( @builtin(global_invocation_id) id: vec3u) {