// This file is part of the 64k demo project. // It implements SDF-related pipeline logic for Renderer3D. #include "3d/renderer.h" #include "generated/assets.h" #include "gpu/effects/shader_composer.h" #include "util/asset_manager.h" #include void Renderer3D::create_pipeline() { pipeline_ = create_pipeline_impl(true); // BVH enabled pipeline_no_bvh_ = create_pipeline_impl(false); // BVH disabled create_mesh_pipeline(); } WGPURenderPipeline Renderer3D::create_pipeline_impl(bool use_bvh) { std::vector entries; // Binding 0: Global Uniforms { WGPUBindGroupLayoutEntry e = {}; e.binding = 0; e.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; e.buffer.type = WGPUBufferBindingType_Uniform; e.buffer.minBindingSize = sizeof(GlobalUniforms); entries.push_back(e); } // Binding 1: Object Data { WGPUBindGroupLayoutEntry e = {}; e.binding = 1; e.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; e.buffer.type = WGPUBufferBindingType_ReadOnlyStorage; e.buffer.minBindingSize = sizeof(ObjectData) * kMaxObjects; entries.push_back(e); } // Binding 2: BVH Nodes (only if BVH is used) if (use_bvh) { WGPUBindGroupLayoutEntry e = {}; e.binding = 2; e.visibility = WGPUShaderStage_Fragment; e.buffer.type = WGPUBufferBindingType_ReadOnlyStorage; e.buffer.minBindingSize = sizeof(BVHNode) * kMaxObjects * 2; entries.push_back(e); } // Binding 3: Noise Texture { WGPUBindGroupLayoutEntry e = {}; e.binding = 3; e.visibility = WGPUShaderStage_Fragment; e.texture.sampleType = WGPUTextureSampleType_Float; e.texture.viewDimension = WGPUTextureViewDimension_2D; entries.push_back(e); } // Binding 4: Default Sampler { WGPUBindGroupLayoutEntry e = {}; e.binding = 4; e.visibility = WGPUShaderStage_Fragment; e.sampler.type = WGPUSamplerBindingType_Filtering; entries.push_back(e); } // Binding 5: Sky Texture { WGPUBindGroupLayoutEntry e = {}; e.binding = 5; e.visibility = WGPUShaderStage_Fragment; e.texture.sampleType = WGPUTextureSampleType_Float; e.texture.viewDimension = WGPUTextureViewDimension_2D; entries.push_back(e); } WGPUBindGroupLayoutDescriptor bgl_desc = {}; bgl_desc.entryCount = (uint32_t)entries.size(); bgl_desc.entries = entries.data(); WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc); WGPUPipelineLayoutDescriptor pl_desc = {}; pl_desc.bindGroupLayoutCount = 1; pl_desc.bindGroupLayouts = &bgl; WGPUPipelineLayout pipeline_layout = wgpuDeviceCreatePipelineLayout(device_, &pl_desc); const char* asset_data = (const char*)GetAsset(AssetId::ASSET_SHADER_RENDERER_3D); std::string main_code = asset_data; // Use ShaderComposer to dynamically include the correct scene_query snippet ShaderComposer::CompositionMap composition_map; if (use_bvh) { composition_map["render/scene_query_mode"] = "render/scene_query_bvh"; } else { composition_map["render/scene_query_mode"] = "render/scene_query_linear"; } std::string shader_source = ShaderComposer::Get().Compose({}, main_code, composition_map); #if defined(DEMO_CROSS_COMPILE_WIN32) WGPUShaderModuleWGSLDescriptor wgsl_desc = {}; wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; wgsl_desc.code = shader_source.c_str(); WGPUShaderModuleDescriptor shader_desc = {}; shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain; #else WGPUShaderSourceWGSL wgsl_desc = {}; wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL; wgsl_desc.code = str_view(shader_source.c_str()); WGPUShaderModuleDescriptor shader_desc = {}; shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain; #endif WGPUShaderModule shader_module = wgpuDeviceCreateShaderModule(device_, &shader_desc); WGPUDepthStencilState depth_stencil = {}; depth_stencil.format = WGPUTextureFormat_Depth24Plus; depth_stencil.depthWriteEnabled = WGPUOptionalBool_True; depth_stencil.depthCompare = WGPUCompareFunction_Less; WGPURenderPipelineDescriptor desc = {}; desc.layout = pipeline_layout; desc.vertex.module = shader_module; #if defined(DEMO_CROSS_COMPILE_WIN32) desc.vertex.entryPoint = "vs_main"; #else desc.vertex.entryPoint = {"vs_main", 7}; #endif WGPUColorTargetState color_target = {}; color_target.format = format_; color_target.writeMask = WGPUColorWriteMask_All; WGPUFragmentState fragment = {}; fragment.module = shader_module; #if defined(DEMO_CROSS_COMPILE_WIN32) fragment.entryPoint = "fs_main"; #else fragment.entryPoint = {"fs_main", 7}; #endif fragment.targetCount = 1; fragment.targets = &color_target; desc.fragment = &fragment; desc.primitive.topology = WGPUPrimitiveTopology_TriangleList; desc.primitive.cullMode = WGPUCullMode_Back; desc.primitive.frontFace = WGPUFrontFace_CCW; desc.depthStencil = &depth_stencil; desc.multisample.count = 1; desc.multisample.mask = 0xFFFFFFFF; WGPURenderPipeline pipeline = wgpuDeviceCreateRenderPipeline(device_, &desc); wgpuBindGroupLayoutRelease(bgl); wgpuPipelineLayoutRelease(pipeline_layout); wgpuShaderModuleRelease(shader_module); return pipeline; }