diff options
Diffstat (limited to 'src/gpu/effects')
| -rw-r--r-- | src/gpu/effects/cnn_effect.cc | 106 | ||||
| -rw-r--r-- | src/gpu/effects/post_process_helper.cc | 102 | ||||
| -rw-r--r-- | src/gpu/effects/rotating_cube_effect.cc | 23 | ||||
| -rw-r--r-- | src/gpu/effects/scene1_effect.cc | 28 | ||||
| -rw-r--r-- | src/gpu/effects/scene1_effect.h | 19 | ||||
| -rw-r--r-- | src/gpu/effects/shaders.cc | 4 | ||||
| -rw-r--r-- | src/gpu/effects/shaders.h | 1 |
7 files changed, 108 insertions, 175 deletions
diff --git a/src/gpu/effects/cnn_effect.cc b/src/gpu/effects/cnn_effect.cc index 7107bea..d74187c 100644 --- a/src/gpu/effects/cnn_effect.cc +++ b/src/gpu/effects/cnn_effect.cc @@ -6,70 +6,30 @@ #include "gpu/effects/shaders.h" #include "gpu/effects/shader_composer.h" #include "gpu/effect.h" +#include "gpu/bind_group_builder.h" +#include "gpu/sampler_cache.h" +#include "gpu/pipeline_builder.h" // Create custom pipeline with 5 bindings (includes original texture) static WGPURenderPipeline create_cnn_pipeline(WGPUDevice device, WGPUTextureFormat format, const char* shader_code) { - std::string composed_shader = ShaderComposer::Get().Compose({}, shader_code); + WGPUBindGroupLayout bgl = BindGroupLayoutBuilder() + .sampler(0, WGPUShaderStage_Fragment) + .texture(1, WGPUShaderStage_Fragment) + .uniform(2, WGPUShaderStage_Vertex | WGPUShaderStage_Fragment) + .uniform(3, WGPUShaderStage_Fragment) + .texture(4, WGPUShaderStage_Fragment) + .build(device); - WGPUShaderModuleDescriptor shader_desc = {}; - WGPUShaderSourceWGSL wgsl_src = {}; - wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; - wgsl_src.code = str_view(composed_shader.c_str()); - shader_desc.nextInChain = &wgsl_src.chain; - WGPUShaderModule shader_module = - wgpuDeviceCreateShaderModule(device, &shader_desc); + WGPURenderPipeline pipeline = RenderPipelineBuilder(device) + .shader(shader_code) + .bind_group_layout(bgl) + .format(format) + .build(); - WGPUBindGroupLayoutEntry bgl_entries[5] = {}; - bgl_entries[0].binding = 0; // sampler - bgl_entries[0].visibility = WGPUShaderStage_Fragment; - bgl_entries[0].sampler.type = WGPUSamplerBindingType_Filtering; - bgl_entries[1].binding = 1; // input texture - 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; // uniforms - bgl_entries[2].visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bgl_entries[2].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[3].binding = 3; // effect params - bgl_entries[3].visibility = WGPUShaderStage_Fragment; - bgl_entries[3].buffer.type = WGPUBufferBindingType_Uniform; - bgl_entries[4].binding = 4; // original texture - bgl_entries[4].visibility = WGPUShaderStage_Fragment; - bgl_entries[4].texture.sampleType = WGPUTextureSampleType_Float; - bgl_entries[4].texture.viewDimension = WGPUTextureViewDimension_2D; - - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 5; - 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); + wgpuBindGroupLayoutRelease(bgl); + return pipeline; } CNNEffect::CNNEffect(const GpuContext& ctx) @@ -137,29 +97,13 @@ void CNNEffect::update_bind_group(WGPUTextureView input_view) { wgpuBindGroupRelease(bind_group_); WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0); - WGPUSamplerDescriptor sd = {}; - sd.magFilter = WGPUFilterMode_Linear; - sd.minFilter = WGPUFilterMode_Linear; - sd.maxAnisotropy = 1; - WGPUSampler sampler = wgpuDeviceCreateSampler(ctx_.device, &sd); - - WGPUBindGroupEntry bge[5] = {}; - 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_.get().buffer; - bge[2].size = uniforms_.get().size; - bge[3].binding = 3; - bge[3].buffer = params_buffer_.get().buffer; - bge[3].size = params_buffer_.get().size; - bge[4].binding = 4; - bge[4].textureView = original_view_ ? original_view_ : input_view_; + WGPUSampler sampler = SamplerCache::Get().get_or_create(ctx_.device, SamplerCache::linear()); - WGPUBindGroupDescriptor bgd = {}; - bgd.layout = bgl; - bgd.entryCount = 5; - bgd.entries = bge; - bind_group_ = wgpuDeviceCreateBindGroup(ctx_.device, &bgd); + bind_group_ = BindGroupBuilder() + .sampler(0, sampler) + .texture(1, input_view_) + .buffer(2, uniforms_.get().buffer, uniforms_.get().size) + .buffer(3, params_buffer_.get().buffer, params_buffer_.get().size) + .texture(4, original_view_ ? original_view_ : input_view_) + .build(ctx_.device, bgl); } diff --git a/src/gpu/effects/post_process_helper.cc b/src/gpu/effects/post_process_helper.cc index e99467f..0c339c7 100644 --- a/src/gpu/effects/post_process_helper.cc +++ b/src/gpu/effects/post_process_helper.cc @@ -5,69 +5,30 @@ #include "../demo_effects.h" #include "gpu/gpu.h" #include "gpu/effects/shader_composer.h" +#include "gpu/bind_group_builder.h" +#include "gpu/sampler_cache.h" +#include "gpu/pipeline_builder.h" #include <cstring> // Helper to create a standard post-processing pipeline WGPURenderPipeline create_post_process_pipeline(WGPUDevice device, WGPUTextureFormat format, const char* shader_code) { - std::string composed_shader = ShaderComposer::Get().Compose({}, shader_code); + WGPUBindGroupLayout bgl = BindGroupLayoutBuilder() + .sampler(PP_BINDING_SAMPLER, WGPUShaderStage_Fragment) + .texture(PP_BINDING_TEXTURE, WGPUShaderStage_Fragment) + .uniform(PP_BINDING_UNIFORMS, WGPUShaderStage_Vertex | WGPUShaderStage_Fragment) + .uniform(PP_BINDING_EFFECT_PARAMS, WGPUShaderStage_Fragment) + .build(device); - WGPUShaderModuleDescriptor shader_desc = {}; - WGPUShaderSourceWGSL wgsl_src = {}; - wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL; - wgsl_src.code = str_view(composed_shader.c_str()); - shader_desc.nextInChain = &wgsl_src.chain; - WGPUShaderModule shader_module = - wgpuDeviceCreateShaderModule(device, &shader_desc); + WGPURenderPipeline pipeline = RenderPipelineBuilder(device) + .shader(shader_code) + .bind_group_layout(bgl) + .format(format) + .build(); - WGPUBindGroupLayoutEntry bgl_entries[4] = {}; - bgl_entries[0].binding = PP_BINDING_SAMPLER; - bgl_entries[0].visibility = WGPUShaderStage_Fragment; - bgl_entries[0].sampler.type = WGPUSamplerBindingType_Filtering; - bgl_entries[1].binding = PP_BINDING_TEXTURE; - bgl_entries[1].visibility = WGPUShaderStage_Fragment; - bgl_entries[1].texture.sampleType = WGPUTextureSampleType_Float; - bgl_entries[1].texture.viewDimension = WGPUTextureViewDimension_2D; - bgl_entries[2].binding = PP_BINDING_UNIFORMS; - bgl_entries[2].visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bgl_entries[2].buffer.type = WGPUBufferBindingType_Uniform; - - // Add an entry for effect-specific parameters - bgl_entries[3].binding = PP_BINDING_EFFECT_PARAMS; - bgl_entries[3].visibility = WGPUShaderStage_Fragment; - bgl_entries[3].buffer.type = WGPUBufferBindingType_Uniform; - - WGPUBindGroupLayoutDescriptor bgl_desc = {}; - bgl_desc.entryCount = 4; - 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); + wgpuBindGroupLayoutRelease(bgl); + return pipeline; } // --- PostProcess Implementation Helper --- @@ -82,25 +43,16 @@ void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline, 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[4] = {}; - bge[0].binding = PP_BINDING_SAMPLER; - bge[0].sampler = sampler; - bge[1].binding = PP_BINDING_TEXTURE; - bge[1].textureView = input_view; - bge[2].binding = PP_BINDING_UNIFORMS; - bge[2].buffer = uniforms.buffer; - bge[2].size = uniforms.size; - bge[3].binding = PP_BINDING_EFFECT_PARAMS; - bge[3].buffer = - effect_params.buffer ? effect_params.buffer : g_dummy_buffer.buffer; - bge[3].size = effect_params.buffer ? effect_params.size : g_dummy_buffer.size; - WGPUBindGroupDescriptor bgd = { - .layout = bgl, .entryCount = 4, .entries = bge}; - *bind_group = wgpuDeviceCreateBindGroup(device, &bgd); + WGPUSampler sampler = SamplerCache::Get().get_or_create(device, SamplerCache::linear()); + + *bind_group = BindGroupBuilder() + .sampler(PP_BINDING_SAMPLER, sampler) + .texture(PP_BINDING_TEXTURE, input_view) + .buffer(PP_BINDING_UNIFORMS, uniforms.buffer, uniforms.size) + .buffer(PP_BINDING_EFFECT_PARAMS, + effect_params.buffer ? effect_params.buffer : g_dummy_buffer.buffer, + effect_params.buffer ? effect_params.size : g_dummy_buffer.size) + .build(device, bgl); } diff --git a/src/gpu/effects/rotating_cube_effect.cc b/src/gpu/effects/rotating_cube_effect.cc index 8d1f05a..da973e5 100644 --- a/src/gpu/effects/rotating_cube_effect.cc +++ b/src/gpu/effects/rotating_cube_effect.cc @@ -5,16 +5,14 @@ #include "gpu/effects/rotating_cube_effect.h" #include "generated/assets.h" #include "gpu/effects/shader_composer.h" +#include "gpu/sampler_cache.h" #include "util/asset_manager_utils.h" RotatingCubeEffect::RotatingCubeEffect(const GpuContext& ctx) : Effect(ctx) { } RotatingCubeEffect::~RotatingCubeEffect() { - if (mask_sampler_) - wgpuSamplerRelease(mask_sampler_); - if (noise_sampler_) - wgpuSamplerRelease(noise_sampler_); + // Samplers owned by SamplerCache - don't release if (noise_view_) wgpuTextureViewRelease(noise_view_); if (noise_texture_) @@ -49,21 +47,8 @@ void RotatingCubeEffect::init(MainSequence* demo) { noise_texture_ = wgpuDeviceCreateTexture(ctx_.device, &tex_desc); noise_view_ = wgpuTextureCreateView(noise_texture_, nullptr); - WGPUSamplerDescriptor sampler_desc = {}; - sampler_desc.addressModeU = WGPUAddressMode_Repeat; - sampler_desc.addressModeV = WGPUAddressMode_Repeat; - sampler_desc.magFilter = WGPUFilterMode_Linear; - sampler_desc.minFilter = WGPUFilterMode_Linear; - sampler_desc.maxAnisotropy = 1; - noise_sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); - - WGPUSamplerDescriptor mask_sampler_desc = {}; - mask_sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; - mask_sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; - mask_sampler_desc.magFilter = WGPUFilterMode_Linear; - mask_sampler_desc.minFilter = WGPUFilterMode_Linear; - mask_sampler_desc.maxAnisotropy = 1; - mask_sampler_ = wgpuDeviceCreateSampler(ctx_.device, &mask_sampler_desc); + noise_sampler_ = SamplerCache::Get().get_or_create(ctx_.device, SamplerCache::linear()); + mask_sampler_ = SamplerCache::Get().get_or_create(ctx_.device, SamplerCache::clamp()); size_t shader_size; const char* shader_code = diff --git a/src/gpu/effects/scene1_effect.cc b/src/gpu/effects/scene1_effect.cc new file mode 100644 index 0000000..a6733b7 --- /dev/null +++ b/src/gpu/effects/scene1_effect.cc @@ -0,0 +1,28 @@ +// This file is part of the 64k demo project. +// Scene1 effect - ShaderToy conversion (raymarching scene) + +#include "gpu/demo_effects.h" +#include "gpu/gpu.h" + +Scene1Effect::Scene1Effect(const GpuContext& ctx) : Effect(ctx) { + ResourceBinding bindings[] = {{uniforms_.get(), WGPUBufferBindingType_Uniform}}; + pass_ = gpu_create_render_pass(ctx_.device, ctx_.format, scene1_shader_wgsl, + bindings, 1); + pass_.vertex_count = 3; +} + +void Scene1Effect::render(WGPURenderPassEncoder pass, float t, float b, + float i, float a) { + CommonPostProcessUniforms u = { + .resolution = {(float)width_, (float)height_}, + ._pad = {0.0f, 0.0f}, + .aspect_ratio = a, + .time = t, + .beat = b, + .audio_intensity = i, + }; + uniforms_.update(ctx_.queue, u); + wgpuRenderPassEncoderSetPipeline(pass, pass_.pipeline); + wgpuRenderPassEncoderSetBindGroup(pass, 0, pass_.bind_group, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, pass_.vertex_count, 1, 0, 0); +} diff --git a/src/gpu/effects/scene1_effect.h b/src/gpu/effects/scene1_effect.h new file mode 100644 index 0000000..dc5c747 --- /dev/null +++ b/src/gpu/effects/scene1_effect.h @@ -0,0 +1,19 @@ +// This file is part of the 64k demo project. +// Scene1 effect - ShaderToy conversion (raymarching scene) + +#ifndef SCENE1_EFFECT_H_ +#define SCENE1_EFFECT_H_ + +#include "gpu/effect.h" + +class Scene1Effect : public Effect { + public: + Scene1Effect(const GpuContext& ctx); + void render(WGPURenderPassEncoder pass, float time, float beat, + float intensity, float aspect_ratio) override; + + private: + RenderPass pass_; +}; + +#endif /* SCENE1_EFFECT_H_ */ diff --git a/src/gpu/effects/shaders.cc b/src/gpu/effects/shaders.cc index 6559bf5..5f78298 100644 --- a/src/gpu/effects/shaders.cc +++ b/src/gpu/effects/shaders.cc @@ -98,6 +98,10 @@ const char* solarize_shader_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_SOLARIZE); +const char* scene1_shader_wgsl = + + SafeGetAsset(AssetId::ASSET_SHADER_SCENE1); + const char* distort_shader_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_DISTORT); diff --git a/src/gpu/effects/shaders.h b/src/gpu/effects/shaders.h index 7acc2a6..03fa48c 100644 --- a/src/gpu/effects/shaders.h +++ b/src/gpu/effects/shaders.h @@ -15,6 +15,7 @@ extern const char* ellipse_shader_wgsl; extern const char* particle_spray_compute_wgsl; extern const char* gaussian_blur_shader_wgsl; extern const char* solarize_shader_wgsl; +extern const char* scene1_shader_wgsl; extern const char* distort_shader_wgsl; extern const char* chroma_aberration_shader_wgsl; extern const char* vignette_shader_wgsl; |
