1#include "BuffersWebGPU.h"
3#include "FormatsWebGPU.h"
4#include "GraphicsDeviceWebGPU.h"
6#include "Foundation/Logging/Logger.h"
11 void buffer_error_callback(WGPUPopErrorScopeStatus status, WGPUErrorType type, WGPUStringView message,
void* userdata1,
void* userdata2)
17 if(status == WGPUPopErrorScopeStatus_CallbackCancelled){
18 LOG_ERROR(logger,
"WebGPU buffer err status: Cancelled");
20 if(status == WGPUPopErrorScopeStatus_Error){
21 LOG_ERROR(logger,
"WebGPU buffer err status: Error");
23 if(message.data && message.length){
24 LOG_ERROR(logger,
"WebGPU buffer err (%d) %.*s", type, WGPUStringViewFormat(message));
31 void BufferWebGPU::CreateInstance(GraphicsDeviceWebGPU *graphicsDevice, BuffersWebGPU & )
33 ResourceCountersWebGPU &counters = graphicsDevice->counters;
34 WGPUBufferDescriptor desc = WGPU_BUFFER_DESCRIPTOR_INIT;
35 desc.label.length = WGPU_STRLEN;
37 desc.label.data = label.data();
38 desc.label.length = label.length();
41 desc.usage |= WGPUBufferUsage_MapRead;
42 desc.usage |= WGPUBufferUsage_CopyDst;
45 desc.usage |= WGPUBufferUsage_CopyDst;
49 desc.usage |= WGPUBufferUsage_Vertex;
51 desc.usage |= WGPUBufferUsage_Index;
53 desc.usage |= WGPUBufferUsage_Uniform;
55 desc.usage |= WGPUBufferUsage_Storage;
57 desc.usage |= WGPUBufferUsage_Storage;
59 desc.usage |= WGPUBufferUsage_Storage;
61 desc.usage |= WGPUBufferUsage_Storage;
64 desc.mappedAtCreation =
false;
66 if(graphicsDevice->use_error_scope){
67 wgpuDevicePushErrorScope(graphicsDevice->device, graphicsDevice->filter);
70 buffer = wgpuDeviceCreateBuffer(graphicsDevice->device, &desc);
73 alias.push_back(buffer);
76 if(graphicsDevice->use_error_scope){
77 WGPUPopErrorScopeCallbackInfo info = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT;
78 info.mode = WGPUCallbackMode_AllowSpontaneous;
79 info.callback = buffer_error_callback;
80 info.userdata1 =
this;
81 info.userdata2 = graphicsDevice;
82 WGPUFuture future = wgpuDevicePopErrorScope(graphicsDevice->device, info);
86 void BufferWebGPU::NextInstance(GraphicsDeviceWebGPU *graphicsDevice, BuffersWebGPU &buffers)
88 uint32_t idx = alias_idx;
91 if(idx >= alias.size()){
92 CreateInstance(graphicsDevice, buffers);
93 assert(idx+1 == alias.size());
99 void BufferWebGPU::ResetInstance()
105 void BuffersWebGPU::initialize(GraphicsDeviceWebGPU *device)
107 graphicsDevice = device;
109 void BuffersWebGPU::resetInstances()
111 for(BufferWebGPU &buffer : buffers){
112 buffer.ResetInstance();
119 buffer.label = std::string(name.
data(), name.
length());
121 WGPUStringView label;
122 label.data = buffer.label.data();
123 label.length = buffer.label.length();
125 if(buffer.is_read_buffer){
126 wgpuBufferSetLabel(buffer.buffer, label);
129 for(WGPUBuffer &alias: buffer.alias){
130 wgpuBufferSetLabel(alias, label);
141 const uint32_t stride = getSize(vertexFormat);
142 const size_t size = count * stride;
149 return loadVertexBuffer(vertexData, count, *VertexFormats::getVertexFormat(vertexFormatHandle));
154 buffers.removeResource(handle);
159 const size_t size = count * indexSize;
166 buffers.removeResource(handle);
171 size_t attribute_count = 0;
172 for(
size_t i=0; i<count; i++){
173 const VertexFormat *vtx_format = getVertexFormat(vertexFormats[i]);
174 for(
size_t j=0; j<vtx_format->
elements.size(); j++){
176 if(element.
format == DataFormat::MAT4X4_FLOAT){
177 attribute_count += 4;
180 attribute_count += 1;
186 input_layout.vertex_attributes.resize(attribute_count);
187 input_layout.vertex_buffer_layout.resize(count);
189 size_t attribute_offset = 0;
190 for(
size_t i=0; i<count; i++){
191 const VertexFormat *vtx_format = getVertexFormat(vertexFormats[i]);
192 WGPUVertexBufferLayout &vtx_layout = input_layout.vertex_buffer_layout[i];
193 vtx_layout.arrayStride = getSize(*vtx_format);
195 vtx_layout.stepMode = WGPUVertexStepMode_Vertex;
198 vtx_layout.stepMode = WGPUVertexStepMode_Instance;
204 vtx_layout.attributeCount = 0;
205 vtx_layout.attributes = vtx_format->
elements.size() ? &input_layout.vertex_attributes[attribute_offset] :
nullptr;
206 for(
size_t j=0; j<vtx_format->
elements.size(); j++){
208 if(vtx_layout.stepMode == WGPUVertexStepMode_Vertex){
212 else if(vtx_layout.stepMode == WGPUVertexStepMode_Instance){
219 EffectWebGPU& effect = graphicsDevice->effects.effects[effectHandle];
221 uint32_t attribute_location = std::numeric_limits<uint32_t>::max();
223 semantic.format =
static_cast<WGPUVertexFormat
>(0);
224 for (
size_t s = 0; s < effect.num_attribs; s++) {
227 attribute_location = sem.binding;
232 if (attribute_location == std::numeric_limits<uint32_t>::max()) {
233 LOG_WARNING(logger,
"Vertex attribute semantic %d, slot %d not used in shader", (
int)element.
semantic, element.
semanticIndex);
235 if(element.
format == DataFormat::MAT4X4_FLOAT){
236 for(
int k=0; k<4; k++){
237 WGPUVertexAttribute &att = input_layout.vertex_attributes[attribute_offset++];
238 att.format = WGPUVertexFormat_Float32x4;
239 att.offset = element.
offset +
sizeof(float)*4*k;
240 att.shaderLocation = attribute_location+k;
241 vtx_layout.attributeCount++;
245 DataFormat format = element.
format;
248 if(format == DataFormat::R8G8B8_UNORM){
249 format = DataFormat::R8G8B8A8_UNORM;
250 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_UNORM not supported by WebGPU (Using R8G8B8A8_UNORM).");
252 else if(format == DataFormat::R8G8B8_SNORM){
253 format = DataFormat::R8G8B8A8_SNORM;
254 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_SNORM not supported by WebGPU (Using R8G8B8A8_SNORM).");
256 else if(format == DataFormat::R8G8B8_UINT){
257 format = DataFormat::R8G8B8A8_UINT;
258 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_UINT not supported by WebGPU (Using R8G8B8A8_UINT).");
260 else if(format == DataFormat::R8G8B8_SINT){
261 format = DataFormat::R8G8B8A8_SINT;
262 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_SINT not supported by WebGPU (Using R8G8B8A8_SINT).");
264 else if(format == DataFormat::R16G16B16_UNORM){
265 format = DataFormat::R16G16B16A16_UNORM;
266 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_UNORM not supported by WebGPU (Using R16G16B16A16_UNORM).");
268 else if(format == DataFormat::R16G16B16_SNORM){
269 format = DataFormat::R16G16B16A16_SNORM;
270 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_SNORM not supported by WebGPU (Using R16G16B16A16_SNORM).");
272 else if(format == DataFormat::R16G16B16_UINT){
273 format = DataFormat::R16G16B16A16_UINT;
274 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_UINT not supported by WebGPU (Using R16G16B16A16_UINT).");
276 else if(format == DataFormat::R16G16B16_SINT){
277 format = DataFormat::R16G16B16A16_SINT;
278 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_SINT not supported by WebGPU (Using R16G16B16A16_SINT).");
280 else if(format == DataFormat::R16G16B16_FLOAT){
281 format = DataFormat::R16G16B16A16_FLOAT;
282 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_FLOAT not supported by WebGPU (Using R16G16B16A16_FLOAT).");
284 WGPUVertexAttribute &att = input_layout.vertex_attributes[attribute_offset++];
285 att.format = VertexFormatsWebGPU[(size_t)format];
286 assert(att.format !=
static_cast<WGPUVertexFormat
>(0));
287 att.offset = element.
offset;
288 att.shaderLocation = attribute_location;
289 vtx_layout.attributeCount++;
293 assert(attribute_offset == input_layout.vertex_attributes.size());
294 return inputLayouts.addResource(std::move(input_layout));
299 inputLayouts.removeResource(inputLayoutHandle);
309 buffer.accessMode = accessMode;
310 buffer.bindFlags = bindFlags;
313 buffer.is_read_buffer =
true;
314 assert(bindFlags == 0);
316 size_t granularity = 256;
317 if(buffer.size%granularity != 0)
318 buffer.size += granularity-buffer.size%granularity;
322 size_t granularity = 16;
323 if (buffer.size % granularity != 0)
324 buffer.size += granularity - buffer.size % granularity;
327 buffer.CreateInstance(graphicsDevice, *
this);
329 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, 0, data, buffer.size);
332 const size_t roundedSize = buffer.size;
333 BufferHandle handle = this->buffers.addResource(std::move(buffer));
340 if (!HandleIsValid(handle))
return;
345 if(buffer.is_read_buffer){
346 wgpuBufferDestroy(buffer.buffer);
347 wgpuBufferRelease(buffer.buffer);
351 for(WGPUBuffer &alias: buffer.alias){
352 wgpuBufferDestroy(alias);
353 wgpuBufferRelease(alias);
356 buffer.alias.clear();
358 buffers.removeResource(handle);
364 std::vector<BufferHandle> handles;
365 for (
auto& resource : buffers) {
366 handles.push_back(buffers.getHandle(resource));
368 for (
auto& handle : handles) {
373 std::vector<InputLayoutHandle> handles;
374 for (
auto& resource : inputLayouts) {
375 handles.push_back(inputLayouts.getHandle(resource));
377 for (
auto& handle : handles) {
385 return static_cast<void*
>(buffers[handle].buffer);
virtual IndexBufferHandle loadIndexBuffer(const void *, const size_t, const size_t) override
Loads a new index buffer and populates it with the given indexData.
virtual void annotate(BufferHandle handle, const StringView &name) override
Associate a name with an object for use in graphics debugging.
virtual VertexBufferHandle loadVertexBuffer(const void *, const size_t, const VertexFormat &vertexFormat) override
Loads a new vertex buffer and populates it with the given data.
virtual void releaseVertexBuffer(VertexBufferHandle vertexBufferHandle) override
Release the vertex buffer with the given handle.
virtual InputLayoutHandle loadInputLayout(const VertexFormatHandle *vertexFormats, const size_t count, EffectHandle effectHandle) override
Loads a new input layout to map vertex flow between vertex buffers with the given vertexFormats to ef...
virtual BufferHandle loadBuffer(const void *, const size_t, Usage::EUsage, uint32_t, uint32_t, uint32_t=0) override
Loads a new buffer using the given data to populate the buffer.
virtual void * getNativeHandle(BufferHandle bufferHandle) override
Get the device-specific handle (D3D buffer pointer, OpenGL buffer ID etc) associated with the given b...
virtual void releaseResources() override
Releases all allocated buffer resources.
virtual void releaseBuffer(BufferHandle bufferHandle) override
Releases the buffer with the given bufferHandle.
virtual void releaseInputLayout(InputLayoutHandle inputLayoutHandle) override
Releases the input layout with the given inputLayoutHandle.
virtual void releaseIndexBuffer(IndexBufferHandle indexBufferHandle) override
Releases the index buffer with the given handle.
Log implementation class.
Provides a weakly referenced view over the contents of a string.
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
constexpr size_t length() const noexcept
Get the length of the string.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
@ InstanceData
Per instance data.
@ VertexData
Per vertex data.
@ Read
The buffer can be mapped and read from by the CPU after creation.
@ None
The buffer can not be either read from or written to by the CPU after creation.
EBindFlags
Bind flags enumeration.
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
@ StructuredBufferWithCounter
The buffer can be bound as a structured buffer and read or written from shaders, with an additional a...
@ StreamOutBuffer
The buffer can be bound as stream output to receive transform feedback results.
@ VertexBuffer
The buffer can be bound as input to the vertex shader stage as a vertex buffer.
@ RawBuffer
The buffer can be bound as a byte address buffer and read or written from shaders.
@ IndexBuffer
The buffer can be bound as input to the vertex shader stage as an index buffer.
@ ShaderResource
The buffer can be bound as a shader resource and read from shaders.
@ StructuredBuffer
The buffer can be bound as a structured buffer and read or written from shaders.
void recordBufferRelease(BufferHandle handle, BindFlags::EBindFlags bindFlags, size_t bytes)
void recordBufferCreate(BufferHandle handle, BindFlags::EBindFlags bindFlags, size_t bytes)
@ Dynamic
Buffer will be loaded and modified with some frequency.
Vertex element structure used to describe a single data element in a vertex for the input assembler.
InputType inputType
Input type of the element, vertex or instance data.
DataFormat format
Format of the element.
uint16_t offset
Offset in bytes from the vertex position in memory.
uint16_t semanticIndex
Index for the semantic mapping.
ElementSemantic semantic
Semantic mapping of the element (position, normal, etc...).
uint16_t instanceStep
Instance step factor.