// This file is part of the 64k demo project. // It implements helper functions for post-processing effects. #include "../demo_effects.h" #include "gpu/gpu.h" #include // Helper to create a standard post-processing pipeline WGPURenderPipeline create_post_process_pipeline(WGPUDevice device, WGPUTextureFormat format, const char* shader_code) { WGPUShaderModuleDescriptor shader_desc = {}; WGPUShaderSourceWGSL wgsl_src = {}; wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; wgsl_src.code = str_view(shader_code); shader_desc.nextInChain = &wgsl_src.chain; WGPUShaderModule shader_module = wgpuDeviceCreateShaderModule(device, &shader_desc); WGPUBindGroupLayoutEntry bgl_entries[3] = {}; bgl_entries[0].binding = 0; bgl_entries[0].visibility = WGPUShaderStage_Fragment; bgl_entries[0].sampler.type = WGPUSamplerBindingType_Filtering; bgl_entries[1].binding = 1; bgl_entries[1].visibility = WGPUShaderStage_Fragment; bgl_entries[1].texture.sampleType = WGPUTextureSampleType_Float; bgl_entries[1].texture.viewDimension = WGPUTextureViewDimension_2D; bgl_entries[2].binding = 2; bgl_entries[2].visibility = WGPUShaderStage_Fragment; bgl_entries[2].buffer.type = WGPUBufferBindingType_Uniform; WGPUBindGroupLayoutDescriptor bgl_desc = {}; bgl_desc.entryCount = 3; bgl_desc.entries = bgl_entries; WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device, &bgl_desc); WGPUPipelineLayoutDescriptor pl_desc = {}; pl_desc.bindGroupLayoutCount = 1; pl_desc.bindGroupLayouts = &bgl; WGPUPipelineLayout pl = wgpuDeviceCreatePipelineLayout(device, &pl_desc); WGPUColorTargetState color_target = {}; color_target.format = format; color_target.writeMask = WGPUColorWriteMask_All; WGPUFragmentState fragment_state = {}; fragment_state.module = shader_module; fragment_state.entryPoint = str_view("fs_main"); fragment_state.targetCount = 1; fragment_state.targets = &color_target; WGPURenderPipelineDescriptor pipeline_desc = {}; pipeline_desc.layout = pl; pipeline_desc.vertex.module = shader_module; 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); } // --- PostProcess Implementation Helper --- 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); }