diff options
| -rw-r--r-- | cmake/DemoSourceLists.cmake | 3 | ||||
| -rw-r--r-- | src/effects/gaussian_blur_effect_v2.cc | 80 | ||||
| -rw-r--r-- | src/effects/gaussian_blur_effect_v2.h | 33 | ||||
| -rw-r--r-- | src/effects/heptagon_effect_v2.cc | 48 | ||||
| -rw-r--r-- | src/effects/heptagon_effect_v2.h | 20 | ||||
| -rw-r--r-- | src/effects/passthrough_effect_v2.cc | 75 | ||||
| -rw-r--r-- | src/effects/passthrough_effect_v2.h | 19 |
7 files changed, 278 insertions, 0 deletions
diff --git a/cmake/DemoSourceLists.cmake b/cmake/DemoSourceLists.cmake index fd4bdcb..8cd5f43 100644 --- a/cmake/DemoSourceLists.cmake +++ b/cmake/DemoSourceLists.cmake @@ -31,6 +31,9 @@ set(COMMON_GPU_EFFECTS src/gpu/effect.cc src/gpu/sequence_v2.cc src/gpu/effect_v2.cc + src/effects/passthrough_effect_v2.cc + src/effects/gaussian_blur_effect_v2.cc + src/effects/heptagon_effect_v2.cc src/effects/heptagon_effect.cc src/effects/particles_effect.cc src/effects/passthrough_effect.cc diff --git a/src/effects/gaussian_blur_effect_v2.cc b/src/effects/gaussian_blur_effect_v2.cc new file mode 100644 index 0000000..6b37f0b --- /dev/null +++ b/src/effects/gaussian_blur_effect_v2.cc @@ -0,0 +1,80 @@ +// Gaussian blur effect v2 implementation + +#include "effects/gaussian_blur_effect_v2.h" +#include "gpu/post_process_helper.h" +#include "gpu/shaders.h" + +GaussianBlurEffectV2::GaussianBlurEffectV2(const GpuContext& ctx, + const std::vector<std::string>& inputs, + const std::vector<std::string>& outputs) + : EffectV2(ctx, inputs, outputs), pipeline_(nullptr), bind_group_(nullptr), + sampler_(nullptr) { + // Create pipeline + pipeline_ = create_post_process_pipeline(ctx_.device, WGPUTextureFormat_RGBA8Unorm, + gaussian_blur_shader_wgsl); + + // Create sampler + WGPUSamplerDescriptor sampler_desc = {}; + sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; + sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; + sampler_desc.magFilter = WGPUFilterMode_Linear; + sampler_desc.minFilter = WGPUFilterMode_Linear; + sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); + + // Init uniform buffers + params_buffer_.init(ctx_.device); + uniforms_buffer_.init(ctx_.device); +} + +void GaussianBlurEffectV2::render(WGPUCommandEncoder encoder, + const UniformsSequenceParams& params, + NodeRegistry& nodes) { + // Get input/output views + WGPUTextureView input_view = nodes.get_view(input_nodes_[0]); + WGPUTextureView output_view = nodes.get_view(output_nodes_[0]); + + // Update uniforms + uniforms_buffer_.update(ctx_.queue, params); + params_buffer_.update(ctx_.queue, blur_params_); + + // Update bind group + WGPUBindGroupEntry entries[4] = {}; + entries[0].binding = PP_BINDING_SAMPLER; + entries[0].sampler = sampler_; + entries[1].binding = PP_BINDING_TEXTURE; + entries[1].textureView = input_view; + entries[2].binding = PP_BINDING_UNIFORMS; + entries[2].buffer = uniforms_buffer_.get().buffer; + entries[2].size = sizeof(UniformsSequenceParams); + entries[3].binding = PP_BINDING_EFFECT_PARAMS; + entries[3].buffer = params_buffer_.get().buffer; + entries[3].size = sizeof(GaussianBlurParams); + + WGPUBindGroupDescriptor bg_desc = {}; + bg_desc.layout = wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0); + bg_desc.entryCount = 4; + bg_desc.entries = entries; + + if (bind_group_) { + wgpuBindGroupRelease(bind_group_); + } + bind_group_ = wgpuDeviceCreateBindGroup(ctx_.device, &bg_desc); + + // Render pass + WGPURenderPassColorAttachment color_attachment = {}; + color_attachment.view = output_view; + color_attachment.loadOp = WGPULoadOp_Clear; + color_attachment.storeOp = WGPUStoreOp_Store; + color_attachment.clearValue = {0.0, 0.0, 0.0, 1.0}; + + WGPURenderPassDescriptor pass_desc = {}; + pass_desc.colorAttachmentCount = 1; + pass_desc.colorAttachments = &color_attachment; + + WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc); + wgpuRenderPassEncoderSetPipeline(pass, pipeline_); + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0); + wgpuRenderPassEncoderEnd(pass); + wgpuRenderPassEncoderRelease(pass); +} diff --git a/src/effects/gaussian_blur_effect_v2.h b/src/effects/gaussian_blur_effect_v2.h new file mode 100644 index 0000000..c5d88ff --- /dev/null +++ b/src/effects/gaussian_blur_effect_v2.h @@ -0,0 +1,33 @@ +// Gaussian blur effect v2 - single-pass blur + +#pragma once + +#include "gpu/effect_v2.h" +#include "gpu/uniform_helper.h" + +struct GaussianBlurParams { + float strength = 1.0f; + float strength_audio = 0.5f; + float stretch = 1.0f; + float _pad = 0.0f; +}; +static_assert(sizeof(GaussianBlurParams) == 16, + "GaussianBlurParams must be 16 bytes"); + +class GaussianBlurEffectV2 : public EffectV2 { + public: + GaussianBlurEffectV2(const GpuContext& ctx, + const std::vector<std::string>& inputs, + const std::vector<std::string>& outputs); + + void render(WGPUCommandEncoder encoder, const UniformsSequenceParams& params, + NodeRegistry& nodes) override; + + private: + WGPURenderPipeline pipeline_; + WGPUBindGroup bind_group_; + WGPUSampler sampler_; + GaussianBlurParams blur_params_; + UniformBuffer<GaussianBlurParams> params_buffer_; + UniformBuffer<UniformsSequenceParams> uniforms_buffer_; +}; diff --git a/src/effects/heptagon_effect_v2.cc b/src/effects/heptagon_effect_v2.cc new file mode 100644 index 0000000..4478327 --- /dev/null +++ b/src/effects/heptagon_effect_v2.cc @@ -0,0 +1,48 @@ +// Heptagon effect v2 implementation + +#include "effects/heptagon_effect_v2.h" +#include "gpu/gpu.h" +#include "gpu/shaders.h" + +HeptagonEffectV2::HeptagonEffectV2(const GpuContext& ctx, + const std::vector<std::string>& inputs, + const std::vector<std::string>& outputs) + : EffectV2(ctx, inputs, outputs), pipeline_(nullptr), bind_group_(nullptr) { + // Init uniforms + uniforms_buffer_.init(ctx_.device); + + // Create render pass using helper + ResourceBinding bindings[] = {{uniforms_buffer_.get(), WGPUBufferBindingType_Uniform}}; + RenderPass pass = gpu_create_render_pass(ctx_.device, WGPUTextureFormat_RGBA8Unorm, + main_shader_wgsl, bindings, 1); + pipeline_ = pass.pipeline; + bind_group_ = pass.bind_group; +} + +void HeptagonEffectV2::render(WGPUCommandEncoder encoder, + const UniformsSequenceParams& params, + NodeRegistry& nodes) { + // Get output view (scene effects typically write to output, ignore input) + WGPUTextureView output_view = nodes.get_view(output_nodes_[0]); + + // Update uniforms + uniforms_buffer_.update(ctx_.queue, params); + + // Render pass + WGPURenderPassColorAttachment color_attachment = {}; + color_attachment.view = output_view; + color_attachment.loadOp = WGPULoadOp_Clear; + color_attachment.storeOp = WGPUStoreOp_Store; + color_attachment.clearValue = {0.0, 0.0, 0.0, 1.0}; + + WGPURenderPassDescriptor pass_desc = {}; + pass_desc.colorAttachmentCount = 1; + pass_desc.colorAttachments = &color_attachment; + + WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc); + wgpuRenderPassEncoderSetPipeline(pass, pipeline_); + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, 21, 1, 0, 0); // 7 triangles * 3 vertices + wgpuRenderPassEncoderEnd(pass); + wgpuRenderPassEncoderRelease(pass); +} diff --git a/src/effects/heptagon_effect_v2.h b/src/effects/heptagon_effect_v2.h new file mode 100644 index 0000000..f740769 --- /dev/null +++ b/src/effects/heptagon_effect_v2.h @@ -0,0 +1,20 @@ +// Heptagon effect v2 - scene rendering effect + +#pragma once + +#include "gpu/effect_v2.h" +#include "gpu/uniform_helper.h" + +class HeptagonEffectV2 : public EffectV2 { + public: + HeptagonEffectV2(const GpuContext& ctx, const std::vector<std::string>& inputs, + const std::vector<std::string>& outputs); + + void render(WGPUCommandEncoder encoder, const UniformsSequenceParams& params, + NodeRegistry& nodes) override; + + private: + WGPURenderPipeline pipeline_; + WGPUBindGroup bind_group_; + UniformBuffer<UniformsSequenceParams> uniforms_buffer_; +}; diff --git a/src/effects/passthrough_effect_v2.cc b/src/effects/passthrough_effect_v2.cc new file mode 100644 index 0000000..d98315f --- /dev/null +++ b/src/effects/passthrough_effect_v2.cc @@ -0,0 +1,75 @@ +// Passthrough effect v2 implementation + +#include "effects/passthrough_effect_v2.h" +#include "gpu/post_process_helper.h" +#include "gpu/shaders.h" + +PassthroughEffectV2::PassthroughEffectV2(const GpuContext& ctx, + const std::vector<std::string>& inputs, + const std::vector<std::string>& outputs) + : EffectV2(ctx, inputs, outputs), pipeline_(nullptr), bind_group_(nullptr), + sampler_(nullptr) { + // Create pipeline + pipeline_ = create_post_process_pipeline(ctx_.device, WGPUTextureFormat_RGBA8Unorm, + passthrough_shader_wgsl); + + // Create sampler + WGPUSamplerDescriptor sampler_desc = {}; + sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; + sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; + sampler_desc.addressModeW = WGPUAddressMode_ClampToEdge; + sampler_desc.magFilter = WGPUFilterMode_Linear; + sampler_desc.minFilter = WGPUFilterMode_Linear; + sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Nearest; + sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); +} + +void PassthroughEffectV2::render(WGPUCommandEncoder encoder, + const UniformsSequenceParams& params, + NodeRegistry& nodes) { + // Get input/output views + WGPUTextureView input_view = nodes.get_view(input_nodes_[0]); + WGPUTextureView output_view = nodes.get_view(output_nodes_[0]); + + // Update bind group (recreate each frame for simplicity) + WGPUBindGroupEntry entries[3] = {}; + + entries[0].binding = PP_BINDING_SAMPLER; + entries[0].sampler = sampler_; + + entries[1].binding = PP_BINDING_TEXTURE; + entries[1].textureView = input_view; + + // Uniforms (binding 2) - use empty buffer for now + entries[2].binding = PP_BINDING_UNIFORMS; + entries[2].buffer = nullptr; + entries[2].size = 0; + + WGPUBindGroupDescriptor bg_desc = {}; + bg_desc.layout = wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0); + bg_desc.entryCount = 2; // Only sampler and texture, no uniforms + bg_desc.entries = entries; + + if (bind_group_) { + wgpuBindGroupRelease(bind_group_); + } + bind_group_ = wgpuDeviceCreateBindGroup(ctx_.device, &bg_desc); + + // Render pass + WGPURenderPassColorAttachment color_attachment = {}; + color_attachment.view = output_view; + color_attachment.loadOp = WGPULoadOp_Clear; + color_attachment.storeOp = WGPUStoreOp_Store; + color_attachment.clearValue = {0.0, 0.0, 0.0, 1.0}; + + WGPURenderPassDescriptor pass_desc = {}; + pass_desc.colorAttachmentCount = 1; + pass_desc.colorAttachments = &color_attachment; + + WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc); + wgpuRenderPassEncoderSetPipeline(pass, pipeline_); + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0); // Fullscreen triangle + wgpuRenderPassEncoderEnd(pass); + wgpuRenderPassEncoderRelease(pass); +} diff --git a/src/effects/passthrough_effect_v2.h b/src/effects/passthrough_effect_v2.h new file mode 100644 index 0000000..813361e --- /dev/null +++ b/src/effects/passthrough_effect_v2.h @@ -0,0 +1,19 @@ +// Passthrough effect v2 - simple copy input to output + +#pragma once + +#include "gpu/effect_v2.h" + +class PassthroughEffectV2 : public EffectV2 { + public: + PassthroughEffectV2(const GpuContext& ctx, const std::vector<std::string>& inputs, + const std::vector<std::string>& outputs); + + void render(WGPUCommandEncoder encoder, const UniformsSequenceParams& params, + NodeRegistry& nodes) override; + + private: + WGPURenderPipeline pipeline_; + WGPUBindGroup bind_group_; + WGPUSampler sampler_; +}; |
