summaryrefslogtreecommitdiff
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/effects/cnn_effect.cc9
-rw-r--r--src/gpu/effects/cnn_effect.h7
-rw-r--r--src/gpu/effects/cnn_v2_effect.cc71
-rw-r--r--src/gpu/effects/cnn_v2_effect.h16
4 files changed, 82 insertions, 21 deletions
diff --git a/src/gpu/effects/cnn_effect.cc b/src/gpu/effects/cnn_effect.cc
index b2305b2..83a3365 100644
--- a/src/gpu/effects/cnn_effect.cc
+++ b/src/gpu/effects/cnn_effect.cc
@@ -79,12 +79,19 @@ void CNNEffect::resize(int width, int height) {
void CNNEffect::render(WGPURenderPassEncoder pass,
const CommonPostProcessUniforms& uniforms) {
- (void)uniforms;
if (!bind_group_) {
fprintf(stderr, "CNN render: no bind_group\n");
return;
}
+ float effective_blend = blend_amount_;
+ if (beat_modulated_) {
+ effective_blend = blend_amount_ * uniforms.beat_phase * beat_scale_;
+ }
+
+ CNNLayerParams params = {layer_index_, effective_blend, {0.0f, 0.0f}};
+ params_buffer_.update(ctx_.queue, params);
+
wgpuRenderPassEncoderSetPipeline(pass, pipeline_);
wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0);
diff --git a/src/gpu/effects/cnn_effect.h b/src/gpu/effects/cnn_effect.h
index 1c9f0f3..3e2b7ca 100644
--- a/src/gpu/effects/cnn_effect.h
+++ b/src/gpu/effects/cnn_effect.h
@@ -34,10 +34,17 @@ class CNNEffect : public PostProcessEffect {
return layer_index_ == 0;
}
+ void set_beat_modulation(bool enabled, float scale = 1.0f) {
+ beat_modulated_ = enabled;
+ beat_scale_ = scale;
+ }
+
private:
int layer_index_;
int total_layers_;
float blend_amount_;
+ bool beat_modulated_ = false;
+ float beat_scale_ = 1.0f;
WGPUTextureView input_view_;
WGPUTextureView original_view_;
UniformBuffer<CNNLayerParams> params_buffer_;
diff --git a/src/gpu/effects/cnn_v2_effect.cc b/src/gpu/effects/cnn_v2_effect.cc
index 9cb6d57..9c727ba 100644
--- a/src/gpu/effects/cnn_v2_effect.cc
+++ b/src/gpu/effects/cnn_v2_effect.cc
@@ -20,9 +20,24 @@ CNNv2Effect::CNNv2Effect(const GpuContext& ctx)
static_features_view_(nullptr),
layer_pipeline_(nullptr),
weights_buffer_(nullptr),
- layer_params_buffer_(nullptr),
input_mip_tex_(nullptr),
current_input_view_(nullptr),
+ blend_amount_(1.0f),
+ initialized_(false) {
+ std::memset(input_mip_view_, 0, sizeof(input_mip_view_));
+}
+
+CNNv2Effect::CNNv2Effect(const GpuContext& ctx, const CNNv2EffectParams& params)
+ : PostProcessEffect(ctx),
+ static_pipeline_(nullptr),
+ static_bind_group_(nullptr),
+ static_features_tex_(nullptr),
+ static_features_view_(nullptr),
+ layer_pipeline_(nullptr),
+ weights_buffer_(nullptr),
+ input_mip_tex_(nullptr),
+ current_input_view_(nullptr),
+ blend_amount_(params.blend_amount),
initialized_(false) {
std::memset(input_mip_view_, 0, sizeof(input_mip_view_));
}
@@ -93,13 +108,16 @@ void CNNv2Effect::load_weights() {
// Upload weights data
wgpuQueueWriteBuffer(ctx_.queue, weights_buffer_, 0, weights_data, weights_size);
- // Create uniform buffer for layer params
- WGPUBufferDescriptor params_desc = {};
- params_desc.size = sizeof(LayerParams);
- params_desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst;
- params_desc.mappedAtCreation = false;
+ // Create uniform buffers for layer params (one per layer)
+ for (uint32_t i = 0; i < num_layers; ++i) {
+ WGPUBufferDescriptor params_desc = {};
+ params_desc.size = sizeof(LayerParams);
+ params_desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst;
+ params_desc.mappedAtCreation = false;
- layer_params_buffer_ = wgpuDeviceCreateBuffer(ctx_.device, &params_desc);
+ WGPUBuffer buf = wgpuDeviceCreateBuffer(ctx_.device, &params_desc);
+ layer_params_buffers_.push_back(buf);
+ }
}
void CNNv2Effect::create_textures() {
@@ -284,8 +302,8 @@ void CNNv2Effect::create_pipelines() {
if (!layer_module) return;
// Create bind group layout for layer compute
- // 0=static_features, 1=layer_input, 2=output, 3=weights, 4=params
- WGPUBindGroupLayoutEntry layer_bgl_entries[5] = {};
+ // 0=static_features, 1=layer_input, 2=output, 3=weights, 4=params, 5=original_input
+ WGPUBindGroupLayoutEntry layer_bgl_entries[6] = {};
// Binding 0: Static features (texture)
layer_bgl_entries[0].binding = 0;
@@ -317,8 +335,14 @@ void CNNv2Effect::create_pipelines() {
layer_bgl_entries[4].buffer.type = WGPUBufferBindingType_Uniform;
layer_bgl_entries[4].buffer.minBindingSize = sizeof(LayerParams);
+ // Binding 5: Original input (for blending)
+ layer_bgl_entries[5].binding = 5;
+ layer_bgl_entries[5].visibility = WGPUShaderStage_Compute;
+ layer_bgl_entries[5].texture.sampleType = WGPUTextureSampleType_Float;
+ layer_bgl_entries[5].texture.viewDimension = WGPUTextureViewDimension_2D;
+
WGPUBindGroupLayoutDescriptor layer_bgl_desc = {};
- layer_bgl_desc.entryCount = 5;
+ layer_bgl_desc.entryCount = 6;
layer_bgl_desc.entries = layer_bgl_entries;
WGPUBindGroupLayout layer_bgl = wgpuDeviceCreateBindGroupLayout(ctx_.device, &layer_bgl_desc);
@@ -399,7 +423,7 @@ void CNNv2Effect::update_bind_group(WGPUTextureView input_view) {
// Create bind group for each layer
for (size_t i = 0; i < layer_info_.size(); ++i) {
- WGPUBindGroupEntry layer_entries[5] = {};
+ WGPUBindGroupEntry layer_entries[6] = {};
// Binding 0: Static features (constant)
layer_entries[0].binding = 0;
@@ -419,14 +443,18 @@ void CNNv2Effect::update_bind_group(WGPUTextureView input_view) {
layer_entries[3].buffer = weights_buffer_;
layer_entries[3].size = wgpuBufferGetSize(weights_buffer_);
- // Binding 4: Layer params (will be updated per dispatch)
+ // Binding 4: Layer params (use dedicated buffer for this layer)
layer_entries[4].binding = 4;
- layer_entries[4].buffer = layer_params_buffer_;
+ layer_entries[4].buffer = layer_params_buffers_[i];
layer_entries[4].size = sizeof(LayerParams);
+ // Binding 5: Original input (for blending)
+ layer_entries[5].binding = 5;
+ layer_entries[5].textureView = input_view;
+
WGPUBindGroupDescriptor layer_bg_desc = {};
layer_bg_desc.layout = layer_bgl;
- layer_bg_desc.entryCount = 5;
+ layer_bg_desc.entryCount = 6;
layer_bg_desc.entries = layer_entries;
WGPUBindGroup layer_bg = wgpuDeviceCreateBindGroup(ctx_.device, &layer_bg_desc);
@@ -438,9 +466,13 @@ void CNNv2Effect::update_bind_group(WGPUTextureView input_view) {
void CNNv2Effect::compute(WGPUCommandEncoder encoder,
const CommonPostProcessUniforms& uniforms) {
- (void)uniforms;
if (!initialized_ || !static_pipeline_ || !static_bind_group_) return;
+ float effective_blend = blend_amount_;
+ if (beat_modulated_) {
+ effective_blend = blend_amount_ * uniforms.beat_phase * beat_scale_;
+ }
+
// Pass 1: Compute static features
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
@@ -458,20 +490,20 @@ void CNNv2Effect::compute(WGPUCommandEncoder encoder,
// Execute CNN layer passes
if (!layer_pipeline_ || layer_bind_groups_.empty()) return;
+ // Update layer params (each layer has own buffer)
for (size_t i = 0; i < layer_info_.size(); ++i) {
const LayerInfo& info = layer_info_[i];
- // Update layer params uniform buffer
LayerParams params;
params.kernel_size = info.kernel_size;
params.in_channels = info.in_channels;
params.out_channels = info.out_channels;
params.weight_offset = info.weight_offset;
params.is_output_layer = (i == layer_info_.size() - 1) ? 1 : 0;
+ params.blend_amount = effective_blend;
- wgpuQueueWriteBuffer(ctx_.queue, layer_params_buffer_, 0, &params, sizeof(params));
+ wgpuQueueWriteBuffer(ctx_.queue, layer_params_buffers_[i], 0, &params, sizeof(params));
- // Execute layer compute pass
WGPUComputePassEncoder layer_pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
wgpuComputePassEncoderSetPipeline(layer_pass, layer_pipeline_);
@@ -499,7 +531,8 @@ void CNNv2Effect::cleanup() {
if (layer_pipeline_) wgpuComputePipelineRelease(layer_pipeline_);
if (weights_buffer_) wgpuBufferRelease(weights_buffer_);
- if (layer_params_buffer_) wgpuBufferRelease(layer_params_buffer_);
+ for (auto buf : layer_params_buffers_) wgpuBufferRelease(buf);
+ layer_params_buffers_.clear();
for (int i = 0; i < 3; ++i) {
if (input_mip_view_[i]) wgpuTextureViewRelease(input_mip_view_[i]);
diff --git a/src/gpu/effects/cnn_v2_effect.h b/src/gpu/effects/cnn_v2_effect.h
index 6005cf5..4389e4f 100644
--- a/src/gpu/effects/cnn_v2_effect.h
+++ b/src/gpu/effects/cnn_v2_effect.h
@@ -5,9 +5,14 @@
#include "gpu/effect.h"
#include <vector>
+struct CNNv2EffectParams {
+ float blend_amount = 1.0f;
+};
+
class CNNv2Effect : public PostProcessEffect {
public:
explicit CNNv2Effect(const GpuContext& ctx);
+ explicit CNNv2Effect(const GpuContext& ctx, const CNNv2EffectParams& params);
~CNNv2Effect();
void init(MainSequence* demo) override;
@@ -18,6 +23,11 @@ public:
const CommonPostProcessUniforms& uniforms) override;
void update_bind_group(WGPUTextureView input_view) override;
+ void set_beat_modulation(bool enabled, float scale = 1.0f) {
+ beat_modulated_ = enabled;
+ beat_scale_ = scale;
+ }
+
private:
struct LayerInfo {
uint32_t kernel_size;
@@ -33,6 +43,7 @@ private:
uint32_t out_channels;
uint32_t weight_offset;
uint32_t is_output_layer;
+ float blend_amount;
};
void create_textures();
@@ -49,7 +60,7 @@ private:
// CNN layers (storage buffer architecture)
WGPUComputePipeline layer_pipeline_; // Single pipeline for all layers
WGPUBuffer weights_buffer_; // Storage buffer for weights
- WGPUBuffer layer_params_buffer_; // Uniform buffer for per-layer params
+ std::vector<WGPUBuffer> layer_params_buffers_; // Uniform buffers (one per layer)
std::vector<LayerInfo> layer_info_; // Layer metadata
std::vector<WGPUBindGroup> layer_bind_groups_; // Per-layer bind groups
std::vector<WGPUTexture> layer_textures_; // Ping-pong buffers
@@ -60,5 +71,8 @@ private:
WGPUTextureView input_mip_view_[3];
WGPUTextureView current_input_view_;
+ float blend_amount_ = 1.0f;
+ bool beat_modulated_ = false;
+ float beat_scale_ = 1.0f;
bool initialized_;
};