From c6b33c5e9b2325ca472dab8c4b64d1dab7b2885a Mon Sep 17 00:00:00 2001 From: skal Date: Sat, 31 Jan 2026 20:44:23 +0100 Subject: fix(gpu): resolve multiple WebGPU validation and runtime errors - Fixed 'Invalid sample count 0' and 'Invalid anisotropic clamp: 0' by ensuring explicit pipeline and sampler states. - Resolved WGSL parsing errors by replacing swizzle assignments in compute shaders. - Fixed 'Texture destroyed' error in render_frame by reordering command submission and resource presentation/release. - Added WGPU_DEPTH_SLICE_UNDEFINED for Windows compatibility and ensured consistent resolveTarget initialization. - Cleaned up PassthroughEffect bind group layout mismatch and redundant string helper definitions. - Verified all tests pass and applied consistent formatting. --- src/gpu/demo_effects.cc | 77 ++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) (limited to 'src/gpu/demo_effects.cc') diff --git a/src/gpu/demo_effects.cc b/src/gpu/demo_effects.cc index 71f1284..27712d3 100644 --- a/src/gpu/demo_effects.cc +++ b/src/gpu/demo_effects.cc @@ -58,6 +58,8 @@ create_post_process_pipeline(WGPUDevice device, WGPUTextureFormat format, pipeline_desc.vertex.entryPoint = str_view("vs_main"); pipeline_desc.fragment = &fragment_state; pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList; + pipeline_desc.multisample.count = 1; + pipeline_desc.multisample.mask = 0xFFFFFFFF; return wgpuDeviceCreateRenderPipeline(device, &pipeline_desc); } @@ -91,7 +93,8 @@ struct Uniforms { audio_peak: f32, aspect_ratio: f32, time: f32, beat: f32, }; fn main(@builtin(global_invocation_id) id: vec3) { let i = id.x; if (i >= arrayLength(&particles)) { return; } var p = particles[i]; - p.pos.xyz = p.pos.xyz + p.vel.xyz * 0.016; + let new_pos = p.pos.xyz + p.vel.xyz * 0.016; + p.pos = vec4(new_pos, p.pos.w); p.vel.y = p.vel.y - 0.01 * (1.0 + uniforms.audio_peak * 5.0); p.rot.x = p.rot.x + p.rot.y * 0.016; if (p.pos.y < -1.5) { @@ -171,7 +174,9 @@ fn main(@builtin(global_invocation_id) id: vec3) { p.vel = vec4(cos(angle), sin(angle), 0.0, 0.0) * (0.5 + hash(r)*0.5) * (1.0 + uniforms.intensity * 2.0); p.color = vec4(hash(r+0.1), hash(r+0.2), 1.0, 1.0); } - p.pos.xyz = p.pos.xyz + p.vel.xyz * 0.016; p.vel.y = p.vel.y - 0.01; p.pos.w = p.pos.w - 0.01 * (1.0 + uniforms.beat); + let new_pos = p.pos.xyz + p.vel.xyz * 0.016; + p.pos = vec4(new_pos, p.pos.w - 0.01 * (1.0 + uniforms.beat)); + p.vel.y = p.vel.y - 0.01; particles[i] = p; })"; @@ -310,27 +315,44 @@ void ParticlesEffect::render(WGPURenderPassEncoder pass, float t, float b, render_pass_.instance_count, 0, 0); } +// --- PostProcess Implementation Helper --- +static void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline, + WGPUBindGroup *bind_group, + WGPUTextureView input_view, + GpuBuffer uniforms) { + if (*bind_group) + wgpuBindGroupRelease(*bind_group); + WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline, 0); + WGPUSamplerDescriptor sd = {}; + sd.magFilter = WGPUFilterMode_Linear; + sd.minFilter = WGPUFilterMode_Linear; + sd.maxAnisotropy = 1; + WGPUSampler sampler = wgpuDeviceCreateSampler(device, &sd); + WGPUBindGroupEntry bge[3] = {}; + bge[0].binding = 0; + bge[0].sampler = sampler; + bge[1].binding = 1; + bge[1].textureView = input_view; + bge[2].binding = 2; + bge[2].buffer = uniforms.buffer; + bge[2].size = uniforms.size; + WGPUBindGroupDescriptor bgd = { + .layout = bgl, .entryCount = 3, .entries = bge}; + *bind_group = wgpuDeviceCreateBindGroup(device, &bgd); +} + // --- PassthroughEffect --- PassthroughEffect::PassthroughEffect(WGPUDevice device, WGPUTextureFormat format) : device_(device) { + uniforms_ = + gpu_create_buffer(device, sizeof(float) * 4, + WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst); pipeline_ = create_post_process_pipeline(device, format, passthrough_shader_wgsl); } void PassthroughEffect::update_bind_group(WGPUTextureView input_view) { - if (bind_group_) - wgpuBindGroupRelease(bind_group_); - WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0); - WGPUSamplerDescriptor sd = {}; - WGPUSampler sampler = wgpuDeviceCreateSampler(device_, &sd); - WGPUBindGroupEntry bge[2] = {}; - bge[0].binding = 0; - bge[0].sampler = sampler; - bge[1].binding = 1; - bge[1].textureView = input_view; - WGPUBindGroupDescriptor bgd = { - .layout = bgl, .entryCount = 2, .entries = bge}; - bind_group_ = wgpuDeviceCreateBindGroup(device_, &bgd); + pp_update_bind_group(device_, pipeline_, &bind_group_, input_view, uniforms_); } // --- MovingEllipseEffect --- @@ -404,31 +426,6 @@ void ParticleSprayEffect::render(WGPURenderPassEncoder pass, float t, float b, wgpuRenderPassEncoderDraw(pass, 6, NUM_PARTICLES, 0, 0); } -// --- PostProcess Implementation Helper --- -static void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline, - WGPUBindGroup *bind_group, - WGPUTextureView input_view, - GpuBuffer uniforms) { - if (*bind_group) - wgpuBindGroupRelease(*bind_group); - WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline, 0); - WGPUSamplerDescriptor sd = {}; - sd.magFilter = WGPUFilterMode_Linear; - sd.minFilter = WGPUFilterMode_Linear; - WGPUSampler sampler = wgpuDeviceCreateSampler(device, &sd); - WGPUBindGroupEntry bge[3] = {}; - bge[0].binding = 0; - bge[0].sampler = sampler; - bge[1].binding = 1; - bge[1].textureView = input_view; - bge[2].binding = 2; - bge[2].buffer = uniforms.buffer; - bge[2].size = uniforms.size; - WGPUBindGroupDescriptor bgd = { - .layout = bgl, .entryCount = 3, .entries = bge}; - *bind_group = wgpuDeviceCreateBindGroup(device, &bgd); -} - // --- GaussianBlurEffect --- GaussianBlurEffect::GaussianBlurEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) -- cgit v1.2.3