diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gpu/texture_manager.cc | 487 | ||||
| -rw-r--r-- | src/gpu/texture_manager.h | 23 |
2 files changed, 144 insertions, 366 deletions
diff --git a/src/gpu/texture_manager.cc b/src/gpu/texture_manager.cc index 9a19957..2b83f63 100644 --- a/src/gpu/texture_manager.cc +++ b/src/gpu/texture_manager.cc @@ -21,9 +21,6 @@ void TextureManager::init(WGPUDevice device, WGPUQueue queue) { device_ = device; queue_ = queue; - noise_compute_pipeline_ = nullptr; - perlin_compute_pipeline_ = nullptr; - grid_compute_pipeline_ = nullptr; } void TextureManager::shutdown() { @@ -32,18 +29,13 @@ void TextureManager::shutdown() { wgpuTextureRelease(pair.second.texture); } textures_.clear(); - if (noise_compute_pipeline_) { - wgpuComputePipelineRelease(noise_compute_pipeline_); - noise_compute_pipeline_ = nullptr; - } - if (perlin_compute_pipeline_) { - wgpuComputePipelineRelease(perlin_compute_pipeline_); - perlin_compute_pipeline_ = nullptr; - } - if (grid_compute_pipeline_) { - wgpuComputePipelineRelease(grid_compute_pipeline_); - grid_compute_pipeline_ = nullptr; + + for (auto& pair : compute_pipelines_) { + if (pair.second.pipeline) { + wgpuComputePipelineRelease(pair.second.pipeline); + } } + compute_pipelines_.clear(); } void TextureManager::create_procedural_texture( @@ -131,78 +123,90 @@ WGPUTextureView TextureManager::get_texture_view(const std::string& name) { return nullptr; } -void TextureManager::dispatch_noise_compute(WGPUTexture target, - const GpuProceduralParams& params) { - // Lazy-init compute pipeline - if (!noise_compute_pipeline_) { - extern const char* gen_noise_compute_wgsl; +WGPUComputePipeline TextureManager::get_or_create_compute_pipeline( + const std::string& func_name, const char* shader_code, + size_t uniform_size) { + auto it = compute_pipelines_.find(func_name); + if (it != compute_pipelines_.end()) { + return it->second.pipeline; + } + + // Create new pipeline + ShaderComposer& composer = ShaderComposer::Get(); + std::string resolved_shader = composer.Compose({}, shader_code); + + WGPUShaderSourceWGSL wgsl_src = {}; + wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; + wgsl_src.code = str_view(resolved_shader.c_str()); + WGPUShaderModuleDescriptor shader_desc = {}; + shader_desc.nextInChain = &wgsl_src.chain; + WGPUShaderModule shader_module = + wgpuDeviceCreateShaderModule(device_, &shader_desc); + + // Bind group layout (storage texture + uniform) + WGPUBindGroupLayoutEntry bgl_entries[2] = {}; + bgl_entries[0].binding = 0; + bgl_entries[0].visibility = WGPUShaderStage_Compute; + bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly; + bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm; + bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D; - // Resolve #include directives using ShaderComposer - ShaderComposer& composer = ShaderComposer::Get(); - std::string resolved_shader = composer.Compose({}, gen_noise_compute_wgsl); + bgl_entries[1].binding = 1; + bgl_entries[1].visibility = WGPUShaderStage_Compute; + bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform; + bgl_entries[1].buffer.minBindingSize = uniform_size; - WGPUShaderSourceWGSL wgsl_src = {}; - wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; - wgsl_src.code = str_view(resolved_shader.c_str()); - WGPUShaderModuleDescriptor shader_desc = {}; - shader_desc.nextInChain = &wgsl_src.chain; - WGPUShaderModule shader_module = - wgpuDeviceCreateShaderModule(device_, &shader_desc); + WGPUBindGroupLayoutDescriptor bgl_desc = {}; + bgl_desc.entryCount = 2; + bgl_desc.entries = bgl_entries; + WGPUBindGroupLayout bind_group_layout = + wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc); - // Bind group layout (storage texture + uniform) - WGPUBindGroupLayoutEntry bgl_entries[2] = {}; - bgl_entries[0].binding = 0; - bgl_entries[0].visibility = WGPUShaderStage_Compute; - bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly; - bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm; - bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D; + WGPUPipelineLayoutDescriptor pl_desc = {}; + pl_desc.bindGroupLayoutCount = 1; + pl_desc.bindGroupLayouts = &bind_group_layout; + WGPUPipelineLayout pipeline_layout = + wgpuDeviceCreatePipelineLayout(device_, &pl_desc); - bgl_entries[1].binding = 1; - bgl_entries[1].visibility = WGPUShaderStage_Compute; - bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[1].buffer.minBindingSize = 16; // sizeof(NoiseParams) + WGPUComputePipelineDescriptor pipeline_desc = {}; + pipeline_desc.layout = pipeline_layout; + pipeline_desc.compute.module = shader_module; + pipeline_desc.compute.entryPoint = str_view("main"); - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 2; - bgl_desc.entries = bgl_entries; - WGPUBindGroupLayout bind_group_layout = - wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc); + WGPUComputePipeline pipeline = + wgpuDeviceCreateComputePipeline(device_, &pipeline_desc); - WGPUPipelineLayoutDescriptor pl_desc = {}; - pl_desc.bindGroupLayoutCount = 1; - pl_desc.bindGroupLayouts = &bind_group_layout; - WGPUPipelineLayout pipeline_layout = - wgpuDeviceCreatePipelineLayout(device_, &pl_desc); + wgpuPipelineLayoutRelease(pipeline_layout); + wgpuBindGroupLayoutRelease(bind_group_layout); + wgpuShaderModuleRelease(shader_module); - WGPUComputePipelineDescriptor pipeline_desc = {}; - pipeline_desc.layout = pipeline_layout; - pipeline_desc.compute.module = shader_module; - pipeline_desc.compute.entryPoint = str_view("main"); + // Cache pipeline + ComputePipelineInfo info = {pipeline, shader_code, uniform_size}; + compute_pipelines_[func_name] = info; - noise_compute_pipeline_ = - wgpuDeviceCreateComputePipeline(device_, &pipeline_desc); + return pipeline; +} - wgpuPipelineLayoutRelease(pipeline_layout); - wgpuBindGroupLayoutRelease(bind_group_layout); - wgpuShaderModuleRelease(shader_module); +void TextureManager::dispatch_compute(const std::string& func_name, + WGPUTexture target, + const GpuProceduralParams& params, + const void* uniform_data, + size_t uniform_size) { + auto it = compute_pipelines_.find(func_name); + if (it == compute_pipelines_.end()) { + return; // Pipeline not created yet } - // Create uniform buffer (width, height, seed, frequency) - struct NoiseParams { - uint32_t width; - uint32_t height; - float seed; - float frequency; - }; - NoiseParams uniform_data = {(uint32_t)params.width, (uint32_t)params.height, - params.params[0], params.params[1]}; + WGPUComputePipeline pipeline = it->second.pipeline; + + // Create uniform buffer WGPUBufferDescriptor buf_desc = {}; - buf_desc.size = sizeof(NoiseParams); + buf_desc.size = uniform_size; buf_desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst; buf_desc.mappedAtCreation = WGPUOptionalBool_True; WGPUBuffer uniform_buf = wgpuDeviceCreateBuffer(device_, &buf_desc); - void* mapped = wgpuBufferGetMappedRange(uniform_buf, 0, sizeof(NoiseParams)); - memcpy(mapped, &uniform_data, sizeof(NoiseParams)); + void* mapped = wgpuBufferGetMappedRange(uniform_buf, 0, uniform_size); + memcpy(mapped, uniform_data, uniform_size); wgpuBufferUnmap(uniform_buf); // Create storage texture view @@ -223,7 +227,7 @@ void TextureManager::dispatch_noise_compute(WGPUTexture target, bgl_entries[1].binding = 1; bgl_entries[1].visibility = WGPUShaderStage_Compute; bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[1].buffer.minBindingSize = 16; + bgl_entries[1].buffer.minBindingSize = uniform_size; WGPUBindGroupLayoutDescriptor bgl_desc = {}; bgl_desc.entryCount = 2; @@ -237,7 +241,7 @@ void TextureManager::dispatch_noise_compute(WGPUTexture target, bg_entries[0].textureView = target_view; bg_entries[1].binding = 1; bg_entries[1].buffer = uniform_buf; - bg_entries[1].size = sizeof(NoiseParams); + bg_entries[1].size = uniform_size; WGPUBindGroupDescriptor bg_desc = {}; bg_desc.layout = bind_group_layout; @@ -247,9 +251,11 @@ void TextureManager::dispatch_noise_compute(WGPUTexture target, // Dispatch compute WGPUCommandEncoderDescriptor enc_desc = {}; - WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device_, &enc_desc); - WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr); - wgpuComputePassEncoderSetPipeline(pass, noise_compute_pipeline_); + WGPUCommandEncoder encoder = + wgpuDeviceCreateCommandEncoder(device_, &enc_desc); + WGPUComputePassEncoder pass = + wgpuCommandEncoderBeginComputePass(encoder, nullptr); + wgpuComputePassEncoderSetPipeline(pass, pipeline); wgpuComputePassEncoderSetBindGroup(pass, 0, bind_group, 0, nullptr); wgpuComputePassEncoderDispatchWorkgroups(pass, (params.width + 7) / 8, (params.height + 7) / 8, 1); @@ -271,7 +277,9 @@ void TextureManager::dispatch_noise_compute(WGPUTexture target, void TextureManager::create_gpu_noise_texture( const std::string& name, const GpuProceduralParams& params) { - // Create storage texture + extern const char* gen_noise_compute_wgsl; + get_or_create_compute_pipeline("gen_noise", gen_noise_compute_wgsl, 16); + WGPUTextureDescriptor tex_desc = {}; tex_desc.usage = WGPUTextureUsage_StorageBinding | WGPUTextureUsage_TextureBinding; @@ -282,10 +290,16 @@ void TextureManager::create_gpu_noise_texture( tex_desc.sampleCount = 1; WGPUTexture texture = wgpuDeviceCreateTexture(device_, &tex_desc); - // Generate via compute - dispatch_noise_compute(texture, params); + struct NoiseParams { + uint32_t width; + uint32_t height; + float seed; + float frequency; + }; + NoiseParams uniforms = {(uint32_t)params.width, (uint32_t)params.height, + params.params[0], params.params[1]}; + dispatch_compute("gen_noise", texture, params, &uniforms, sizeof(NoiseParams)); - // Create view for sampling WGPUTextureViewDescriptor view_desc = {}; view_desc.format = WGPUTextureFormat_RGBA8Unorm; view_desc.dimension = WGPUTextureViewDimension_2D; @@ -293,7 +307,6 @@ void TextureManager::create_gpu_noise_texture( view_desc.arrayLayerCount = 1; WGPUTextureView view = wgpuTextureCreateView(texture, &view_desc); - // Store texture GpuTexture gpu_tex; gpu_tex.texture = texture; gpu_tex.view = view; @@ -307,59 +320,21 @@ void TextureManager::create_gpu_noise_texture( #endif } -void TextureManager::dispatch_perlin_compute(WGPUTexture target, - const GpuProceduralParams& params) { - // Lazy-init compute pipeline - if (!perlin_compute_pipeline_) { - extern const char* gen_perlin_compute_wgsl; - ShaderComposer& composer = ShaderComposer::Get(); - std::string resolved_shader = composer.Compose({}, gen_perlin_compute_wgsl); - - WGPUShaderSourceWGSL wgsl_src = {}; - wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; - wgsl_src.code = str_view(resolved_shader.c_str()); - WGPUShaderModuleDescriptor shader_desc = {}; - shader_desc.nextInChain = &wgsl_src.chain; - WGPUShaderModule shader_module = - wgpuDeviceCreateShaderModule(device_, &shader_desc); - - WGPUBindGroupLayoutEntry bgl_entries[2] = {}; - bgl_entries[0].binding = 0; - bgl_entries[0].visibility = WGPUShaderStage_Compute; - bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly; - bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm; - bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D; - bgl_entries[1].binding = 1; - bgl_entries[1].visibility = WGPUShaderStage_Compute; - bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[1].buffer.minBindingSize = 32; // sizeof(PerlinParams) - - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 2; - 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); - - WGPUComputePipelineDescriptor pipeline_desc = {}; - pipeline_desc.layout = pipeline_layout; - pipeline_desc.compute.module = shader_module; - pipeline_desc.compute.entryPoint = str_view("main"); - - perlin_compute_pipeline_ = - wgpuDeviceCreateComputePipeline(device_, &pipeline_desc); +void TextureManager::create_gpu_perlin_texture( + const std::string& name, const GpuProceduralParams& params) { + extern const char* gen_perlin_compute_wgsl; + get_or_create_compute_pipeline("gen_perlin", gen_perlin_compute_wgsl, 32); - wgpuPipelineLayoutRelease(pipeline_layout); - wgpuBindGroupLayoutRelease(bind_group_layout); - wgpuShaderModuleRelease(shader_module); - } + WGPUTextureDescriptor tex_desc = {}; + tex_desc.usage = + WGPUTextureUsage_StorageBinding | WGPUTextureUsage_TextureBinding; + tex_desc.dimension = WGPUTextureDimension_2D; + tex_desc.size = {(uint32_t)params.width, (uint32_t)params.height, 1}; + tex_desc.format = WGPUTextureFormat_RGBA8Unorm; + tex_desc.mipLevelCount = 1; + tex_desc.sampleCount = 1; + WGPUTexture texture = wgpuDeviceCreateTexture(device_, &tex_desc); - // Create uniform buffer struct PerlinParams { uint32_t width; uint32_t height; @@ -370,98 +345,17 @@ void TextureManager::dispatch_perlin_compute(WGPUTexture target, uint32_t octaves; float _pad0; }; - PerlinParams uniform_data = { + PerlinParams uniforms = { (uint32_t)params.width, (uint32_t)params.height, - params.params[0], // seed - params.params[1], // frequency - params.num_params > 2 ? params.params[2] : 1.0f, // amplitude - params.num_params > 3 ? params.params[3] : 0.5f, // amplitude_decay - params.num_params > 4 ? (uint32_t)params.params[4] : 4u, // octaves - 0.0f // padding - }; - - WGPUBufferDescriptor buf_desc = {}; - buf_desc.size = sizeof(PerlinParams); - buf_desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst; - buf_desc.mappedAtCreation = WGPUOptionalBool_True; - WGPUBuffer uniform_buf = wgpuDeviceCreateBuffer(device_, &buf_desc); - void* mapped = wgpuBufferGetMappedRange(uniform_buf, 0, sizeof(PerlinParams)); - memcpy(mapped, &uniform_data, sizeof(PerlinParams)); - wgpuBufferUnmap(uniform_buf); - - WGPUTextureViewDescriptor view_desc = {}; - view_desc.format = WGPUTextureFormat_RGBA8Unorm; - view_desc.dimension = WGPUTextureViewDimension_2D; - view_desc.mipLevelCount = 1; - view_desc.arrayLayerCount = 1; - WGPUTextureView target_view = wgpuTextureCreateView(target, &view_desc); - - WGPUBindGroupLayoutEntry bgl_entries[2] = {}; - bgl_entries[0].binding = 0; - bgl_entries[0].visibility = WGPUShaderStage_Compute; - bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly; - bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm; - bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D; - bgl_entries[1].binding = 1; - bgl_entries[1].visibility = WGPUShaderStage_Compute; - bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[1].buffer.minBindingSize = 32; - - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 2; - bgl_desc.entries = bgl_entries; - WGPUBindGroupLayout bind_group_layout = - wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc); - - WGPUBindGroupEntry bg_entries[2] = {}; - bg_entries[0].binding = 0; - bg_entries[0].textureView = target_view; - bg_entries[1].binding = 1; - bg_entries[1].buffer = uniform_buf; - bg_entries[1].size = sizeof(PerlinParams); - - WGPUBindGroupDescriptor bg_desc = {}; - bg_desc.layout = bind_group_layout; - bg_desc.entryCount = 2; - bg_desc.entries = bg_entries; - WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup(device_, &bg_desc); - - WGPUCommandEncoderDescriptor enc_desc = {}; - WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device_, &enc_desc); - WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr); - wgpuComputePassEncoderSetPipeline(pass, perlin_compute_pipeline_); - wgpuComputePassEncoderSetBindGroup(pass, 0, bind_group, 0, nullptr); - wgpuComputePassEncoderDispatchWorkgroups(pass, (params.width + 7) / 8, - (params.height + 7) / 8, 1); - wgpuComputePassEncoderEnd(pass); - - WGPUCommandBufferDescriptor cmd_desc = {}; - WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, &cmd_desc); - wgpuQueueSubmit(queue_, 1, &cmd); - - wgpuCommandBufferRelease(cmd); - wgpuCommandEncoderRelease(encoder); - wgpuComputePassEncoderRelease(pass); - wgpuBindGroupRelease(bind_group); - wgpuBindGroupLayoutRelease(bind_group_layout); - wgpuBufferRelease(uniform_buf); - wgpuTextureViewRelease(target_view); -} - -void TextureManager::create_gpu_perlin_texture( - const std::string& name, const GpuProceduralParams& params) { - WGPUTextureDescriptor tex_desc = {}; - tex_desc.usage = - WGPUTextureUsage_StorageBinding | WGPUTextureUsage_TextureBinding; - tex_desc.dimension = WGPUTextureDimension_2D; - tex_desc.size = {(uint32_t)params.width, (uint32_t)params.height, 1}; - tex_desc.format = WGPUTextureFormat_RGBA8Unorm; - tex_desc.mipLevelCount = 1; - tex_desc.sampleCount = 1; - WGPUTexture texture = wgpuDeviceCreateTexture(device_, &tex_desc); - - dispatch_perlin_compute(texture, params); + params.params[0], + params.params[1], + params.num_params > 2 ? params.params[2] : 1.0f, + params.num_params > 3 ? params.params[3] : 0.5f, + params.num_params > 4 ? (uint32_t)params.params[4] : 4u, + 0.0f}; + dispatch_compute("gen_perlin", texture, params, &uniforms, + sizeof(PerlinParams)); WGPUTextureViewDescriptor view_desc = {}; view_desc.format = WGPUTextureFormat_RGBA8Unorm; @@ -483,142 +377,11 @@ void TextureManager::create_gpu_perlin_texture( #endif } -void TextureManager::dispatch_grid_compute(WGPUTexture target, - const GpuProceduralParams& params) { - // Lazy-init compute pipeline - if (!grid_compute_pipeline_) { - extern const char* gen_grid_compute_wgsl; - ShaderComposer& composer = ShaderComposer::Get(); - std::string resolved_shader = composer.Compose({}, gen_grid_compute_wgsl); - - WGPUShaderSourceWGSL wgsl_src = {}; - wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; - wgsl_src.code = str_view(resolved_shader.c_str()); - WGPUShaderModuleDescriptor shader_desc = {}; - shader_desc.nextInChain = &wgsl_src.chain; - WGPUShaderModule shader_module = - wgpuDeviceCreateShaderModule(device_, &shader_desc); - - WGPUBindGroupLayoutEntry bgl_entries[2] = {}; - bgl_entries[0].binding = 0; - bgl_entries[0].visibility = WGPUShaderStage_Compute; - bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly; - bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm; - bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D; - bgl_entries[1].binding = 1; - bgl_entries[1].visibility = WGPUShaderStage_Compute; - bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[1].buffer.minBindingSize = 16; // sizeof(GridParams) - - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 2; - 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); - - WGPUComputePipelineDescriptor pipeline_desc = {}; - pipeline_desc.layout = pipeline_layout; - pipeline_desc.compute.module = shader_module; - pipeline_desc.compute.entryPoint = str_view("main"); - - grid_compute_pipeline_ = - wgpuDeviceCreateComputePipeline(device_, &pipeline_desc); - - wgpuPipelineLayoutRelease(pipeline_layout); - wgpuBindGroupLayoutRelease(bind_group_layout); - wgpuShaderModuleRelease(shader_module); - } - - // Create uniform buffer - struct GridParams { - uint32_t width; - uint32_t height; - uint32_t grid_size; - uint32_t thickness; - }; - GridParams uniform_data = { - (uint32_t)params.width, - (uint32_t)params.height, - params.num_params > 0 ? (uint32_t)params.params[0] : 32u, // grid_size - params.num_params > 1 ? (uint32_t)params.params[1] : 2u // thickness - }; - - WGPUBufferDescriptor buf_desc = {}; - buf_desc.size = sizeof(GridParams); - buf_desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst; - buf_desc.mappedAtCreation = WGPUOptionalBool_True; - WGPUBuffer uniform_buf = wgpuDeviceCreateBuffer(device_, &buf_desc); - void* mapped = wgpuBufferGetMappedRange(uniform_buf, 0, sizeof(GridParams)); - memcpy(mapped, &uniform_data, sizeof(GridParams)); - wgpuBufferUnmap(uniform_buf); - - WGPUTextureViewDescriptor view_desc = {}; - view_desc.format = WGPUTextureFormat_RGBA8Unorm; - view_desc.dimension = WGPUTextureViewDimension_2D; - view_desc.mipLevelCount = 1; - view_desc.arrayLayerCount = 1; - WGPUTextureView target_view = wgpuTextureCreateView(target, &view_desc); - - WGPUBindGroupLayoutEntry bgl_entries[2] = {}; - bgl_entries[0].binding = 0; - bgl_entries[0].visibility = WGPUShaderStage_Compute; - bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly; - bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm; - bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D; - bgl_entries[1].binding = 1; - bgl_entries[1].visibility = WGPUShaderStage_Compute; - bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[1].buffer.minBindingSize = 16; - - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 2; - bgl_desc.entries = bgl_entries; - WGPUBindGroupLayout bind_group_layout = - wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc); - - WGPUBindGroupEntry bg_entries[2] = {}; - bg_entries[0].binding = 0; - bg_entries[0].textureView = target_view; - bg_entries[1].binding = 1; - bg_entries[1].buffer = uniform_buf; - bg_entries[1].size = sizeof(GridParams); - - WGPUBindGroupDescriptor bg_desc = {}; - bg_desc.layout = bind_group_layout; - bg_desc.entryCount = 2; - bg_desc.entries = bg_entries; - WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup(device_, &bg_desc); - - WGPUCommandEncoderDescriptor enc_desc = {}; - WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device_, &enc_desc); - WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr); - wgpuComputePassEncoderSetPipeline(pass, grid_compute_pipeline_); - wgpuComputePassEncoderSetBindGroup(pass, 0, bind_group, 0, nullptr); - wgpuComputePassEncoderDispatchWorkgroups(pass, (params.width + 7) / 8, - (params.height + 7) / 8, 1); - wgpuComputePassEncoderEnd(pass); - - WGPUCommandBufferDescriptor cmd_desc = {}; - WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, &cmd_desc); - wgpuQueueSubmit(queue_, 1, &cmd); - - wgpuCommandBufferRelease(cmd); - wgpuCommandEncoderRelease(encoder); - wgpuComputePassEncoderRelease(pass); - wgpuBindGroupRelease(bind_group); - wgpuBindGroupLayoutRelease(bind_group_layout); - wgpuBufferRelease(uniform_buf); - wgpuTextureViewRelease(target_view); -} - void TextureManager::create_gpu_grid_texture( const std::string& name, const GpuProceduralParams& params) { + extern const char* gen_grid_compute_wgsl; + get_or_create_compute_pipeline("gen_grid", gen_grid_compute_wgsl, 16); + WGPUTextureDescriptor tex_desc = {}; tex_desc.usage = WGPUTextureUsage_StorageBinding | WGPUTextureUsage_TextureBinding; @@ -629,7 +392,17 @@ void TextureManager::create_gpu_grid_texture( tex_desc.sampleCount = 1; WGPUTexture texture = wgpuDeviceCreateTexture(device_, &tex_desc); - dispatch_grid_compute(texture, params); + struct GridParams { + uint32_t width; + uint32_t height; + uint32_t grid_size; + uint32_t thickness; + }; + GridParams uniforms = { + (uint32_t)params.width, (uint32_t)params.height, + params.num_params > 0 ? (uint32_t)params.params[0] : 32u, + params.num_params > 1 ? (uint32_t)params.params[1] : 2u}; + dispatch_compute("gen_grid", texture, params, &uniforms, sizeof(GridParams)); WGPUTextureViewDescriptor view_desc = {}; view_desc.format = WGPUTextureFormat_RGBA8Unorm; diff --git a/src/gpu/texture_manager.h b/src/gpu/texture_manager.h index b2dea84..63c2947 100644 --- a/src/gpu/texture_manager.h +++ b/src/gpu/texture_manager.h @@ -61,16 +61,21 @@ class TextureManager { WGPUTextureView get_texture_view(const std::string& name); private: - void dispatch_noise_compute(WGPUTexture target, - const GpuProceduralParams& params); - void dispatch_perlin_compute(WGPUTexture target, - const GpuProceduralParams& params); - void dispatch_grid_compute(WGPUTexture target, - const GpuProceduralParams& params); + struct ComputePipelineInfo { + WGPUComputePipeline pipeline; + const char* shader_code; + size_t uniform_size; + }; + + WGPUComputePipeline get_or_create_compute_pipeline(const std::string& func_name, + const char* shader_code, + size_t uniform_size); + void dispatch_compute(const std::string& func_name, WGPUTexture target, + const GpuProceduralParams& params, const void* uniform_data, + size_t uniform_size); + WGPUDevice device_; WGPUQueue queue_; std::map<std::string, GpuTexture> textures_; - WGPUComputePipeline noise_compute_pipeline_ = nullptr; - WGPUComputePipeline perlin_compute_pipeline_ = nullptr; - WGPUComputePipeline grid_compute_pipeline_ = nullptr; + std::map<std::string, ComputePipelineInfo> compute_pipelines_; }; |
