summaryrefslogtreecommitdiff
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/demo_effects.cc77
-rw-r--r--src/gpu/demo_effects.h1
-rw-r--r--src/gpu/effect.cc63
-rw-r--r--src/gpu/gpu.h56
4 files changed, 87 insertions, 110 deletions
diff --git a/src/gpu/demo_effects.cc b/src/gpu/demo_effects.cc
index 71f1284..27712d3 100644
--- a/src/gpu/demo_effects.cc
+++ b/src/gpu/demo_effects.cc
@@ -58,6 +58,8 @@ create_post_process_pipeline(WGPUDevice device, WGPUTextureFormat format,
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);
}
@@ -91,7 +93,8 @@ struct Uniforms { audio_peak: f32, aspect_ratio: f32, time: f32, beat: f32, };
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
let i = id.x; if (i >= arrayLength(&particles)) { return; }
var p = particles[i];
- p.pos.xyz = p.pos.xyz + p.vel.xyz * 0.016;
+ let new_pos = p.pos.xyz + p.vel.xyz * 0.016;
+ p.pos = vec4<f32>(new_pos, p.pos.w);
p.vel.y = p.vel.y - 0.01 * (1.0 + uniforms.audio_peak * 5.0);
p.rot.x = p.rot.x + p.rot.y * 0.016;
if (p.pos.y < -1.5) {
@@ -171,7 +174,9 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
p.vel = vec4<f32>(cos(angle), sin(angle), 0.0, 0.0) * (0.5 + hash(r)*0.5) * (1.0 + uniforms.intensity * 2.0);
p.color = vec4<f32>(hash(r+0.1), hash(r+0.2), 1.0, 1.0);
}
- p.pos.xyz = p.pos.xyz + p.vel.xyz * 0.016; p.vel.y = p.vel.y - 0.01; p.pos.w = p.pos.w - 0.01 * (1.0 + uniforms.beat);
+ let new_pos = p.pos.xyz + p.vel.xyz * 0.016;
+ p.pos = vec4<f32>(new_pos, p.pos.w - 0.01 * (1.0 + uniforms.beat));
+ p.vel.y = p.vel.y - 0.01;
particles[i] = p;
})";
@@ -310,27 +315,44 @@ void ParticlesEffect::render(WGPURenderPassEncoder pass, float t, float b,
render_pass_.instance_count, 0, 0);
}
+// --- PostProcess Implementation Helper ---
+static void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline,
+ WGPUBindGroup *bind_group,
+ WGPUTextureView input_view,
+ GpuBuffer uniforms) {
+ 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[3] = {};
+ 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.buffer;
+ bge[2].size = uniforms.size;
+ WGPUBindGroupDescriptor bgd = {
+ .layout = bgl, .entryCount = 3, .entries = bge};
+ *bind_group = wgpuDeviceCreateBindGroup(device, &bgd);
+}
+
// --- PassthroughEffect ---
PassthroughEffect::PassthroughEffect(WGPUDevice device,
WGPUTextureFormat format)
: device_(device) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
pipeline_ =
create_post_process_pipeline(device, format, passthrough_shader_wgsl);
}
void PassthroughEffect::update_bind_group(WGPUTextureView input_view) {
- if (bind_group_)
- wgpuBindGroupRelease(bind_group_);
- WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0);
- WGPUSamplerDescriptor sd = {};
- WGPUSampler sampler = wgpuDeviceCreateSampler(device_, &sd);
- WGPUBindGroupEntry bge[2] = {};
- bge[0].binding = 0;
- bge[0].sampler = sampler;
- bge[1].binding = 1;
- bge[1].textureView = input_view;
- WGPUBindGroupDescriptor bgd = {
- .layout = bgl, .entryCount = 2, .entries = bge};
- bind_group_ = wgpuDeviceCreateBindGroup(device_, &bgd);
+ pp_update_bind_group(device_, pipeline_, &bind_group_, input_view, uniforms_);
}
// --- MovingEllipseEffect ---
@@ -404,31 +426,6 @@ void ParticleSprayEffect::render(WGPURenderPassEncoder pass, float t, float b,
wgpuRenderPassEncoderDraw(pass, 6, NUM_PARTICLES, 0, 0);
}
-// --- PostProcess Implementation Helper ---
-static void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline,
- WGPUBindGroup *bind_group,
- WGPUTextureView input_view,
- GpuBuffer uniforms) {
- if (*bind_group)
- wgpuBindGroupRelease(*bind_group);
- WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline, 0);
- WGPUSamplerDescriptor sd = {};
- sd.magFilter = WGPUFilterMode_Linear;
- sd.minFilter = WGPUFilterMode_Linear;
- WGPUSampler sampler = wgpuDeviceCreateSampler(device, &sd);
- WGPUBindGroupEntry bge[3] = {};
- 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.buffer;
- bge[2].size = uniforms.size;
- WGPUBindGroupDescriptor bgd = {
- .layout = bgl, .entryCount = 3, .entries = bge};
- *bind_group = wgpuDeviceCreateBindGroup(device, &bgd);
-}
-
// --- GaussianBlurEffect ---
GaussianBlurEffect::GaussianBlurEffect(WGPUDevice device, WGPUQueue queue,
WGPUTextureFormat format)
diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h
index 603c32e..5db710e 100644
--- a/src/gpu/demo_effects.h
+++ b/src/gpu/demo_effects.h
@@ -50,6 +50,7 @@ public:
private:
WGPUDevice device_;
+ GpuBuffer uniforms_;
};
class MovingEllipseEffect : public Effect {
diff --git a/src/gpu/effect.cc b/src/gpu/effect.cc
index 0ac9063..f9ebf0c 100644
--- a/src/gpu/effect.cc
+++ b/src/gpu/effect.cc
@@ -175,12 +175,11 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
// 2. Scene Pass (to A)
WGPURenderPassColorAttachment scene_attachment = {};
scene_attachment.view = framebuffer_view_a_;
+ scene_attachment.resolveTarget = nullptr;
scene_attachment.loadOp = WGPULoadOp_Clear;
scene_attachment.storeOp = WGPUStoreOp_Store;
scene_attachment.clearValue = {0, 0, 0, 1};
-#if !defined(DEMO_CROSS_COMPILE_WIN32)
scene_attachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
-#endif
WGPURenderPassDescriptor scene_desc = {.colorAttachmentCount = 1,
.colorAttachments = &scene_attachment};
WGPURenderPassEncoder scene_pass =
@@ -192,48 +191,52 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
wgpuRenderPassEncoderEnd(scene_pass);
// 3. Post Chain
+ WGPUSurfaceTexture st = {};
+ WGPUTextureView final_view = nullptr;
+
if (post_effects.empty()) {
- WGPUSurfaceTexture st;
wgpuSurfaceGetCurrentTexture(surface, &st);
- WGPUTextureView final_view = wgpuTextureCreateView(st.texture, nullptr);
+ final_view = wgpuTextureCreateView(st.texture, nullptr);
passthrough_effect_->update_bind_group(framebuffer_view_a_);
- WGPURenderPassColorAttachment final_attachment = {.view = final_view,
- .loadOp = WGPULoadOp_Load,
- .storeOp =
- WGPUStoreOp_Store};
+ WGPURenderPassColorAttachment final_attachment = {};
+ final_attachment.view = final_view;
+ final_attachment.resolveTarget = nullptr;
+ final_attachment.loadOp = WGPULoadOp_Load;
+ final_attachment.storeOp = WGPUStoreOp_Store;
+ final_attachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
WGPURenderPassDescriptor final_desc = {
.colorAttachmentCount = 1, .colorAttachments = &final_attachment};
WGPURenderPassEncoder final_pass =
wgpuCommandEncoderBeginRenderPass(encoder, &final_desc);
passthrough_effect_->render(final_pass, 0, 0, 0, aspect_ratio);
wgpuRenderPassEncoderEnd(final_pass);
-
- wgpuTextureViewRelease(final_view);
- wgpuSurfacePresent(surface);
- wgpuTextureRelease(st.texture);
} else {
WGPUTextureView current_input = framebuffer_view_a_;
for (size_t i = 0; i < post_effects.size(); ++i) {
bool is_last = (i == post_effects.size() - 1);
- WGPUSurfaceTexture st;
- if (is_last)
- wgpuSurfaceGetCurrentTexture(surface, &st);
+ WGPUTextureView current_output = nullptr;
- WGPUTextureView current_output =
- is_last
- ? wgpuTextureCreateView(st.texture, nullptr)
- : (current_input == framebuffer_view_a_ ? framebuffer_view_b_
- : framebuffer_view_a_);
+ if (is_last) {
+ wgpuSurfaceGetCurrentTexture(surface, &st);
+ final_view = wgpuTextureCreateView(st.texture, nullptr);
+ current_output = final_view;
+ } else {
+ current_output =
+ (current_input == framebuffer_view_a_ ? framebuffer_view_b_
+ : framebuffer_view_a_);
+ }
PostProcessEffect *pp =
static_cast<PostProcessEffect *>(post_effects[i]->effect.get());
pp->update_bind_group(current_input);
- WGPURenderPassColorAttachment pp_attachment = {.view = current_output,
- .loadOp = WGPULoadOp_Load,
- .storeOp =
- WGPUStoreOp_Store};
+ WGPURenderPassColorAttachment pp_attachment = {};
+ pp_attachment.view = current_output;
+ pp_attachment.resolveTarget = nullptr;
+ pp_attachment.loadOp = WGPULoadOp_Load;
+ pp_attachment.storeOp = WGPUStoreOp_Store;
+ pp_attachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
WGPURenderPassDescriptor pp_desc = {.colorAttachmentCount = 1,
.colorAttachments = &pp_attachment};
WGPURenderPassEncoder pp_pass =
@@ -241,18 +244,18 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
pp->render(pp_pass, global_time - post_effects[i]->start_time, beat, peak,
aspect_ratio);
wgpuRenderPassEncoderEnd(pp_pass);
-
- if (is_last) {
- wgpuTextureViewRelease(current_output);
- wgpuSurfacePresent(surface);
- wgpuTextureRelease(st.texture);
- }
current_input = current_output;
}
}
WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, nullptr);
wgpuQueueSubmit(queue, 1, &commands);
+
+ if (st.texture) {
+ wgpuTextureViewRelease(final_view);
+ wgpuSurfacePresent(surface);
+ wgpuTextureRelease(st.texture);
+ }
}
void MainSequence::shutdown() {
diff --git a/src/gpu/gpu.h b/src/gpu/gpu.h
index 0bc20b7..c2c0670 100644
--- a/src/gpu/gpu.h
+++ b/src/gpu/gpu.h
@@ -8,8 +8,6 @@
#include <cstring> // For strlen
-
-
#if defined(DEMO_CROSS_COMPILE_WIN32)
// Windows (MinGW) using wgpu-native v0.19.4.1
@@ -18,69 +16,52 @@
#include <webgpu/wgpu.h>
+static inline const char *str_view(const char *str) {
+ return str;
+}
-
-static inline const char *str_view(const char *str) { return str; }
-
-
-
-static inline const char *label_view(const char *str) { return str; }
-
-
-
-
-
-
+static inline const char *label_view(const char *str) {
+ return str;
+}
#define WGPUSType_ShaderSourceWGSL WGPUSType_ShaderModuleWGSLDescriptor
-
-
using WGPUShaderSourceWGSL = WGPUShaderModuleWGSLDescriptor;
+#define WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal \
+ WGPUSurfaceGetCurrentTextureStatus_Success
-
-#define WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal WGPUSurfaceGetCurrentTextureStatus_Success
-
-
-
-#define WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal WGPUSurfaceGetCurrentTextureStatus_Success
-
-
+#define WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal \
+ WGPUSurfaceGetCurrentTextureStatus_Success
#define WGPUCallbackMode_WaitAnyOnly 0
-
-
-
+#define WGPU_DEPTH_SLICE_UNDEFINED (0xffffffff)
#else
-// Native (macOS/Linux) using newer wgpu-native
+// Native (macOS/Linux) using newer wgpu-native
#include <webgpu.h>
#include <wgpu.h>
-
-
static inline WGPUStringView str_view(const char *str) {
- if (!str) return {nullptr, 0};
+ if (!str)
+ return {nullptr, 0};
return {str, strlen(str)};
-
}
-
-
static inline WGPUStringView label_view(const char *str) {
#ifndef STRIP_ALL
- if (!str) return {nullptr, 0};
+ if (!str)
+ return {nullptr, 0};
return {str, strlen(str)};
@@ -91,15 +72,10 @@ static inline WGPUStringView label_view(const char *str) {
return {nullptr, 0};
#endif
-
}
-
-
#endif
-
-
struct GLFWwindow;
// Basic wrapper for WebGPU buffers