summaryrefslogtreecommitdiff
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/effect.cc19
-rw-r--r--src/gpu/effect.h20
-rw-r--r--src/gpu/gpu.cc35
-rw-r--r--src/gpu/gpu.h9
-rw-r--r--src/gpu/wgpu_resource.h45
5 files changed, 127 insertions, 1 deletions
diff --git a/src/gpu/effect.cc b/src/gpu/effect.cc
index 752dd84..d0693ec 100644
--- a/src/gpu/effect.cc
+++ b/src/gpu/effect.cc
@@ -14,6 +14,7 @@ Effect::Effect(const GpuContext& ctx, const std::vector<std::string>& inputs,
FATAL_CHECK(!outputs.empty(), "Effect must have at least one output\n");
FATAL_CHECK(start_time <= end_time, "Invalid time range: %f > %f\n",
start_time, end_time);
+ HEADLESS_RETURN_IF_NULL(ctx_.device);
}
void Effect::dispatch_render(WGPUCommandEncoder encoder,
@@ -55,3 +56,21 @@ void Effect::blit_input_to_output(WGPUCommandEncoder encoder,
wgpuCommandEncoderCopyTextureToTexture(encoder, &src_copy, &dst_copy,
&extent);
}
+
+void Effect::init_uniforms_buffer() {
+ uniforms_buffer_.init(ctx_.device);
+}
+
+void Effect::create_linear_sampler() {
+ sampler_.set(gpu_create_linear_sampler(ctx_.device));
+}
+
+void Effect::create_nearest_sampler() {
+ sampler_.set(gpu_create_nearest_sampler(ctx_.device));
+}
+
+void Effect::create_dummy_scene_texture() {
+ TextureWithView dummy = gpu_create_dummy_scene_texture(ctx_.device);
+ dummy_texture_.set(dummy.texture);
+ dummy_texture_view_.set(dummy.view);
+}
diff --git a/src/gpu/effect.h b/src/gpu/effect.h
index f5cdf2d..d47a8b7 100644
--- a/src/gpu/effect.h
+++ b/src/gpu/effect.h
@@ -6,6 +6,8 @@
#include "gpu/gpu.h"
#include "gpu/sequence.h"
+#include "gpu/uniform_helper.h"
+#include "gpu/wgpu_resource.h"
#include <string>
#include <vector>
@@ -51,6 +53,24 @@ class Effect {
int width_ = 1280;
int height_ = 720;
+ // Common resources for most effects
+ UniformBuffer<UniformsSequenceParams> uniforms_buffer_;
+ Sampler sampler_;
+ Texture dummy_texture_;
+ TextureView dummy_texture_view_;
+
+ // Helper: Initialize uniforms buffer (call in subclass constructor)
+ void init_uniforms_buffer();
+
+ // Helper: Create linear sampler (call in subclass constructor)
+ void create_linear_sampler();
+
+ // Helper: Create nearest sampler (call in subclass constructor)
+ void create_nearest_sampler();
+
+ // Helper: Create dummy texture for scene effects (call in subclass constructor)
+ void create_dummy_scene_texture();
+
private:
float start_time_;
float end_time_;
diff --git a/src/gpu/gpu.cc b/src/gpu/gpu.cc
index 2226889..e743bf7 100644
--- a/src/gpu/gpu.cc
+++ b/src/gpu/gpu.cc
@@ -124,6 +124,41 @@ WGPUTextureView gpu_create_texture_view_2d(WGPUTexture texture,
return wgpuTextureCreateView(texture, &view_desc);
}
+WGPUSampler gpu_create_linear_sampler(WGPUDevice device) {
+ WGPUSamplerDescriptor desc = {};
+ desc.addressModeU = WGPUAddressMode_ClampToEdge;
+ desc.addressModeV = WGPUAddressMode_ClampToEdge;
+ desc.addressModeW = WGPUAddressMode_ClampToEdge;
+ desc.magFilter = WGPUFilterMode_Linear;
+ desc.minFilter = WGPUFilterMode_Linear;
+ desc.mipmapFilter = WGPUMipmapFilterMode_Nearest;
+ desc.maxAnisotropy = 1;
+ return wgpuDeviceCreateSampler(device, &desc);
+}
+
+WGPUSampler gpu_create_nearest_sampler(WGPUDevice device) {
+ WGPUSamplerDescriptor desc = {};
+ desc.addressModeU = WGPUAddressMode_ClampToEdge;
+ desc.addressModeV = WGPUAddressMode_ClampToEdge;
+ desc.magFilter = WGPUFilterMode_Nearest;
+ desc.minFilter = WGPUFilterMode_Nearest;
+ desc.maxAnisotropy = 1;
+ return wgpuDeviceCreateSampler(device, &desc);
+}
+
+TextureWithView gpu_create_dummy_scene_texture(WGPUDevice device) {
+ WGPUTextureDescriptor desc = {};
+ desc.size = {1, 1, 1};
+ desc.format = WGPUTextureFormat_RGBA8Unorm;
+ desc.usage = WGPUTextureUsage_TextureBinding;
+ desc.dimension = WGPUTextureDimension_2D;
+ desc.mipLevelCount = 1;
+ desc.sampleCount = 1;
+ WGPUTexture texture = wgpuDeviceCreateTexture(device, &desc);
+ WGPUTextureView view = wgpuTextureCreateView(texture, nullptr);
+ return {texture, view};
+}
+
RenderPass gpu_create_render_pass(WGPUDevice device, WGPUTextureFormat format,
const char* shader_code,
ResourceBinding* bindings, int num_bindings) {
diff --git a/src/gpu/gpu.h b/src/gpu/gpu.h
index 9a3fd38..d6c0255 100644
--- a/src/gpu/gpu.h
+++ b/src/gpu/gpu.h
@@ -97,4 +97,11 @@ RenderPass
gpu_create_render_pass(WGPUDevice device,
WGPUTextureFormat format, // Needed for render pipeline
const char* shader_code, ResourceBinding* bindings,
- int num_bindings); \ No newline at end of file
+ int num_bindings);
+
+// Common sampler configurations
+WGPUSampler gpu_create_linear_sampler(WGPUDevice device);
+WGPUSampler gpu_create_nearest_sampler(WGPUDevice device);
+
+// Dummy 1x1 texture for scene effects (don't need texture input)
+TextureWithView gpu_create_dummy_scene_texture(WGPUDevice device); \ No newline at end of file
diff --git a/src/gpu/wgpu_resource.h b/src/gpu/wgpu_resource.h
new file mode 100644
index 0000000..e448b18
--- /dev/null
+++ b/src/gpu/wgpu_resource.h
@@ -0,0 +1,45 @@
+// WGPU Resource RAII Wrapper
+// Automatic release on destruction
+//
+// IMPORTANT: Field ordering matters for destruction order.
+// Members are destroyed in reverse declaration order.
+// Declare dependencies before dependents:
+// RenderPipeline pipeline_; // Destroyed last
+// BindGroup bind_group_; // Destroyed first (may reference pipeline)
+
+#pragma once
+#include "platform/platform.h"
+#include "util/fatal_error.h"
+
+template<typename T, void(*Release)(T)>
+class WGPUResource {
+ public:
+ WGPUResource() : ptr_(nullptr) {}
+ ~WGPUResource() { if (ptr_) Release(ptr_); }
+
+ void set(T ptr) {
+ FATAL_ASSERT(ptr_ == nullptr);
+ ptr_ = ptr;
+ }
+
+ void replace(T ptr) {
+ if (ptr_) Release(ptr_);
+ ptr_ = ptr;
+ }
+
+ T get() const { return ptr_; }
+ T* get_address() { return &ptr_; }
+
+ private:
+ T ptr_;
+ WGPUResource(const WGPUResource&) = delete;
+ WGPUResource& operator=(const WGPUResource&) = delete;
+};
+
+using BindGroup = WGPUResource<WGPUBindGroup, wgpuBindGroupRelease>;
+using RenderPipeline = WGPUResource<WGPURenderPipeline, wgpuRenderPipelineRelease>;
+using ComputePipeline = WGPUResource<WGPUComputePipeline, wgpuComputePipelineRelease>;
+using Sampler = WGPUResource<WGPUSampler, wgpuSamplerRelease>;
+using Texture = WGPUResource<WGPUTexture, wgpuTextureRelease>;
+using TextureView = WGPUResource<WGPUTextureView, wgpuTextureViewRelease>;
+using Buffer = WGPUResource<WGPUBuffer, wgpuBufferRelease>;