summaryrefslogtreecommitdiff
path: root/src/gpu/effects
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/effects')
-rw-r--r--src/gpu/effects/cnn_effect.cc106
-rw-r--r--src/gpu/effects/post_process_helper.cc102
-rw-r--r--src/gpu/effects/rotating_cube_effect.cc23
-rw-r--r--src/gpu/effects/scene1_effect.cc28
-rw-r--r--src/gpu/effects/scene1_effect.h19
-rw-r--r--src/gpu/effects/shaders.cc4
-rw-r--r--src/gpu/effects/shaders.h1
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;