From 3252fff7aa131eaf826db19eede82ee9e70fecf5 Mon Sep 17 00:00:00 2001 From: skal Date: Sun, 8 Feb 2026 09:46:31 +0100 Subject: refactor(3d): Split Renderer3D into modular files and fix compilation. --- src/3d/renderer.cc | 235 +-------------------------------------- src/3d/renderer_draw.cc | 215 ++++++++++++++++++++++++++++++++++++ src/3d/renderer_mesh.cc | 204 ---------------------------------- src/3d/renderer_pipelines.cc | 255 +++++++++++++++++++++++++++++++++++++++++++ src/3d/renderer_resources.cc | 54 +++++++++ src/3d/renderer_sdf.cc | 158 --------------------------- src/3d/renderer_skybox.cc | 94 ---------------- 7 files changed, 525 insertions(+), 690 deletions(-) create mode 100644 src/3d/renderer_draw.cc delete mode 100644 src/3d/renderer_mesh.cc create mode 100644 src/3d/renderer_pipelines.cc create mode 100644 src/3d/renderer_resources.cc delete mode 100644 src/3d/renderer_sdf.cc delete mode 100644 src/3d/renderer_skybox.cc (limited to 'src') diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc index e08a0d0..d846895 100644 --- a/src/3d/renderer.cc +++ b/src/3d/renderer.cc @@ -106,25 +106,6 @@ void Renderer3D::resize(int width, int height) { depth_view_ = wgpuTextureCreateView(depth_texture_, &view_desc); } -void Renderer3D::create_default_resources() { - global_uniform_buffer_ = - gpu_create_buffer(device_, sizeof(GlobalUniforms), - WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, - nullptr) - .buffer; - object_storage_buffer_ = - gpu_create_buffer(device_, sizeof(ObjectData) * kMaxObjects, - WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, - nullptr) - .buffer; - bvh_storage_buffer_ = - gpu_create_buffer( - device_, - sizeof(BVHNode) * kMaxObjects * 2, // Capacity for a full tree - WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, nullptr) - .buffer; -} - void Renderer3D::set_noise_texture(WGPUTextureView noise_view) { noise_texture_view_ = noise_view; } @@ -140,223 +121,12 @@ void Renderer3D::add_debug_aabb(const vec3& min, const vec3& max, #endif } -void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera, - float time) { - GlobalUniforms globals; - globals.view_proj = camera.get_projection_matrix() * camera.get_view_matrix(); - globals.inv_view_proj = globals.view_proj.inverse(); - globals.camera_pos_time = - vec4(camera.position.x, camera.position.y, camera.position.z, time); - globals.params = - vec4((float)std::min((size_t)kMaxObjects, scene.objects.size()), 0.0f, - 0.0f, 0.0f); - globals.resolution = vec2((float)width_, (float)height_); - globals.padding = vec2(0.0f, 0.0f); - - wgpuQueueWriteBuffer(queue_, global_uniform_buffer_, 0, &globals, - sizeof(GlobalUniforms)); - - std::vector obj_data; - for (const auto& obj : scene.objects) { - ObjectData data; - data.model = obj.get_model_matrix(); - - // Calculate Inverse for point transformation - data.inv_model = data.model.inverse(); - - data.color = obj.color; - float type_id = 0.0f; - switch (obj.type) { - case ObjectType::SPHERE: - type_id = 1.0f; - break; - case ObjectType::BOX: - type_id = 2.0f; - break; - case ObjectType::CUBE: - type_id = 2.0f; - break; // CUBE is same as BOX for shader - case ObjectType::TORUS: - type_id = 3.0f; - break; - case ObjectType::PLANE: - type_id = 4.0f; - break; - case ObjectType::MESH: - type_id = 5.0f; - break; - default: - type_id = 0.0f; - break; - } - data.params = vec4(type_id, obj.local_extent.x, obj.local_extent.y, - obj.local_extent.z); - obj_data.push_back(data); - if (obj_data.size() >= kMaxObjects) - break; - } - if (!obj_data.empty()) { - wgpuQueueWriteBuffer(queue_, object_storage_buffer_, 0, obj_data.data(), - obj_data.size() * sizeof(ObjectData)); - } - - // Build and upload BVH (always uploaded, used by BVH pipeline) - BVHBuilder::build(cpu_bvh_, scene.objects); - if (!cpu_bvh_.nodes.empty()) { - wgpuQueueWriteBuffer(queue_, bvh_storage_buffer_, 0, cpu_bvh_.nodes.data(), - cpu_bvh_.nodes.size() * sizeof(BVHNode)); - } -} - -void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene, - const Camera& camera, float time) { - update_uniforms(scene, camera, time); - - // Lazy Bind Group creation - - if (bind_group_) - wgpuBindGroupRelease(bind_group_); - - std::vector bg_entries; - - { - WGPUBindGroupEntry e = {}; - e.binding = 0; - e.buffer = global_uniform_buffer_; - e.size = sizeof(GlobalUniforms); - bg_entries.push_back(e); - } - - { - WGPUBindGroupEntry e = {}; - e.binding = 1; - e.buffer = object_storage_buffer_; - e.size = sizeof(ObjectData) * kMaxObjects; - bg_entries.push_back(e); - } - - if (bvh_enabled_) { - WGPUBindGroupEntry e = {}; - e.binding = 2; - e.buffer = bvh_storage_buffer_; - e.size = sizeof(BVHNode) * kMaxObjects * 2; - bg_entries.push_back(e); - } - - { - WGPUBindGroupEntry e = {}; - e.binding = 3; - e.textureView = noise_texture_view_; - bg_entries.push_back(e); - } - - { - WGPUBindGroupEntry e = {}; - e.binding = 4; - e.sampler = default_sampler_; - bg_entries.push_back(e); - } - - { - WGPUBindGroupEntry e = {}; - e.binding = 5; - e.textureView = sky_texture_view_ ? sky_texture_view_ : noise_texture_view_; - bg_entries.push_back(e); - } - - // Select the correct pipeline and bind group layout - WGPURenderPipeline current_pipeline = - bvh_enabled_ ? pipeline_ : pipeline_no_bvh_; - WGPUBindGroupLayout current_layout = - wgpuRenderPipelineGetBindGroupLayout(current_pipeline, 0); - - WGPUBindGroupDescriptor bg_desc = {}; - bg_desc.layout = current_layout; - bg_desc.entryCount = (uint32_t)bg_entries.size(); - bg_desc.entries = bg_entries.data(); - - bind_group_ = wgpuDeviceCreateBindGroup(device_, &bg_desc); - - wgpuBindGroupLayoutRelease(current_layout); - - wgpuRenderPassEncoderSetPipeline(pass, current_pipeline); - - wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); - - uint32_t instance_count = - (uint32_t)std::min((size_t)kMaxObjects, scene.objects.size()); - - if (instance_count > 0) { - wgpuRenderPassEncoderSetPipeline(pass, current_pipeline); - wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); - wgpuRenderPassEncoderDraw(pass, 36, instance_count, 0, 0); - - // Mesh pass - if (mesh_pipeline_) { - wgpuRenderPassEncoderSetPipeline(pass, mesh_pipeline_); - // Bind group is the same layout - wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); - - for (uint32_t i = 0; i < instance_count; ++i) { - const auto& obj = scene.objects[i]; - if (obj.type == ObjectType::MESH) { - const MeshGpuData* mesh = temp_mesh_override_ - ? temp_mesh_override_ - : get_or_create_mesh(obj.mesh_asset_id); - if (mesh) { - wgpuRenderPassEncoderSetVertexBuffer(pass, 0, mesh->vertex_buffer, - 0, WGPU_WHOLE_SIZE); - wgpuRenderPassEncoderSetIndexBuffer(pass, mesh->index_buffer, - WGPUIndexFormat_Uint32, 0, - WGPU_WHOLE_SIZE); - wgpuRenderPassEncoderDrawIndexed(pass, mesh->num_indices, 1, 0, 0, - i); - } - } - } - } - } - -#if !defined(STRIP_ALL) - if (s_debug_enabled_) { - for (const auto& obj : scene.objects) { - vec3 extent = obj.local_extent; - if (obj.type == ObjectType::TORUS) { - extent = vec3(1.5f, 0.5f, 1.5f); - } else if (obj.type == ObjectType::MESH) { - MeshAsset mesh = GetMeshAsset(obj.mesh_asset_id); - if (mesh.num_indices > 0) { - visual_debug_.add_mesh_wireframe( - obj.get_model_matrix(), mesh.num_vertices, mesh.vertices, - mesh.num_indices, mesh.indices, - vec3(0.0f, 1.0f, 1.0f)); // Cyan wireframe - } - } else { - extent = vec3(1.0f, 1.0f, 1.0f); - } - - if (obj.type != ObjectType::MESH) { - visual_debug_.add_box(obj.get_model_matrix(), extent, - vec3(1.0f, 1.0f, 0.0f)); // Yellow boxes - } - } - - // Calculate ViewProj matrix for the debug renderer - mat4 view_proj = camera.get_projection_matrix() * camera.get_view_matrix(); - visual_debug_.render(pass, view_proj); - } -#endif -} - void Renderer3D::render(const Scene& scene, const Camera& camera, float time, - WGPUTextureView target_view, - WGPUTextureView depth_view_opt) { WGPUTextureView depth_view = depth_view_opt ? depth_view_opt : depth_view_; if (!depth_view) - return; WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device_, nullptr); @@ -444,10 +214,7 @@ void Renderer3D::render(const Scene& scene, const Camera& camera, float time, wgpuRenderPassEncoderRelease(obj_pass); WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, nullptr); - wgpuQueueSubmit(queue_, 1, &commands); - wgpuCommandBufferRelease(commands); - wgpuCommandEncoderRelease(encoder); -} \ No newline at end of file +} diff --git a/src/3d/renderer_draw.cc b/src/3d/renderer_draw.cc new file mode 100644 index 0000000..b50229f --- /dev/null +++ b/src/3d/renderer_draw.cc @@ -0,0 +1,215 @@ +// This file is part of the 64k demo project. +// It implements the drawing logic for Renderer3D. + +#include "3d/renderer.h" +#include "util/asset_manager_utils.h" +#include +#include + +void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera, + float time) { + GlobalUniforms globals; + globals.view_proj = camera.get_projection_matrix() * camera.get_view_matrix(); + globals.inv_view_proj = globals.view_proj.inverse(); + globals.camera_pos_time = + vec4(camera.position.x, camera.position.y, camera.position.z, time); + globals.params = + vec4((float)std::min((size_t)kMaxObjects, scene.objects.size()), 0.0f, + 0.0f, 0.0f); + globals.resolution = vec2((float)width_, (float)height_); + globals.padding = vec2(0.0f, 0.0f); + + wgpuQueueWriteBuffer(queue_, global_uniform_buffer_, 0, &globals, + sizeof(GlobalUniforms)); + + std::vector obj_data; + for (const auto& obj : scene.objects) { + ObjectData data; + data.model = obj.get_model_matrix(); + + // Calculate Inverse for point transformation + data.inv_model = data.model.inverse(); + + data.color = obj.color; + float type_id = 0.0f; + switch (obj.type) { + case ObjectType::SPHERE: + type_id = 1.0f; + break; + case ObjectType::BOX: + type_id = 2.0f; + break; + case ObjectType::CUBE: + type_id = 2.0f; + break; // CUBE is same as BOX for shader + case ObjectType::TORUS: + type_id = 3.0f; + break; + case ObjectType::PLANE: + type_id = 4.0f; + break; + case ObjectType::MESH: + type_id = 5.0f; + break; + default: + type_id = 0.0f; + break; + } + data.params = vec4(type_id, obj.local_extent.x, obj.local_extent.y, + obj.local_extent.z); + obj_data.push_back(data); + if (obj_data.size() >= kMaxObjects) + break; + } + if (!obj_data.empty()) { + wgpuQueueWriteBuffer(queue_, object_storage_buffer_, 0, obj_data.data(), + obj_data.size() * sizeof(ObjectData)); + } + + // Build and upload BVH (always uploaded, used by BVH pipeline) + BVHBuilder::build(cpu_bvh_, scene.objects); + if (!cpu_bvh_.nodes.empty()) { + wgpuQueueWriteBuffer(queue_, bvh_storage_buffer_, 0, cpu_bvh_.nodes.data(), + cpu_bvh_.nodes.size() * sizeof(BVHNode)); + } +} + +void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene, + const Camera& camera, float time) { + update_uniforms(scene, camera, time); + + // Lazy Bind Group creation + + if (bind_group_) + wgpuBindGroupRelease(bind_group_); + + std::vector bg_entries; + + { + WGPUBindGroupEntry e = {}; + e.binding = 0; + e.buffer = global_uniform_buffer_; + e.size = sizeof(GlobalUniforms); + bg_entries.push_back(e); + } + + { + WGPUBindGroupEntry e = {}; + e.binding = 1; + e.buffer = object_storage_buffer_; + e.size = sizeof(ObjectData) * kMaxObjects; + bg_entries.push_back(e); + } + + if (bvh_enabled_) { + WGPUBindGroupEntry e = {}; + e.binding = 2; + e.buffer = bvh_storage_buffer_; + e.size = sizeof(BVHNode) * kMaxObjects * 2; + bg_entries.push_back(e); + } + + { + WGPUBindGroupEntry e = {}; + e.binding = 3; + e.textureView = noise_texture_view_; + bg_entries.push_back(e); + } + + { + WGPUBindGroupEntry e = {}; + e.binding = 4; + e.sampler = default_sampler_; + bg_entries.push_back(e); + } + + { + WGPUBindGroupEntry e = {}; + e.binding = 5; + e.textureView = sky_texture_view_ ? sky_texture_view_ : noise_texture_view_; + bg_entries.push_back(e); + } + + // Select the correct pipeline and bind group layout + WGPURenderPipeline current_pipeline = + bvh_enabled_ ? pipeline_ : pipeline_no_bvh_; + WGPUBindGroupLayout current_layout = + wgpuRenderPipelineGetBindGroupLayout(current_pipeline, 0); + + WGPUBindGroupDescriptor bg_desc = {}; + bg_desc.layout = current_layout; + bg_desc.entryCount = (uint32_t)bg_entries.size(); + bg_desc.entries = bg_entries.data(); + + bind_group_ = wgpuDeviceCreateBindGroup(device_, &bg_desc); + + wgpuBindGroupLayoutRelease(current_layout); + + wgpuRenderPassEncoderSetPipeline(pass, current_pipeline); + + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + + uint32_t instance_count = + (uint32_t)std::min((size_t)kMaxObjects, scene.objects.size()); + + if (instance_count > 0) { + wgpuRenderPassEncoderSetPipeline(pass, current_pipeline); + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, 36, instance_count, 0, 0); + + // Mesh pass + if (mesh_pipeline_) { + wgpuRenderPassEncoderSetPipeline(pass, mesh_pipeline_); + // Bind group is the same layout + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + + for (uint32_t i = 0; i < instance_count; ++i) { + const auto& obj = scene.objects[i]; + if (obj.type == ObjectType::MESH) { + const MeshGpuData* mesh = temp_mesh_override_ + ? temp_mesh_override_ + : get_or_create_mesh(obj.mesh_asset_id); + if (mesh) { + wgpuRenderPassEncoderSetVertexBuffer(pass, 0, mesh->vertex_buffer, + 0, WGPU_WHOLE_SIZE); + wgpuRenderPassEncoderSetIndexBuffer(pass, mesh->index_buffer, + WGPUIndexFormat_Uint32, 0, + WGPU_WHOLE_SIZE); + wgpuRenderPassEncoderDrawIndexed(pass, mesh->num_indices, 1, 0, 0, + i); + } + } + } + } + } + +#if !defined(STRIP_ALL) + if (s_debug_enabled_) { + for (const auto& obj : scene.objects) { + vec3 extent = obj.local_extent; + if (obj.type == ObjectType::TORUS) { + extent = vec3(1.5f, 0.5f, 1.5f); + } else if (obj.type == ObjectType::MESH) { + MeshAsset mesh = GetMeshAsset(obj.mesh_asset_id); + if (mesh.num_indices > 0) { + visual_debug_.add_mesh_wireframe( + obj.get_model_matrix(), mesh.num_vertices, mesh.vertices, + mesh.num_indices, mesh.indices, + vec3(0.0f, 1.0f, 1.0f)); // Cyan wireframe + } + } else { + extent = vec3(1.0f, 1.0f, 1.0f); + } + + if (obj.type != ObjectType::MESH) { + visual_debug_.add_box(obj.get_model_matrix(), extent, + vec3(1.0f, 1.0f, 0.0f)); // Yellow boxes + } + } + + // Calculate ViewProj matrix for the debug renderer + mat4 view_proj = camera.get_projection_matrix() * camera.get_view_matrix(); + visual_debug_.render(pass, view_proj); + } +#endif +} diff --git a/src/3d/renderer_mesh.cc b/src/3d/renderer_mesh.cc deleted file mode 100644 index 7ef2b42..0000000 --- a/src/3d/renderer_mesh.cc +++ /dev/null @@ -1,204 +0,0 @@ -// This file is part of the 64k demo project. -// It implements mesh-related logic for Renderer3D. - -#include "3d/renderer.h" -#include "generated/assets.h" -#include "gpu/effects/shader_composer.h" -#include "util/asset_manager_utils.h" -#include -#include - -void Renderer3D::create_mesh_pipeline() { - 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 (Optional) - if (bvh_enabled_) { - 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* shader_code_asset = - (const char*)GetAsset(AssetId::ASSET_SHADER_MESH); - - ShaderComposer::CompositionMap composition_map; - if (bvh_enabled_) { - 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({}, shader_code_asset, 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); - - WGPUVertexAttribute vert_attrs[3] = {}; - // pos - vert_attrs[0].format = WGPUVertexFormat_Float32x3; - vert_attrs[0].offset = offsetof(MeshVertex, p); - vert_attrs[0].shaderLocation = 0; - // norm - vert_attrs[1].format = WGPUVertexFormat_Float32x3; - vert_attrs[1].offset = offsetof(MeshVertex, n); - vert_attrs[1].shaderLocation = 1; - // uv - vert_attrs[2].format = WGPUVertexFormat_Float32x2; - vert_attrs[2].offset = offsetof(MeshVertex, u); - vert_attrs[2].shaderLocation = 2; - - WGPUVertexBufferLayout vert_layout = {}; - vert_layout.arrayStride = sizeof(MeshVertex); - vert_layout.stepMode = WGPUVertexStepMode_Vertex; - vert_layout.attributeCount = 3; - vert_layout.attributes = vert_attrs; - - 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 - desc.vertex.bufferCount = 1; - desc.vertex.buffers = &vert_layout; - - 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; - - WGPUDepthStencilState depth_stencil = {}; - depth_stencil.format = WGPUTextureFormat_Depth24Plus; - depth_stencil.depthWriteEnabled = WGPUOptionalBool_True; - depth_stencil.depthCompare = WGPUCompareFunction_Less; - desc.depthStencil = &depth_stencil; - - desc.multisample.count = 1; - desc.multisample.mask = 0xFFFFFFFF; - - mesh_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &desc); - wgpuBindGroupLayoutRelease(bgl); - wgpuPipelineLayoutRelease(pipeline_layout); - wgpuShaderModuleRelease(shader_module); -} - -const Renderer3D::MeshGpuData* -Renderer3D::get_or_create_mesh(AssetId asset_id) { - auto it = mesh_cache_.find(asset_id); - if (it != mesh_cache_.end()) { - return &it->second; - } - - MeshAsset asset = GetMeshAsset(asset_id); - if (!asset.vertices || asset.num_vertices == 0) { - return nullptr; - } - - MeshGpuData data; - data.num_indices = asset.num_indices; - - data.vertex_buffer = - gpu_create_buffer(device_, asset.num_vertices * sizeof(MeshVertex), - WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst, - asset.vertices) - .buffer; - data.index_buffer = - gpu_create_buffer(device_, asset.num_indices * sizeof(uint32_t), - WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst, - asset.indices) - .buffer; - - mesh_cache_[asset_id] = data; - return &mesh_cache_[asset_id]; -} diff --git a/src/3d/renderer_pipelines.cc b/src/3d/renderer_pipelines.cc new file mode 100644 index 0000000..d0f1a7b --- /dev/null +++ b/src/3d/renderer_pipelines.cc @@ -0,0 +1,255 @@ +// This file is part of the 64k demo project. +// It implements the pipeline creation logic for Renderer3D. + +#include "3d/renderer.h" +#include "generated/assets.h" +#include "gpu/effects/shader_composer.h" +#include "util/asset_manager.h" +#include "util/asset_manager_utils.h" +#include + +void Renderer3D::create_pipeline() { + pipeline_ = create_pipeline_impl(true); + pipeline_no_bvh_ = create_pipeline_impl(false); + create_mesh_pipeline(); +} + +WGPURenderPipeline Renderer3D::create_pipeline_impl(bool use_bvh) { + // Main SDF shader + size_t size; + const char* shader_code = reinterpret_cast( + GetAsset(AssetId::ASSET_SHADER_RENDERER_3D, &size)); + + // Compose the final shader by substituting the scene query implementation + 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 composed_shader = ShaderComposer::Get().Compose( + {}, std::string(shader_code, size), composition_map); + + WGPUShaderSourceWGSL wgsl_src = {}; + wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; + wgsl_src.code = str_view(composed_shader.c_str()); + + WGPUShaderModuleDescriptor shader_desc = {}; + shader_desc.nextInChain = &wgsl_src.chain; + WGPUShaderModule shader_module = + wgpuDeviceCreateShaderModule(device_, &shader_desc); + + // BIND GROUP LAYOUT + std::vector bgl_entries; + bgl_entries.push_back({.binding = 0, // B0: uniforms + .visibility = WGPUShaderStage_Vertex | + WGPUShaderStage_Fragment, + .buffer = {.type = WGPUBufferBindingType_Uniform}}); + bgl_entries.push_back( + {.binding = 1, // B1: object storage + .visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment, + .buffer = {.type = WGPUBufferBindingType_ReadOnlyStorage}}); + if (use_bvh) { + bgl_entries.push_back( + {.binding = 2, // B2: bvh storage + .visibility = WGPUShaderStage_Fragment, + .buffer = {.type = WGPUBufferBindingType_ReadOnlyStorage}}); + } + bgl_entries.push_back({.binding = 3, // B3: noise texture + .visibility = WGPUShaderStage_Fragment, + .texture = {.sampleType = WGPUTextureSampleType_Float, + .viewDimension = + WGPUTextureViewDimension_2D}}); + bgl_entries.push_back({.binding = 4, // B4: default sampler + .visibility = WGPUShaderStage_Fragment, + .sampler = {.type = WGPUSamplerBindingType_Filtering}}); + bgl_entries.push_back({.binding = 5, // B5: sky texture + .visibility = WGPUShaderStage_Fragment, + .texture = {.sampleType = WGPUTextureSampleType_Float, + .viewDimension = + WGPUTextureViewDimension_2D}}); + + WGPUBindGroupLayoutDescriptor bgl_desc = {}; + bgl_desc.entryCount = bgl_entries.size(); + bgl_desc.entries = bgl_entries.data(); + WGPUBindGroupLayout bind_group_layout = + wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc); + + // PIPELINE LAYOUT + WGPUPipelineLayoutDescriptor pl_desc = {}; + pl_desc.bindGroupLayoutCount = 1; + pl_desc.bindGroupLayouts = &bind_group_layout; + WGPUPipelineLayout pipeline_layout = + wgpuDeviceCreatePipelineLayout(device_, &pl_desc); + + // PIPELINE + WGPUDepthStencilState depth_stencil = {}; + depth_stencil.format = WGPUTextureFormat_Depth24Plus; + depth_stencil.depthWriteEnabled = WGPUOptionalBool_True; + depth_stencil.depthCompare = WGPUCompareFunction_Less; + + 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 = pipeline_layout; + pipeline_desc.vertex.module = shader_module; + pipeline_desc.vertex.entryPoint = str_view("vs_main"); + pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList; + pipeline_desc.multisample.count = 1; + pipeline_desc.fragment = &fragment_state; + pipeline_desc.depthStencil = &depth_stencil; + + WGPURenderPipeline pipeline = + wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc); + + wgpuShaderModuleRelease(shader_module); + wgpuPipelineLayoutRelease(pipeline_layout); + wgpuBindGroupLayoutRelease(bind_group_layout); + + return pipeline; +} + +void Renderer3D::create_mesh_pipeline() { + size_t size; + const char* shader_code = reinterpret_cast( + GetAsset(AssetId::ASSET_SHADER_MESH, &size)); + + ShaderComposer::CompositionMap composition_map; + if (bvh_enabled_) { + composition_map["render/scene_query_mode"] = "render/scene_query_bvh"; + } else { + composition_map["render/scene_query_mode"] = "render/scene_query_linear"; + } + std::string composed_shader = ShaderComposer::Get().Compose( + {}, std::string(shader_code, size), composition_map); + + WGPUShaderSourceWGSL wgsl_src = {}; + wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; + wgsl_src.code = str_view(composed_shader.c_str()); + WGPUShaderModuleDescriptor shader_desc = {}; + shader_desc.nextInChain = &wgsl_src.chain; + WGPUShaderModule shader_module = + wgpuDeviceCreateShaderModule(device_, &shader_desc); + + WGPUBindGroupLayout bgl = + wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0); + WGPUPipelineLayoutDescriptor pl_desc = {}; + pl_desc.bindGroupLayoutCount = 1; + pl_desc.bindGroupLayouts = &bgl; + WGPUPipelineLayout pipeline_layout = + wgpuDeviceCreatePipelineLayout(device_, &pl_desc); + wgpuBindGroupLayoutRelease(bgl); + + WGPUDepthStencilState depth_stencil = {}; + depth_stencil.format = WGPUTextureFormat_Depth24Plus; + depth_stencil.depthWriteEnabled = WGPUOptionalBool_True; + depth_stencil.depthCompare = WGPUCompareFunction_Less; + + 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; + + WGPUVertexAttribute vert_attrs[3] = {}; + vert_attrs[0] = {.format = WGPUVertexFormat_Float32x3, .offset = offsetof(MeshVertex, p), .shaderLocation = 0}; + vert_attrs[1] = {.format = WGPUVertexFormat_Float32x3, .offset = offsetof(MeshVertex, n), .shaderLocation = 1}; + vert_attrs[2] = {.format = WGPUVertexFormat_Float32x2, .offset = offsetof(MeshVertex, u), .shaderLocation = 2}; + + WGPUVertexBufferLayout vert_buffer_layout = {}; + vert_buffer_layout.arrayStride = sizeof(MeshVertex); + vert_buffer_layout.stepMode = WGPUVertexStepMode_Vertex; + vert_buffer_layout.attributeCount = 3; + vert_buffer_layout.attributes = vert_attrs; + + WGPURenderPipelineDescriptor pipeline_desc = {}; + pipeline_desc.layout = pipeline_layout; + pipeline_desc.vertex.module = shader_module; + pipeline_desc.vertex.entryPoint = str_view("vs_main"); + pipeline_desc.vertex.bufferCount = 1; + pipeline_desc.vertex.buffers = &vert_buffer_layout; + pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList; + pipeline_desc.primitive.cullMode = WGPUCullMode_Back; + pipeline_desc.multisample.count = 1; + pipeline_desc.fragment = &fragment_state; + pipeline_desc.depthStencil = &depth_stencil; + + mesh_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc); + + wgpuShaderModuleRelease(shader_module); + wgpuPipelineLayoutRelease(pipeline_layout); +} + +void Renderer3D::create_skybox_pipeline() { + size_t size; + const char* shader_code = reinterpret_cast( + GetAsset(AssetId::ASSET_SHADER_SKYBOX, &size)); + + std::string composed_shader = ShaderComposer::Get().Compose( + {}, std::string(shader_code, size)); + + WGPUShaderSourceWGSL wgsl_src = {}; + wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; + wgsl_src.code = str_view(composed_shader.c_str()); + WGPUShaderModuleDescriptor shader_desc = {}; + shader_desc.nextInChain = &wgsl_src.chain; + WGPUShaderModule shader_module = + wgpuDeviceCreateShaderModule(device_, &shader_desc); + + WGPUBindGroupLayoutEntry bgl_entries[3] = {}; + bgl_entries[0] = {.binding=0, .visibility=WGPUShaderStage_Fragment, .texture={.sampleType=WGPUTextureSampleType_Float, .viewDimension=WGPUTextureViewDimension_2D}}; + bgl_entries[1] = {.binding=1, .visibility=WGPUShaderStage_Fragment, .sampler={.type=WGPUSamplerBindingType_Filtering}}; + bgl_entries[2] = {.binding=2, .visibility=WGPUShaderStage_Fragment, .buffer={.type=WGPUBufferBindingType_Uniform}}; + + WGPUBindGroupLayoutDescriptor bgl_desc = {}; + bgl_desc.entryCount = 3; + bgl_desc.entries = bgl_entries; + WGPUBindGroupLayout bind_group_layout = + wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc); + + WGPUPipelineLayoutDescriptor pl_desc = {}; + pl_desc.bindGroupLayoutCount = 1; + pl_desc.bindGroupLayouts = &bind_group_layout; + WGPUPipelineLayout pipeline_layout = + wgpuDeviceCreatePipelineLayout(device_, &pl_desc); + + WGPUDepthStencilState depth_stencil = {}; + depth_stencil.format = WGPUTextureFormat_Depth24Plus; + depth_stencil.depthWriteEnabled = WGPUOptionalBool_False; + depth_stencil.depthCompare = WGPUCompareFunction_Always; + + 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 = pipeline_layout; + pipeline_desc.vertex.module = shader_module; + pipeline_desc.vertex.entryPoint = str_view("vs_main"); + pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList; + pipeline_desc.multisample.count = 1; + pipeline_desc.fragment = &fragment_state; + pipeline_desc.depthStencil = &depth_stencil; + + skybox_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc); + + wgpuShaderModuleRelease(shader_module); + wgpuPipelineLayoutRelease(pipeline_layout); + wgpuBindGroupLayoutRelease(bind_group_layout); +} \ No newline at end of file diff --git a/src/3d/renderer_resources.cc b/src/3d/renderer_resources.cc new file mode 100644 index 0000000..2b001aa --- /dev/null +++ b/src/3d/renderer_resources.cc @@ -0,0 +1,54 @@ +// This file is part of the 64k demo project. +// It implements the resource management logic for Renderer3D. + +#include "3d/renderer.h" +#include "util/asset_manager_utils.h" + +void Renderer3D::create_default_resources() { + global_uniform_buffer_ = + gpu_create_buffer(device_, sizeof(GlobalUniforms), + WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, + nullptr) + .buffer; + object_storage_buffer_ = + gpu_create_buffer(device_, sizeof(ObjectData) * kMaxObjects, + WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, + nullptr) + .buffer; + bvh_storage_buffer_ = + gpu_create_buffer( + device_, + sizeof(BVHNode) * kMaxObjects * 2, // Capacity for a full tree + WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, nullptr) + .buffer; +} + +const Renderer3D::MeshGpuData* +Renderer3D::get_or_create_mesh(AssetId asset_id) { + auto it = mesh_cache_.find(asset_id); + if (it != mesh_cache_.end()) { + return &it->second; + } + + MeshAsset asset = GetMeshAsset(asset_id); + if (!asset.vertices || asset.num_vertices == 0) { + return nullptr; + } + + MeshGpuData data; + data.num_indices = asset.num_indices; + + data.vertex_buffer = + gpu_create_buffer(device_, asset.num_vertices * sizeof(MeshVertex), + WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst, + asset.vertices) + .buffer; + data.index_buffer = + gpu_create_buffer(device_, asset.num_indices * sizeof(uint32_t), + WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst, + asset.indices) + .buffer; + + mesh_cache_[asset_id] = data; + return &mesh_cache_[asset_id]; +} diff --git a/src/3d/renderer_sdf.cc b/src/3d/renderer_sdf.cc deleted file mode 100644 index d94df11..0000000 --- a/src/3d/renderer_sdf.cc +++ /dev/null @@ -1,158 +0,0 @@ -// 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; -} diff --git a/src/3d/renderer_skybox.cc b/src/3d/renderer_skybox.cc deleted file mode 100644 index 203cc07..0000000 --- a/src/3d/renderer_skybox.cc +++ /dev/null @@ -1,94 +0,0 @@ -// This file is part of the 64k demo project. -// It implements the skybox pipeline for Renderer3D. - -#include "3d/renderer.h" -#include "generated/assets.h" -#include "gpu/effects/shader_composer.h" -#include "util/asset_manager.h" - -void Renderer3D::create_skybox_pipeline() { - WGPUBindGroupLayoutEntry entries[3] = {}; - entries[0].binding = 0; - entries[0].visibility = WGPUShaderStage_Fragment; - entries[0].texture.sampleType = WGPUTextureSampleType_Float; - entries[0].texture.viewDimension = WGPUTextureViewDimension_2D; - - entries[1].binding = 1; - entries[1].visibility = WGPUShaderStage_Fragment; - entries[1].sampler.type = WGPUSamplerBindingType_Filtering; - - entries[2].binding = 2; - entries[2].visibility = WGPUShaderStage_Fragment; - entries[2].buffer.type = WGPUBufferBindingType_Uniform; - entries[2].buffer.minBindingSize = sizeof(GlobalUniforms); - - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 3; - bgl_desc.entries = entries; - 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 uint8_t* shader_code_asset = - GetAsset(AssetId::ASSET_SHADER_SKYBOX, nullptr); - std::string shader_source = - ShaderComposer::Get().Compose({}, (const char*)shader_code_asset); - -#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); - - 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.multisample.count = 1; - desc.multisample.mask = 0xFFFFFFFF; - - WGPUDepthStencilState depth_stencil = {}; - depth_stencil.format = WGPUTextureFormat_Depth24Plus; - depth_stencil.depthWriteEnabled = WGPUOptionalBool_False; - depth_stencil.depthCompare = WGPUCompareFunction_Always; - desc.depthStencil = &depth_stencil; - - skybox_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &desc); - wgpuBindGroupLayoutRelease(bgl); - wgpuPipelineLayoutRelease(pipeline_layout); - wgpuShaderModuleRelease(shader_module); -} -- cgit v1.2.3