载入中...
搜索中...
未找到
ShaderSystem.cpp
浏览该文件的文档.
2#include "gpgpu/Gpgpu.h"
3#include "gpgpu/GpuBuffer.h"
4#include "gpgpu/Sequence.h"
5
6#include "common/Exception.h"
7
8#include <algorithm>
9#include <cstring>
10
11namespace eve::gpgpu {
12
15 if (ownsShader_) {
16 delete shader_;
17 shader_ = nullptr;
18 ownsShader_ = false;
19 }
20}
21
22void ShaderSystem::setGpgpu(Gpgpu *gpu) { gpu_ = gpu; }
23
24void ShaderSystem::setShaderSource(const std::string &glsl) {
25 if (!gpu_) throw Exception("ShaderSystem.setShaderSource: Gpgpu is null");
26 ComputeShader *compiled = gpu_->newShader(glsl);
27 if (ownsShader_) delete shader_;
28 shader_ = compiled;
29 ownsShader_ = true;
30}
31
32void ShaderSystem::setShader(ComputeShader *shader, bool takeOwnership) {
33 if (ownsShader_ && shader_ != shader) {
34 delete shader_;
35 ownsShader_ = false;
36 }
37 shader_ = shader;
38 ownsShader_ = takeOwnership && shader != nullptr;
39}
40
41void ShaderSystem::setLocalSize(int localSize) {
42 localSize_ = localSize > 0 ? localSize : kDefaultLocalSize;
43}
44
46 if (binding < 0 || binding >= kMaxBindings)
47 throw Exception("ShaderSystem.ensureBuffer: binding out of range");
48 if (!gpu_) throw Exception("ShaderSystem.ensureBuffer: Gpgpu is null");
49 if (floatCount <= 0) floatCount = 1;
50
51 const int bytes = floatCount * int(sizeof(float));
52 GpuBuffer *existing = buffers_[binding];
53 if (existing && existing->getSize() >= bytes) return existing;
54
55 GpuBuffer *created = gpu_->newBuffer(bytes, "storage");
56 if (ownsBuffer_[binding]) delete existing;
57 buffers_[binding] = created;
58 ownsBuffer_[binding] = true;
59 return created;
60}
61
63 if (binding < 0 || binding >= kMaxBindings) return nullptr;
64 return buffers_[binding];
65}
66
68 if (binding < 0 || binding >= kMaxBindings) throw Exception("ShaderSystem.attachBuffer: binding out of range");
69 if (!buffer) throw Exception("ShaderSystem.attachBuffer: buffer is null");
70 if (buffers_[binding] == buffer) return;
71 if (ownsBuffer_[binding]) delete buffers_[binding];
72 buffers_[binding] = buffer;
73 ownsBuffer_[binding] = false;
74}
75
76void ShaderSystem::upload(int binding, const float *data, int floatCount) {
77 if (!data || floatCount <= 0) return;
78 GpuBuffer *buf = ensureBuffer(binding, floatCount);
79 buf->writeFloat32s(data, floatCount, 0);
80 ++uploadCount_;
81}
82
83void ShaderSystem::download(int binding, float *out, int floatCount) const {
84 if (!out || floatCount <= 0) return;
86 if (!buf) throw Exception("ShaderSystem.download: binding has no buffer");
87 buf->readFloat32s(out, floatCount, 0);
88 ++downloadCount_;
89}
90
91void ShaderSystem::uploadRange(int binding, const float *data, int floatCount, int startFloat) {
92 if (!data || floatCount <= 0) return;
93 if (startFloat < 0) throw Exception("ShaderSystem.uploadRange: negative offset");
95 if (!buf) throw Exception("ShaderSystem.uploadRange: binding has no buffer");
96 const uint64_t end = (uint64_t(startFloat) + uint64_t(floatCount)) * sizeof(float);
97 if (end > uint64_t(buf->getSize())) throw Exception("ShaderSystem.uploadRange: range exceeds buffer");
98 buf->writeFloat32s(data, floatCount, startFloat);
99 ++uploadCount_;
100}
101
102void ShaderSystem::downloadRange(int binding, float *out, int floatCount, int startFloat) const {
103 if (!out || floatCount <= 0) return;
104 if (startFloat < 0) throw Exception("ShaderSystem.downloadRange: negative offset");
106 if (!buf) throw Exception("ShaderSystem.downloadRange: binding has no buffer");
107 const uint64_t end = (uint64_t(startFloat) + uint64_t(floatCount)) * sizeof(float);
108 if (end > uint64_t(buf->getSize())) throw Exception("ShaderSystem.downloadRange: range exceeds buffer");
109 buf->readFloat32s(out, floatCount, startFloat);
110 ++downloadCount_;
111}
112
113void ShaderSystem::upload(int binding, const std::vector<float> &data) {
114 if (data.empty()) return;
115 upload(binding, data.data(), int(data.size()));
116}
117
118std::vector<float> ShaderSystem::download(int binding, int floatCount) const {
119 std::vector<float> out(size_t(std::max(0, floatCount)));
120 if (floatCount > 0) download(binding, out.data(), floatCount);
121 return out;
122}
123
125 if (!shader_) return;
126 shader_->setFloat(index, value);
127}
128
130 if (!shader_) return 0.f;
131 return shader_->getFloat(index);
132}
133
134void ShaderSystem::dispatch(int entityCount, float dt) {
135 if (!gpu_ || !shader_ || entityCount <= 0) return;
136
137 for (int i = 0; i < kMaxBindings; ++i) {
138 if (buffers_[i]) shader_->bindBuffer(i, buffers_[i]);
139 }
140
141 shader_->setFloat(0, dt);
142 shader_->setFloat(1, float(entityCount));
143
144 const int ls = localSize_ > 0 ? localSize_ : kDefaultLocalSize;
145 const int groups = (entityCount + ls - 1) / ls;
146 gpu_->dispatch(shader_, groups, 1, 1);
147 ++dispatchCount_;
148}
149
150void ShaderSystem::recordDispatch(Sequence *sequence, int entityCount, float dt) {
151 if (!sequence) throw Exception("ShaderSystem.recordDispatch: sequence is null");
152 if (!shader_ || entityCount <= 0) return;
153
154 for (int i = 0; i < kMaxBindings; ++i) {
155 if (buffers_[i]) shader_->bindBuffer(i, buffers_[i]);
156 }
157 shader_->setFloat(0, dt);
158 shader_->setFloat(1, float(entityCount));
159
160 const int ls = localSize_ > 0 ? localSize_ : kDefaultLocalSize;
161 sequence->recordDispatch(shader_, (entityCount + ls - 1) / ls, 1, 1);
162 ++dispatchCount_;
163}
164
166 uploadCount_ = 0;
167 downloadCount_ = 0;
168 dispatchCount_ = 0;
169}
170
172 for (int i = 0; i < kMaxBindings; ++i) {
173 if (ownsBuffer_[i]) {
174 delete buffers_[i];
175 ownsBuffer_[i] = false;
176 }
177 buffers_[i] = nullptr;
178 }
179}
180
181} // namespace eve::gpgpu
double value
std::uint64_t bytes
uint32_t groups
Definition OnnxGpgpu.cpp:39
std::unique_ptr< gpgpu::GpuBuffer > buffer
Definition OnnxGpgpu.cpp:26
std::unique_ptr< gpgpu::Sequence > sequence
Definition OnnxGpgpu.cpp:43
eve::action::ActionVfxBinding binding
Shader * shader
int created
uint32_t index
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
Backend-agnostic compute program. Bind storage buffers then dispatch via Gpgpu::dispatch....
virtual void setFloat(int index, float value)=0
Sets the float.
virtual float getFloat(int index) const =0
Returns the float.
virtual void bindBuffer(int binding, GpuBuffer *buffer)=0
Bind a storage buffer to set=0 binding. binding in [0, kMaxBindings).
GPGPU module — compute shaders + storage buffers via the active Graphics backend. Uses the graphics q...
Definition Gpgpu.h:23
ComputeShader * newShader(const std::string &source)
Compatibility-only raw-owning shader factory (Vulkan: GLSL; WebGPU: WGSL). Vulkan delegates to the ch...
Definition Gpgpu.cpp:324
void dispatch(ComputeShader *shader, int groupsX, int groupsY=1, int groupsZ=1)
Record + submit a compute dispatch and wait for completion (sync). groups*: workgroup counts (not thr...
Definition Gpgpu.cpp:396
GpuBuffer * newBuffer(int byteSize, const std::string &usage="storage")
Allocate a GPU buffer. usage: "storage" (SSBO, device-local) | "staging" (host-visible transfer).
Definition Gpgpu.cpp:372
Backend-agnostic GPU buffer for compute (storage) or CPU staging transfers. Squirrel-owned; derived c...
Definition GpuBuffer.h:18
virtual void writeFloat32s(const float *data, int count, int startIndex=0)=0
Bulk float upload/download (one transfer). startIndex is in floats.
virtual int getSize() const =0
Byte length of the owned buffer.
virtual void readFloat32s(float *out, int count, int startIndex=0) const =0
Reads float 32 s.
EVENGINE_API_WORLD public API.
Definition Sequence.h:41
GpuBuffer * getBuffer(int binding) const
Returns the buffer.
void upload(int binding, const float *data, int floatCount)
Uploads upload.
GpuBuffer * ensureBuffer(int binding, int floatCount)
Ensure buffer.
~ShaderSystem()
Shader system.
void dispatch(int entityCount, float dt=0.f)
Dispatches dispatch.
static constexpr int kMaxBindings
void downloadRange(int binding, float *out, int floatCount, int startFloat) const
Download floats from an existing resident buffer range.
static constexpr int kDefaultLocalSize
void clearBuffers()
Clears buffers.
void download(int binding, float *out, int floatCount) const
Downloads download.
void setFloat(int index, float value)
Sets the float.
float getFloat(int index) const
Returns the float.
void attachBuffer(int binding, GpuBuffer *buffer)
Attach a non-owning resident buffer produced by another GPU system.
void setShaderSource(const std::string &glsl)
Sets the shader source.
void setLocalSize(int localSize)
Sets the local size.
void setGpgpu(Gpgpu *gpu)
Sets the gpgpu.
void resetStatistics()
Reset transfer and dispatch counters used for profiling.
void setShader(ComputeShader *shader, bool takeOwnership=false)
Sets the shader.
void uploadRange(int binding, const float *data, int floatCount, int startFloat)
Upload floats into an existing resident buffer range.
void recordDispatch(Sequence *sequence, int entityCount, float dt=0.f)
Record this system into a caller-owned sequence without submitting or waiting. The sequence and all a...
Fluids module — interactive surface fluid simulation.
Definition Fluids.h:34