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 &buffers)
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);
72 buffers.bufferMemoryConsumption += size;
74 alias.push_back(buffer);
77 if(graphicsDevice->use_error_scope){
78 WGPUPopErrorScopeCallbackInfo info = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT;
79 info.mode = WGPUCallbackMode_AllowSpontaneous;
80 info.callback = buffer_error_callback;
81 info.userdata1 =
this;
82 info.userdata2 = graphicsDevice;
83 WGPUFuture future = wgpuDevicePopErrorScope(graphicsDevice->device, info);
87 void BufferWebGPU::NextInstance(GraphicsDeviceWebGPU *graphicsDevice, BuffersWebGPU &buffers)
89 uint32_t idx = alias_idx;
92 if(idx >= alias.size()){
93 CreateInstance(graphicsDevice, buffers);
94 assert(idx+1 == alias.size());
100 void BufferWebGPU::ResetInstance()
106 void BuffersWebGPU::initialize(GraphicsDeviceWebGPU *device)
108 graphicsDevice = device;
110 void BuffersWebGPU::resetInstances()
112 for(BufferWebGPU &buffer : buffers){
113 buffer.ResetInstance();
120 buffer.label = std::string(name.
data(), name.
length());
122 WGPUStringView label;
123 label.data = buffer.label.data();
124 label.length = buffer.label.length();
126 if(!buffer.is_read_buffer){
127 wgpuBufferSetLabel(buffer.buffer, label);
130 for(WGPUBuffer &alias: buffer.alias){
131 wgpuBufferRelease(alias);
142 const uint32_t stride = getSize(vertexFormat);
143 const size_t size = count * stride;
150 return loadVertexBuffer(vertexData, count, *VertexFormats::getVertexFormat(vertexFormatHandle));
155 buffers.removeResource(handle);
160 const size_t size = count * indexSize;
167 buffers.removeResource(handle);
172 size_t attribute_count = 0;
173 for(
size_t i=0; i<count; i++){
174 const VertexFormat *vtx_format = getVertexFormat(vertexFormats[i]);
175 for(
size_t j=0; j<vtx_format->
elements.size(); j++){
177 if(element.
format == DataFormat::MAT4X4_FLOAT){
178 attribute_count += 4;
181 attribute_count += 1;
187 input_layout.vertex_attributes.resize(attribute_count);
188 input_layout.vertex_buffer_layout.resize(count);
190 size_t attribute_offset = 0;
191 for(
size_t i=0; i<count; i++){
192 const VertexFormat *vtx_format = getVertexFormat(vertexFormats[i]);
193 WGPUVertexBufferLayout &vtx_layout = input_layout.vertex_buffer_layout[i];
194 vtx_layout.arrayStride = getSize(*vtx_format);
196 vtx_layout.stepMode = WGPUVertexStepMode_Vertex;
199 vtx_layout.stepMode = WGPUVertexStepMode_Instance;
205 vtx_layout.attributeCount = 0;
206 vtx_layout.attributes = vtx_format->
elements.size() ? &input_layout.vertex_attributes[attribute_offset] :
nullptr;
207 for(
size_t j=0; j<vtx_format->
elements.size(); j++){
209 if(vtx_layout.stepMode == WGPUVertexStepMode_Vertex){
213 else if(vtx_layout.stepMode == WGPUVertexStepMode_Instance){
220 EffectWebGPU& effect = graphicsDevice->effects.effects[effectHandle];
222 uint32_t attribute_location = std::numeric_limits<uint32_t>::max();
224 semantic.format =
static_cast<WGPUVertexFormat
>(0);
225 for (
size_t s = 0; s < effect.num_attribs; s++) {
228 attribute_location = sem.binding;
233 if (attribute_location == std::numeric_limits<uint32_t>::max()) {
234 LOG_WARNING(logger,
"Vertex attribute semantic %d, slot %d not used in shader", (
int)element.
semantic, element.
semanticIndex);
236 if(element.
format == DataFormat::MAT4X4_FLOAT){
237 for(
int k=0; k<4; k++){
238 WGPUVertexAttribute &att = input_layout.vertex_attributes[attribute_offset++];
239 att.format = WGPUVertexFormat_Float32x4;
240 att.offset = element.
offset +
sizeof(float)*4*k;
241 att.shaderLocation = attribute_location+k;
242 vtx_layout.attributeCount++;
246 DataFormat format = element.
format;
249 if(format == DataFormat::R8G8B8_UNORM){
250 format = DataFormat::R8G8B8A8_UNORM;
251 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_UNORM not supported by WebGPU (Using R8G8B8A8_UNORM).");
253 else if(format == DataFormat::R8G8B8_SNORM){
254 format = DataFormat::R8G8B8A8_SNORM;
255 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_SNORM not supported by WebGPU (Using R8G8B8A8_SNORM).");
257 else if(format == DataFormat::R8G8B8_UINT){
258 format = DataFormat::R8G8B8A8_UINT;
259 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_UINT not supported by WebGPU (Using R8G8B8A8_UINT).");
261 else if(format == DataFormat::R8G8B8_SINT){
262 format = DataFormat::R8G8B8A8_SINT;
263 LOG_WARNING(logger,
"Vertex attribute format R8G8B8_SINT not supported by WebGPU (Using R8G8B8A8_SINT).");
265 else if(format == DataFormat::R16G16B16_UNORM){
266 format = DataFormat::R16G16B16A16_UNORM;
267 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_UNORM not supported by WebGPU (Using R16G16B16A16_UNORM).");
269 else if(format == DataFormat::R16G16B16_SNORM){
270 format = DataFormat::R16G16B16A16_SNORM;
271 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_SNORM not supported by WebGPU (Using R16G16B16A16_SNORM).");
273 else if(format == DataFormat::R16G16B16_UINT){
274 format = DataFormat::R16G16B16A16_UINT;
275 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_UINT not supported by WebGPU (Using R16G16B16A16_UINT).");
277 else if(format == DataFormat::R16G16B16_SINT){
278 format = DataFormat::R16G16B16A16_SINT;
279 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_SINT not supported by WebGPU (Using R16G16B16A16_SINT).");
281 else if(format == DataFormat::R16G16B16_FLOAT){
282 format = DataFormat::R16G16B16A16_FLOAT;
283 LOG_WARNING(logger,
"Vertex attribute format R16G16B16_FLOAT not supported by WebGPU (Using R16G16B16A16_FLOAT).");
285 WGPUVertexAttribute &att = input_layout.vertex_attributes[attribute_offset++];
286 att.format = VertexFormatsWebGPU[(size_t)format];
287 if (semantic.format != att.format) {
288 LOG_WARNING(logger,
"Inconsistent vertex attribute format");
290 assert(att.format !=
static_cast<WGPUVertexFormat
>(0));
291 att.offset = element.
offset;
292 att.shaderLocation = attribute_location;
293 vtx_layout.attributeCount++;
297 assert(attribute_offset == input_layout.vertex_attributes.size());
298 return inputLayouts.addResource(std::move(input_layout));
303 inputLayouts.removeResource(inputLayoutHandle);
313 buffer.accessMode = accessMode;
314 buffer.bindFlags = bindFlags;
317 buffer.is_read_buffer =
true;
318 assert(bindFlags == 0);
320 size_t granularity = 256;
321 if(buffer.size%granularity != 0)
322 buffer.size += granularity-buffer.size%granularity;
326 size_t granularity = 16;
327 if (buffer.size % granularity != 0)
328 buffer.size += granularity - buffer.size % granularity;
331 buffer.CreateInstance(graphicsDevice, *
this);
333 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, 0, data, buffer.size);
336 return this->buffers.addResource(std::move(buffer));
343 if(!buffer.is_read_buffer){
344 wgpuBufferRelease(buffer.buffer);
346 bufferMemoryConsumption -= buffer.size;
349 for(WGPUBuffer &alias: buffer.alias){
350 wgpuBufferRelease(alias);
352 bufferMemoryConsumption -= buffer.size;
355 buffers.removeResource(handle);
360 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 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.
@ 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.
@ 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.