diff --git a/generator/templates/dawn_native/webgpu_absl_format.cpp b/generator/templates/dawn_native/webgpu_absl_format.cpp index db748f3dac..42fb37ec8b 100644 --- a/generator/templates/dawn_native/webgpu_absl_format.cpp +++ b/generator/templates/dawn_native/webgpu_absl_format.cpp @@ -21,6 +21,36 @@ namespace dawn_native { + // + // Structs (Manually written) + // + + absl::FormatConvertResult + AbslFormatConvert(const Color* value, + const absl::FormatConversionSpec& spec, + absl::FormatSink* s) { + if (value == nullptr) { + s->Append("[null]"); + return {true}; + } + s->Append(absl::StrFormat("[Color r:%f, g:%f, b:%f, a:%f]", + value->r, value->g, value->b, value->a)); + return {true}; + } + + absl::FormatConvertResult + AbslFormatConvert(const Extent3D* value, + const absl::FormatConversionSpec& spec, + absl::FormatSink* s) { + if (value == nullptr) { + s->Append("[null]"); + return {true}; + } + s->Append(absl::StrFormat("[Extent3D width:%u, height:%u, depthOrArrayLayers:%u]", + value->width, value->height, value->depthOrArrayLayers)); + return {true}; + } + // // Objects // @@ -29,6 +59,10 @@ namespace dawn_native { AbslFormatConvert(const DeviceBase* value, const absl::FormatConversionSpec& spec, absl::FormatSink* s) { + if (value == nullptr) { + s->Append("[null]"); + return {true}; + } s->Append("[Device"); const std::string& label = value->GetLabel(); if (!label.empty()) { @@ -42,6 +76,10 @@ namespace dawn_native { AbslFormatConvert(const ApiObjectBase* value, const absl::FormatConversionSpec& spec, absl::FormatSink* s) { + if (value == nullptr) { + s->Append("[null]"); + return {true}; + } s->Append("["); s->Append(ObjectTypeAsString(value->GetType())); const std::string& label = value->GetLabel(); @@ -56,6 +94,10 @@ namespace dawn_native { AbslFormatConvert(const TextureViewBase* value, const absl::FormatConversionSpec& spec, absl::FormatSink* s) { + if (value == nullptr) { + s->Append("[null]"); + return {true}; + } s->Append("["); s->Append(ObjectTypeAsString(value->GetType())); const std::string& label = value->GetLabel(); @@ -81,6 +123,10 @@ namespace dawn_native { AbslFormatConvert(const {{as_cppType(type.name)}}* value, const absl::FormatConversionSpec& spec, absl::FormatSink* s) { + if (value == nullptr) { + s->Append("[null]"); + return {true}; + } s->Append("[{{as_cppType(type.name)}}"); if (value->label != nullptr) { s->Append(absl::StrFormat(" \"%s\"", value->label)); diff --git a/generator/templates/dawn_native/webgpu_absl_format.h b/generator/templates/dawn_native/webgpu_absl_format.h index 4cf85c64a3..434a4634e9 100644 --- a/generator/templates/dawn_native/webgpu_absl_format.h +++ b/generator/templates/dawn_native/webgpu_absl_format.h @@ -21,6 +21,22 @@ namespace dawn_native { + // + // Structs (Manually written) + // + + struct Color; + absl::FormatConvertResult + AbslFormatConvert(const Color* value, + const absl::FormatConversionSpec& spec, + absl::FormatSink* s); + + struct Extent3D; + absl::FormatConvertResult + AbslFormatConvert(const Extent3D* value, + const absl::FormatConversionSpec& spec, + absl::FormatSink* s); + // // Objects // diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp index 98f9373a57..2a32c3e47e 100644 --- a/src/dawn_native/CommandEncoder.cpp +++ b/src/dawn_native/CommandEncoder.cpp @@ -486,14 +486,16 @@ namespace dawn_native { const ComputePassDescriptor* descriptor) { DeviceBase* device = GetDevice(); - bool success = - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { + bool success = mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { DAWN_TRY(ValidateComputePassDescriptor(device, descriptor)); allocator->Allocate(Command::BeginComputePass); return {}; - }); + }, + "encoding BeginComputePass(%s).", descriptor); if (success) { ComputePassEncoder* passEncoder = @@ -513,8 +515,9 @@ namespace dawn_native { uint32_t width = 0; uint32_t height = 0; Ref attachmentState; - bool success = - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { + bool success = mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { uint32_t sampleCount = 0; DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, &width, &height, @@ -576,7 +579,8 @@ namespace dawn_native { cmd->occlusionQuerySet = descriptor->occlusionQuerySet; return {}; - }); + }, + "encoding BeginRenderPass(%s).", descriptor); if (success) { RenderPassEncoder* passEncoder = new RenderPassEncoder( @@ -594,140 +598,152 @@ namespace dawn_native { BufferBase* destination, uint64_t destinationOffset, uint64_t size) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(source)); - DAWN_TRY(GetDevice()->ValidateObject(destination)); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(source)); + DAWN_TRY(GetDevice()->ValidateObject(destination)); - if (source == destination) { - return DAWN_VALIDATION_ERROR( - "Source and destination cannot be the same buffer."); + if (source == destination) { + return DAWN_VALIDATION_ERROR( + "Source and destination cannot be the same buffer."); + } + + DAWN_TRY(ValidateCopySizeFitsInBuffer(source, sourceOffset, size)); + DAWN_TRY(ValidateCopySizeFitsInBuffer(destination, destinationOffset, size)); + DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset)); + + DAWN_TRY(ValidateCanUseAs(source, wgpu::BufferUsage::CopySrc)); + DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst)); + + mTopLevelBuffers.insert(source); + mTopLevelBuffers.insert(destination); } - DAWN_TRY(ValidateCopySizeFitsInBuffer(source, sourceOffset, size)); - DAWN_TRY(ValidateCopySizeFitsInBuffer(destination, destinationOffset, size)); - DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset)); + CopyBufferToBufferCmd* copy = + allocator->Allocate(Command::CopyBufferToBuffer); + copy->source = source; + copy->sourceOffset = sourceOffset; + copy->destination = destination; + copy->destinationOffset = destinationOffset; + copy->size = size; - DAWN_TRY(ValidateCanUseAs(source, wgpu::BufferUsage::CopySrc)); - DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst)); - - mTopLevelBuffers.insert(source); - mTopLevelBuffers.insert(destination); - } - - CopyBufferToBufferCmd* copy = - allocator->Allocate(Command::CopyBufferToBuffer); - copy->source = source; - copy->sourceOffset = sourceOffset; - copy->destination = destination; - copy->destinationOffset = destinationOffset; - copy->size = size; - - return {}; - }); + return {}; + }, + "encoding CopyBufferToBuffer(%s, %u, %s, %u, %u).", source, sourceOffset, destination, + destinationOffset, size); } void CommandEncoder::APICopyBufferToTexture(const ImageCopyBuffer* source, const ImageCopyTexture* destination, const Extent3D* copySize) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *source)); - DAWN_TRY(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc)); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *source)); + DAWN_TRY(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc)); - DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize)); - DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst)); - DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture)); + DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize)); + DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst)); + DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture)); - DAWN_TRY(ValidateLinearToDepthStencilCopyRestrictions(*destination)); - // We validate texture copy range before validating linear texture data, - // because in the latter we divide copyExtent.width by blockWidth and - // copyExtent.height by blockHeight while the divisibility conditions are - // checked in validating texture copy range. - DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize)); - } - const TexelBlockInfo& blockInfo = - destination->texture->GetFormat().GetAspectInfo(destination->aspect).block; - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(ValidateLinearTextureCopyOffset( - source->layout, blockInfo, - destination->texture->GetFormat().HasDepthOrStencil())); - DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(), - blockInfo, *copySize)); + DAWN_TRY(ValidateLinearToDepthStencilCopyRestrictions(*destination)); + // We validate texture copy range before validating linear texture data, + // because in the latter we divide copyExtent.width by blockWidth and + // copyExtent.height by blockHeight while the divisibility conditions are + // checked in validating texture copy range. + DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize)); + } + const TexelBlockInfo& blockInfo = + destination->texture->GetFormat().GetAspectInfo(destination->aspect).block; + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(ValidateLinearTextureCopyOffset( + source->layout, blockInfo, + destination->texture->GetFormat().HasDepthOrStencil())); + DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(), + blockInfo, *copySize)); - mTopLevelBuffers.insert(source->buffer); - mTopLevelTextures.insert(destination->texture); - } + mTopLevelBuffers.insert(source->buffer); + mTopLevelTextures.insert(destination->texture); + } - TextureDataLayout srcLayout = source->layout; - ApplyDefaultTextureDataLayoutOptions(&srcLayout, blockInfo, *copySize); + TextureDataLayout srcLayout = source->layout; + ApplyDefaultTextureDataLayoutOptions(&srcLayout, blockInfo, *copySize); - CopyBufferToTextureCmd* copy = - allocator->Allocate(Command::CopyBufferToTexture); - copy->source.buffer = source->buffer; - copy->source.offset = srcLayout.offset; - copy->source.bytesPerRow = srcLayout.bytesPerRow; - copy->source.rowsPerImage = srcLayout.rowsPerImage; - copy->destination.texture = destination->texture; - copy->destination.origin = destination->origin; - copy->destination.mipLevel = destination->mipLevel; - copy->destination.aspect = - ConvertAspect(destination->texture->GetFormat(), destination->aspect); - copy->copySize = *copySize; + CopyBufferToTextureCmd* copy = + allocator->Allocate(Command::CopyBufferToTexture); + copy->source.buffer = source->buffer; + copy->source.offset = srcLayout.offset; + copy->source.bytesPerRow = srcLayout.bytesPerRow; + copy->source.rowsPerImage = srcLayout.rowsPerImage; + copy->destination.texture = destination->texture; + copy->destination.origin = destination->origin; + copy->destination.mipLevel = destination->mipLevel; + copy->destination.aspect = + ConvertAspect(destination->texture->GetFormat(), destination->aspect); + copy->copySize = *copySize; - return {}; - }); + return {}; + }, + "encoding CopyBufferToTexture(%s, %s, %s).", source->buffer, destination->texture, + copySize); } void CommandEncoder::APICopyTextureToBuffer(const ImageCopyTexture* source, const ImageCopyBuffer* destination, const Extent3D* copySize) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize)); - DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); - DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture)); - DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source)); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize)); + DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); + DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture)); + DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source)); - DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *destination)); - DAWN_TRY(ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst)); + DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *destination)); + DAWN_TRY(ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst)); - // We validate texture copy range before validating linear texture data, - // because in the latter we divide copyExtent.width by blockWidth and - // copyExtent.height by blockHeight while the divisibility conditions are - // checked in validating texture copy range. - DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize)); - } - const TexelBlockInfo& blockInfo = - source->texture->GetFormat().GetAspectInfo(source->aspect).block; - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(ValidateLinearTextureCopyOffset( - destination->layout, blockInfo, - source->texture->GetFormat().HasDepthOrStencil())); - DAWN_TRY(ValidateLinearTextureData( - destination->layout, destination->buffer->GetSize(), blockInfo, *copySize)); + // We validate texture copy range before validating linear texture data, + // because in the latter we divide copyExtent.width by blockWidth and + // copyExtent.height by blockHeight while the divisibility conditions are + // checked in validating texture copy range. + DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize)); + } + const TexelBlockInfo& blockInfo = + source->texture->GetFormat().GetAspectInfo(source->aspect).block; + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(ValidateLinearTextureCopyOffset( + destination->layout, blockInfo, + source->texture->GetFormat().HasDepthOrStencil())); + DAWN_TRY(ValidateLinearTextureData( + destination->layout, destination->buffer->GetSize(), blockInfo, *copySize)); - mTopLevelTextures.insert(source->texture); - mTopLevelBuffers.insert(destination->buffer); - } + mTopLevelTextures.insert(source->texture); + mTopLevelBuffers.insert(destination->buffer); + } - TextureDataLayout dstLayout = destination->layout; - ApplyDefaultTextureDataLayoutOptions(&dstLayout, blockInfo, *copySize); + TextureDataLayout dstLayout = destination->layout; + ApplyDefaultTextureDataLayoutOptions(&dstLayout, blockInfo, *copySize); - CopyTextureToBufferCmd* copy = - allocator->Allocate(Command::CopyTextureToBuffer); - copy->source.texture = source->texture; - copy->source.origin = source->origin; - copy->source.mipLevel = source->mipLevel; - copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect); - copy->destination.buffer = destination->buffer; - copy->destination.offset = dstLayout.offset; - copy->destination.bytesPerRow = dstLayout.bytesPerRow; - copy->destination.rowsPerImage = dstLayout.rowsPerImage; - copy->copySize = *copySize; + CopyTextureToBufferCmd* copy = + allocator->Allocate(Command::CopyTextureToBuffer); + copy->source.texture = source->texture; + copy->source.origin = source->origin; + copy->source.mipLevel = source->mipLevel; + copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect); + copy->destination.buffer = destination->buffer; + copy->destination.offset = dstLayout.offset; + copy->destination.bytesPerRow = dstLayout.bytesPerRow; + copy->destination.rowsPerImage = dstLayout.rowsPerImage; + copy->copySize = *copySize; - return {}; - }); + return {}; + }, + "encoding CopyTextureToBuffer(%s, %s, %s).", source->texture, destination->buffer, + copySize); } void CommandEncoder::APICopyTextureToTexture(const ImageCopyTexture* source, @@ -746,51 +762,56 @@ namespace dawn_native { void CommandEncoder::APICopyTextureToTextureHelper(const ImageCopyTexture* source, const ImageCopyTexture* destination, const Extent3D* copySize) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(source->texture)); - DAWN_TRY(GetDevice()->ValidateObject(destination->texture)); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(source->texture)); + DAWN_TRY(GetDevice()->ValidateObject(destination->texture)); - DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize)); - DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize)); + DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize)); + DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize)); - DAWN_TRY( - ValidateTextureToTextureCopyRestrictions(*source, *destination, *copySize)); - - DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize)); - DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize)); - - // For internal usages (CopyToCopyInternal) we don't care if the user has added - // CopySrc as a usage for this texture, but we will always add it internally. - if (Internal) { DAWN_TRY( - ValidateInternalCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); - DAWN_TRY(ValidateInternalCanUseAs(destination->texture, - wgpu::TextureUsage::CopyDst)); - } else { - DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); - DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst)); + ValidateTextureToTextureCopyRestrictions(*source, *destination, *copySize)); + + DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize)); + DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize)); + + // For internal usages (CopyToCopyInternal) we don't care if the user has added + // CopySrc as a usage for this texture, but we will always add it internally. + if (Internal) { + DAWN_TRY( + ValidateInternalCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); + DAWN_TRY(ValidateInternalCanUseAs(destination->texture, + wgpu::TextureUsage::CopyDst)); + } else { + DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); + DAWN_TRY( + ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst)); + } + + mTopLevelTextures.insert(source->texture); + mTopLevelTextures.insert(destination->texture); } - mTopLevelTextures.insert(source->texture); - mTopLevelTextures.insert(destination->texture); - } + CopyTextureToTextureCmd* copy = + allocator->Allocate(Command::CopyTextureToTexture); + copy->source.texture = source->texture; + copy->source.origin = source->origin; + copy->source.mipLevel = source->mipLevel; + copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect); + copy->destination.texture = destination->texture; + copy->destination.origin = destination->origin; + copy->destination.mipLevel = destination->mipLevel; + copy->destination.aspect = + ConvertAspect(destination->texture->GetFormat(), destination->aspect); + copy->copySize = *copySize; - CopyTextureToTextureCmd* copy = - allocator->Allocate(Command::CopyTextureToTexture); - copy->source.texture = source->texture; - copy->source.origin = source->origin; - copy->source.mipLevel = source->mipLevel; - copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect); - copy->destination.texture = destination->texture; - copy->destination.origin = destination->origin; - copy->destination.mipLevel = destination->mipLevel; - copy->destination.aspect = - ConvertAspect(destination->texture->GetFormat(), destination->aspect); - copy->copySize = *copySize; - - return {}; - }); + return {}; + }, + "encoding CopyTextureToTexture(%s, %s, %s).", source->texture, destination->texture, + copySize); } void CommandEncoder::APIInjectValidationError(const char* message) { @@ -800,45 +821,55 @@ namespace dawn_native { } void CommandEncoder::APIInsertDebugMarker(const char* groupLabel) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - InsertDebugMarkerCmd* cmd = - allocator->Allocate(Command::InsertDebugMarker); - cmd->length = strlen(groupLabel); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + InsertDebugMarkerCmd* cmd = + allocator->Allocate(Command::InsertDebugMarker); + cmd->length = strlen(groupLabel); - char* label = allocator->AllocateData(cmd->length + 1); - memcpy(label, groupLabel, cmd->length + 1); + char* label = allocator->AllocateData(cmd->length + 1); + memcpy(label, groupLabel, cmd->length + 1); - return {}; - }); + return {}; + }, + "encoding InsertDebugMarker(\"%s\").", groupLabel); } void CommandEncoder::APIPopDebugGroup() { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - if (mDebugGroupStackSize == 0) { - return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push."); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + if (mDebugGroupStackSize == 0) { + return DAWN_VALIDATION_ERROR( + "Pop must be balanced by a corresponding Push."); + } } - } - allocator->Allocate(Command::PopDebugGroup); - mDebugGroupStackSize--; + allocator->Allocate(Command::PopDebugGroup); + mDebugGroupStackSize--; - return {}; - }); + return {}; + }, + "encoding PopDebugGroup()."); } void CommandEncoder::APIPushDebugGroup(const char* groupLabel) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - PushDebugGroupCmd* cmd = - allocator->Allocate(Command::PushDebugGroup); - cmd->length = strlen(groupLabel); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + PushDebugGroupCmd* cmd = + allocator->Allocate(Command::PushDebugGroup); + cmd->length = strlen(groupLabel); - char* label = allocator->AllocateData(cmd->length + 1); - memcpy(label, groupLabel, cmd->length + 1); + char* label = allocator->AllocateData(cmd->length + 1); + memcpy(label, groupLabel, cmd->length + 1); - mDebugGroupStackSize++; + mDebugGroupStackSize++; - return {}; - }); + return {}; + }, + "encoding PushDebugGroup(\"%s\").", groupLabel); } void CommandEncoder::APIResolveQuerySet(QuerySetBase* querySet, @@ -846,77 +877,87 @@ namespace dawn_native { uint32_t queryCount, BufferBase* destination, uint64_t destinationOffset) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(querySet)); - DAWN_TRY(GetDevice()->ValidateObject(destination)); + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(querySet)); + DAWN_TRY(GetDevice()->ValidateObject(destination)); - DAWN_TRY(ValidateQuerySetResolve(querySet, firstQuery, queryCount, destination, - destinationOffset)); + DAWN_TRY(ValidateQuerySetResolve(querySet, firstQuery, queryCount, destination, + destinationOffset)); - DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::QueryResolve)); + DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::QueryResolve)); - TrackUsedQuerySet(querySet); - mTopLevelBuffers.insert(destination); - } + TrackUsedQuerySet(querySet); + mTopLevelBuffers.insert(destination); + } - ResolveQuerySetCmd* cmd = - allocator->Allocate(Command::ResolveQuerySet); - cmd->querySet = querySet; - cmd->firstQuery = firstQuery; - cmd->queryCount = queryCount; - cmd->destination = destination; - cmd->destinationOffset = destinationOffset; + ResolveQuerySetCmd* cmd = + allocator->Allocate(Command::ResolveQuerySet); + cmd->querySet = querySet; + cmd->firstQuery = firstQuery; + cmd->queryCount = queryCount; + cmd->destination = destination; + cmd->destinationOffset = destinationOffset; - // Encode internal compute pipeline for timestamp query - if (querySet->GetQueryType() == wgpu::QueryType::Timestamp) { - DAWN_TRY(EncodeTimestampsToNanosecondsConversion( - this, querySet, firstQuery, queryCount, destination, destinationOffset)); - } + // Encode internal compute pipeline for timestamp query + if (querySet->GetQueryType() == wgpu::QueryType::Timestamp) { + DAWN_TRY(EncodeTimestampsToNanosecondsConversion( + this, querySet, firstQuery, queryCount, destination, destinationOffset)); + } - return {}; - }); + return {}; + }, + "encoding ResolveQuerySet(%s, %u, %u, %s, %u).", querySet, firstQuery, queryCount, + destination, destinationOffset); } void CommandEncoder::APIWriteBuffer(BufferBase* buffer, uint64_t bufferOffset, const uint8_t* data, uint64_t size) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(ValidateWriteBuffer(GetDevice(), buffer, bufferOffset, size)); - } + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(ValidateWriteBuffer(GetDevice(), buffer, bufferOffset, size)); + } - WriteBufferCmd* cmd = allocator->Allocate(Command::WriteBuffer); - cmd->buffer = buffer; - cmd->offset = bufferOffset; - cmd->size = size; + WriteBufferCmd* cmd = allocator->Allocate(Command::WriteBuffer); + cmd->buffer = buffer; + cmd->offset = bufferOffset; + cmd->size = size; - uint8_t* inlinedData = allocator->AllocateData(size); - memcpy(inlinedData, data, size); + uint8_t* inlinedData = allocator->AllocateData(size); + memcpy(inlinedData, data, size); - mTopLevelBuffers.insert(buffer); + mTopLevelBuffers.insert(buffer); - return {}; - }); + return {}; + }, + "encoding WriteBuffer(%s, %u, ..., %u).", buffer, bufferOffset, size); } void CommandEncoder::APIWriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) { - mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (GetDevice()->IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(querySet)); - DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); - } + mEncodingContext.TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (GetDevice()->IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(querySet)); + DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); + } - TrackQueryAvailability(querySet, queryIndex); + TrackQueryAvailability(querySet, queryIndex); - WriteTimestampCmd* cmd = - allocator->Allocate(Command::WriteTimestamp); - cmd->querySet = querySet; - cmd->queryIndex = queryIndex; + WriteTimestampCmd* cmd = + allocator->Allocate(Command::WriteTimestamp); + cmd->querySet = querySet; + cmd->queryIndex = queryIndex; - return {}; - }); + return {}; + }, + "encoding WriteTimestamp(%s, %u).", querySet, queryIndex); } CommandBufferBase* CommandEncoder::APIFinish(const CommandBufferDescriptor* descriptor) { diff --git a/src/dawn_native/ComputePassEncoder.cpp b/src/dawn_native/ComputePassEncoder.cpp index 48c040849c..517429a30f 100644 --- a/src/dawn_native/ComputePassEncoder.cpp +++ b/src/dawn_native/ComputePassEncoder.cpp @@ -63,137 +63,157 @@ namespace dawn_native { } void ComputePassEncoder::APIEndPass() { - if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(ValidateProgrammableEncoderEnd()); - } + if (mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(ValidateProgrammableEncoderEnd()); + } - allocator->Allocate(Command::EndComputePass); + allocator->Allocate(Command::EndComputePass); - return {}; - })) { + return {}; + }, + "encoding EndPass()")) { mEncodingContext->ExitComputePass(this, mUsageTracker.AcquireResourceUsage()); } } void ComputePassEncoder::APIDispatch(uint32_t x, uint32_t y, uint32_t z) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(mCommandBufferState.ValidateCanDispatch()); - DAWN_TRY(ValidatePerDimensionDispatchSizeLimit(x)); - DAWN_TRY(ValidatePerDimensionDispatchSizeLimit(y)); - DAWN_TRY(ValidatePerDimensionDispatchSizeLimit(z)); - } + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(mCommandBufferState.ValidateCanDispatch()); + DAWN_TRY(ValidatePerDimensionDispatchSizeLimit(x)); + DAWN_TRY(ValidatePerDimensionDispatchSizeLimit(y)); + DAWN_TRY(ValidatePerDimensionDispatchSizeLimit(z)); + } - // Record the synchronization scope for Dispatch, which is just the current bindgroups. - AddDispatchSyncScope(); + // Record the synchronization scope for Dispatch, which is just the current + // bindgroups. + AddDispatchSyncScope(); - DispatchCmd* dispatch = allocator->Allocate(Command::Dispatch); - dispatch->x = x; - dispatch->y = y; - dispatch->z = z; + DispatchCmd* dispatch = allocator->Allocate(Command::Dispatch); + dispatch->x = x; + dispatch->y = y; + dispatch->z = z; - return {}; - }); + return {}; + }, + "encoding Dispatch (x: %u, y: %u, z: %u)", x, y, z); } void ComputePassEncoder::APIDispatchIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); - DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); - DAWN_TRY(mCommandBufferState.ValidateCanDispatch()); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); + DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); + DAWN_TRY(mCommandBufferState.ValidateCanDispatch()); - // Indexed dispatches need a compute-shader based validation to check that the - // dispatch sizes aren't too big. Disallow them as unsafe until the validation is - // implemented. - if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) { - return DAWN_VALIDATION_ERROR( - "DispatchIndirect is disallowed because it doesn't validate that the " - "dispatch " - "size is valid yet."); + // Indexed dispatches need a compute-shader based validation to check that the + // dispatch sizes aren't too big. Disallow them as unsafe until the validation + // is implemented. + if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) { + return DAWN_VALIDATION_ERROR( + "DispatchIndirect is disallowed because it doesn't validate that the " + "dispatch " + "size is valid yet."); + } + + if (indirectOffset % 4 != 0) { + return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4"); + } + + if (indirectOffset >= indirectBuffer->GetSize() || + indirectOffset + kDispatchIndirectSize > indirectBuffer->GetSize()) { + return DAWN_VALIDATION_ERROR("Indirect offset out of bounds"); + } } - if (indirectOffset % 4 != 0) { - return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4"); - } + // Record the synchronization scope for Dispatch, both the bindgroups and the + // indirect buffer. + SyncScopeUsageTracker scope; + scope.BufferUsedAs(indirectBuffer, wgpu::BufferUsage::Indirect); + mUsageTracker.AddReferencedBuffer(indirectBuffer); + AddDispatchSyncScope(std::move(scope)); - if (indirectOffset >= indirectBuffer->GetSize() || - indirectOffset + kDispatchIndirectSize > indirectBuffer->GetSize()) { - return DAWN_VALIDATION_ERROR("Indirect offset out of bounds"); - } - } + DispatchIndirectCmd* dispatch = + allocator->Allocate(Command::DispatchIndirect); + dispatch->indirectBuffer = indirectBuffer; + dispatch->indirectOffset = indirectOffset; - // Record the synchronization scope for Dispatch, both the bindgroups and the indirect - // buffer. - SyncScopeUsageTracker scope; - scope.BufferUsedAs(indirectBuffer, wgpu::BufferUsage::Indirect); - mUsageTracker.AddReferencedBuffer(indirectBuffer); - AddDispatchSyncScope(std::move(scope)); - - DispatchIndirectCmd* dispatch = - allocator->Allocate(Command::DispatchIndirect); - dispatch->indirectBuffer = indirectBuffer; - dispatch->indirectOffset = indirectOffset; - - return {}; - }); + return {}; + }, + "encoding DispatchIndirect with %s", indirectBuffer); } void ComputePassEncoder::APISetPipeline(ComputePipelineBase* pipeline) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(pipeline)); - } + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(pipeline)); + } - mCommandBufferState.SetComputePipeline(pipeline); + mCommandBufferState.SetComputePipeline(pipeline); - SetComputePipelineCmd* cmd = - allocator->Allocate(Command::SetComputePipeline); - cmd->pipeline = pipeline; + SetComputePipelineCmd* cmd = + allocator->Allocate(Command::SetComputePipeline); + cmd->pipeline = pipeline; - return {}; - }); + return {}; + }, + "encoding SetPipeline with %s", pipeline); } void ComputePassEncoder::APISetBindGroup(uint32_t groupIndexIn, BindGroupBase* group, uint32_t dynamicOffsetCount, const uint32_t* dynamicOffsets) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - BindGroupIndex groupIndex(groupIndexIn); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + BindGroupIndex groupIndex(groupIndexIn); - if (IsValidationEnabled()) { - DAWN_TRY( - ValidateSetBindGroup(groupIndex, group, dynamicOffsetCount, dynamicOffsets)); - } + if (IsValidationEnabled()) { + DAWN_TRY(ValidateSetBindGroup(groupIndex, group, dynamicOffsetCount, + dynamicOffsets)); + } - mUsageTracker.AddResourcesReferencedByBindGroup(group); + mUsageTracker.AddResourcesReferencedByBindGroup(group); - RecordSetBindGroup(allocator, groupIndex, group, dynamicOffsetCount, dynamicOffsets); - mCommandBufferState.SetBindGroup(groupIndex, group); + RecordSetBindGroup(allocator, groupIndex, group, dynamicOffsetCount, + dynamicOffsets); + mCommandBufferState.SetBindGroup(groupIndex, group); - return {}; - }); + return {}; + }, + "encoding SetBindGroup with %s at index %u", group, groupIndexIn); } void ComputePassEncoder::APIWriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(querySet)); - DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); - } + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(querySet)); + DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); + } - mCommandEncoder->TrackQueryAvailability(querySet, queryIndex); + mCommandEncoder->TrackQueryAvailability(querySet, queryIndex); - WriteTimestampCmd* cmd = - allocator->Allocate(Command::WriteTimestamp); - cmd->querySet = querySet; - cmd->queryIndex = queryIndex; + WriteTimestampCmd* cmd = + allocator->Allocate(Command::WriteTimestamp); + cmd->querySet = querySet; + cmd->queryIndex = queryIndex; - return {}; - }); + return {}; + }, + "encoding WriteTimestamp to %s.", querySet); } void ComputePassEncoder::AddDispatchSyncScope(SyncScopeUsageTracker scope) { diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp index 07a24f5c8a..bd84b5e78e 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -484,6 +484,7 @@ namespace dawn_native { "%s is associated with %s, and cannot be used with %s.", object, object->GetDevice(), this); + // TODO(dawn:563): Preserve labels for error objects. DAWN_INVALID_IF(object->IsError(), "%s is an error.", object); return {}; @@ -852,7 +853,8 @@ namespace dawn_native { BindGroupBase* DeviceBase::APICreateBindGroup(const BindGroupDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateBindGroup(descriptor), &result)) { + if (ConsumedError(CreateBindGroup(descriptor), &result, "calling CreateBindGroup(%s).", + descriptor)) { return BindGroupBase::MakeError(this); } return result.Detach(); @@ -860,14 +862,16 @@ namespace dawn_native { BindGroupLayoutBase* DeviceBase::APICreateBindGroupLayout( const BindGroupLayoutDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateBindGroupLayout(descriptor), &result)) { + if (ConsumedError(CreateBindGroupLayout(descriptor), &result, + "calling CreateBindGroupLayout(%s).", descriptor)) { return BindGroupLayoutBase::MakeError(this); } return result.Detach(); } BufferBase* DeviceBase::APICreateBuffer(const BufferDescriptor* descriptor) { Ref result = nullptr; - if (ConsumedError(CreateBuffer(descriptor), &result)) { + if (ConsumedError(CreateBuffer(descriptor), &result, "calling CreateBuffer(%s).", + descriptor)) { ASSERT(result == nullptr); return BufferBase::MakeError(this, descriptor); } @@ -880,7 +884,8 @@ namespace dawn_native { ComputePipelineBase* DeviceBase::APICreateComputePipeline( const ComputePipelineDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateComputePipeline(descriptor), &result)) { + if (ConsumedError(CreateComputePipeline(descriptor), &result, + "calling CreateComputePipeline(%s).", descriptor)) { return ComputePipelineBase::MakeError(this); } return result.Detach(); @@ -902,21 +907,24 @@ namespace dawn_native { PipelineLayoutBase* DeviceBase::APICreatePipelineLayout( const PipelineLayoutDescriptor* descriptor) { Ref result; - if (ConsumedError(CreatePipelineLayout(descriptor), &result)) { + if (ConsumedError(CreatePipelineLayout(descriptor), &result, + "calling CreatePipelineLayout(%s).", descriptor)) { return PipelineLayoutBase::MakeError(this); } return result.Detach(); } QuerySetBase* DeviceBase::APICreateQuerySet(const QuerySetDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateQuerySet(descriptor), &result)) { + if (ConsumedError(CreateQuerySet(descriptor), &result, "calling CreateQuerySet(%s).", + descriptor)) { return QuerySetBase::MakeError(this); } return result.Detach(); } SamplerBase* DeviceBase::APICreateSampler(const SamplerDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateSampler(descriptor), &result)) { + if (ConsumedError(CreateSampler(descriptor), &result, "calling CreateSampler(%s).", + descriptor)) { return SamplerBase::MakeError(this); } return result.Detach(); @@ -924,6 +932,7 @@ namespace dawn_native { void DeviceBase::APICreateRenderPipelineAsync(const RenderPipelineDescriptor* descriptor, WGPUCreateRenderPipelineAsyncCallback callback, void* userdata) { + // TODO(dawn:563): Add validation error context. MaybeError maybeResult = CreateRenderPipelineAsync(descriptor, callback, userdata); // Call the callback directly when a validation error has been found in the front-end @@ -938,7 +947,8 @@ namespace dawn_native { RenderBundleEncoder* DeviceBase::APICreateRenderBundleEncoder( const RenderBundleEncoderDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateRenderBundleEncoder(descriptor), &result)) { + if (ConsumedError(CreateRenderBundleEncoder(descriptor), &result, + "calling CreateRenderBundleEncoder(%s).", descriptor)) { return RenderBundleEncoder::MakeError(this); } return result.Detach(); @@ -946,7 +956,8 @@ namespace dawn_native { RenderPipelineBase* DeviceBase::APICreateRenderPipeline( const RenderPipelineDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateRenderPipeline(descriptor), &result)) { + if (ConsumedError(CreateRenderPipeline(descriptor), &result, + "calling CreateRenderPipeline(%s).", descriptor)) { return RenderPipelineBase::MakeError(this); } return result.Detach(); @@ -955,7 +966,8 @@ namespace dawn_native { Ref result; std::unique_ptr compilationMessages( std::make_unique()); - if (ConsumedError(CreateShaderModule(descriptor, compilationMessages.get()), &result)) { + if (ConsumedError(CreateShaderModule(descriptor, compilationMessages.get()), &result, + "calling CreateShaderModule(%s).", descriptor)) { DAWN_ASSERT(result == nullptr); result = ShaderModuleBase::MakeError(this); } @@ -968,14 +980,16 @@ namespace dawn_native { SwapChainBase* DeviceBase::APICreateSwapChain(Surface* surface, const SwapChainDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateSwapChain(surface, descriptor), &result)) { + if (ConsumedError(CreateSwapChain(surface, descriptor), &result, + "calling CreateSwapChain(%s).", descriptor)) { return SwapChainBase::MakeError(this); } return result.Detach(); } TextureBase* DeviceBase::APICreateTexture(const TextureDescriptor* descriptor) { Ref result; - if (ConsumedError(CreateTexture(descriptor), &result)) { + if (ConsumedError(CreateTexture(descriptor), &result, "calling CreateTexture(%s).", + descriptor)) { return TextureBase::MakeError(this); } return result.Detach(); @@ -1042,7 +1056,8 @@ namespace dawn_native { ExternalTextureBase* DeviceBase::APICreateExternalTexture( const ExternalTextureDescriptor* descriptor) { Ref result = nullptr; - if (ConsumedError(CreateExternalTexture(descriptor), &result)) { + if (ConsumedError(CreateExternalTexture(descriptor), &result, + "calling CreateExternalTexture(%s).", descriptor)) { return ExternalTextureBase::MakeError(this); } diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h index 1f5d0d4e9f..79c0c80a5b 100644 --- a/src/dawn_native/Device.h +++ b/src/dawn_native/Device.h @@ -78,6 +78,27 @@ namespace dawn_native { return false; } + template + bool ConsumedError(ResultOrError resultOrError, + T* result, + const char* formatStr, + const Args&... args) { + if (DAWN_UNLIKELY(resultOrError.IsError())) { + std::unique_ptr error = resultOrError.AcquireError(); + if (error->GetType() == InternalErrorType::Validation) { + std::string out; + absl::UntypedFormatSpec format(formatStr); + if (absl::FormatUntyped(&out, format, {absl::FormatArg(args)...})) { + error->AppendContext(std::move(out)); + } + } + ConsumeError(std::move(error)); + return true; + } + *result = resultOrError.AcquireSuccess(); + return false; + } + MaybeError ValidateObject(const ApiObjectBase* object) const; AdapterBase* GetAdapter() const; diff --git a/src/dawn_native/EncodingContext.h b/src/dawn_native/EncodingContext.h index 522d29ed63..87dfecb4ff 100644 --- a/src/dawn_native/EncodingContext.h +++ b/src/dawn_native/EncodingContext.h @@ -51,6 +51,25 @@ namespace dawn_native { return false; } + template + inline bool ConsumedError(MaybeError maybeError, + const char* formatStr, + const Args&... args) { + if (DAWN_UNLIKELY(maybeError.IsError())) { + std::unique_ptr error = maybeError.AcquireError(); + if (error->GetType() == InternalErrorType::Validation) { + std::string out; + absl::UntypedFormatSpec format(formatStr); + if (absl::FormatUntyped(&out, format, {absl::FormatArg(args)...})) { + error->AppendContext(std::move(out)); + } + } + HandleError(std::move(error)); + return true; + } + return false; + } + inline bool CheckCurrentEncoder(const ObjectBase* encoder) { if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) { if (mCurrentEncoder != mTopLevelEncoder) { @@ -74,6 +93,18 @@ namespace dawn_native { return !ConsumedError(encodeFunction(&mPendingCommands)); } + template + inline bool TryEncode(const ObjectBase* encoder, + EncodeFunction&& encodeFunction, + const char* formatStr, + const Args&... args) { + if (!CheckCurrentEncoder(encoder)) { + return false; + } + ASSERT(!mWasMovedToIterator); + return !ConsumedError(encodeFunction(&mPendingCommands), formatStr, args...); + } + // Must be called prior to encoding a BeginRenderPassCmd. Note that it's OK to call this // and then not actually call EnterPass+ExitRenderPass, for example if some other pass setup // failed validation before the BeginRenderPassCmd could be encoded. diff --git a/src/dawn_native/ProgrammablePassEncoder.cpp b/src/dawn_native/ProgrammablePassEncoder.cpp index 0c3234e4d9..de2803375a 100644 --- a/src/dawn_native/ProgrammablePassEncoder.cpp +++ b/src/dawn_native/ProgrammablePassEncoder.cpp @@ -55,45 +55,55 @@ namespace dawn_native { } void ProgrammablePassEncoder::APIInsertDebugMarker(const char* groupLabel) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - InsertDebugMarkerCmd* cmd = - allocator->Allocate(Command::InsertDebugMarker); - cmd->length = strlen(groupLabel); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + InsertDebugMarkerCmd* cmd = + allocator->Allocate(Command::InsertDebugMarker); + cmd->length = strlen(groupLabel); - char* label = allocator->AllocateData(cmd->length + 1); - memcpy(label, groupLabel, cmd->length + 1); + char* label = allocator->AllocateData(cmd->length + 1); + memcpy(label, groupLabel, cmd->length + 1); - return {}; - }); + return {}; + }, + "encoding InsertDebugMarker(\"%s\")", groupLabel); } void ProgrammablePassEncoder::APIPopDebugGroup() { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - if (mDebugGroupStackSize == 0) { - return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push."); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + if (mDebugGroupStackSize == 0) { + return DAWN_VALIDATION_ERROR( + "Pop must be balanced by a corresponding Push."); + } } - } - allocator->Allocate(Command::PopDebugGroup); - mDebugGroupStackSize--; + allocator->Allocate(Command::PopDebugGroup); + mDebugGroupStackSize--; - return {}; - }); + return {}; + }, + "encoding PopDebugGroup()"); } void ProgrammablePassEncoder::APIPushDebugGroup(const char* groupLabel) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - PushDebugGroupCmd* cmd = - allocator->Allocate(Command::PushDebugGroup); - cmd->length = strlen(groupLabel); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + PushDebugGroupCmd* cmd = + allocator->Allocate(Command::PushDebugGroup); + cmd->length = strlen(groupLabel); - char* label = allocator->AllocateData(cmd->length + 1); - memcpy(label, groupLabel, cmd->length + 1); + char* label = allocator->AllocateData(cmd->length + 1); + memcpy(label, groupLabel, cmd->length + 1); - mDebugGroupStackSize++; + mDebugGroupStackSize++; - return {}; - }); + return {}; + }, + "encoding PushDebugGroup(\"%s\")", groupLabel); } MaybeError ProgrammablePassEncoder::ValidateSetBindGroup( diff --git a/src/dawn_native/RenderEncoderBase.cpp b/src/dawn_native/RenderEncoderBase.cpp index 0b4b8b5f93..4f44f2290a 100644 --- a/src/dawn_native/RenderEncoderBase.cpp +++ b/src/dawn_native/RenderEncoderBase.cpp @@ -61,27 +61,31 @@ namespace dawn_native { uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(mCommandBufferState.ValidateCanDraw()); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(mCommandBufferState.ValidateCanDraw()); - DAWN_INVALID_IF(mDisableBaseInstance && firstInstance != 0, - "First instance (%u) must be zero.", firstInstance); + DAWN_INVALID_IF(mDisableBaseInstance && firstInstance != 0, + "First instance (%u) must be zero.", firstInstance); - DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForVertexBuffer(vertexCount, - firstVertex)); - DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForInstanceBuffer(instanceCount, - firstInstance)); - } + DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForVertexBuffer(vertexCount, + firstVertex)); + DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForInstanceBuffer( + instanceCount, firstInstance)); + } - DrawCmd* draw = allocator->Allocate(Command::Draw); - draw->vertexCount = vertexCount; - draw->instanceCount = instanceCount; - draw->firstVertex = firstVertex; - draw->firstInstance = firstInstance; + DrawCmd* draw = allocator->Allocate(Command::Draw); + draw->vertexCount = vertexCount; + draw->instanceCount = instanceCount; + draw->firstVertex = firstVertex; + draw->firstInstance = firstInstance; - return {}; - }); + return {}; + }, + "encoding Draw(%u, %u, %u, %u).", vertexCount, instanceCount, firstVertex, + firstInstance); } void RenderEncoderBase::APIDrawIndexed(uint32_t indexCount, @@ -89,268 +93,297 @@ namespace dawn_native { uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(mCommandBufferState.ValidateCanDrawIndexed()); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(mCommandBufferState.ValidateCanDrawIndexed()); - DAWN_INVALID_IF(mDisableBaseInstance && firstInstance != 0, - "First instance (%u) must be zero.", firstInstance); + DAWN_INVALID_IF(mDisableBaseInstance && firstInstance != 0, + "First instance (%u) must be zero.", firstInstance); - DAWN_INVALID_IF(mDisableBaseVertex && baseVertex != 0, - "Base vertex (%u) must be zero.", baseVertex); + DAWN_INVALID_IF(mDisableBaseVertex && baseVertex != 0, + "Base vertex (%u) must be zero.", baseVertex); - DAWN_TRY(mCommandBufferState.ValidateIndexBufferInRange(indexCount, firstIndex)); + DAWN_TRY( + mCommandBufferState.ValidateIndexBufferInRange(indexCount, firstIndex)); - // Although we don't know actual vertex access range in CPU, we still call the - // ValidateBufferInRangeForVertexBuffer in order to deal with those vertex step mode - // vertex buffer with an array stride of zero. - DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForVertexBuffer(0, 0)); - DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForInstanceBuffer(instanceCount, - firstInstance)); - } + // Although we don't know actual vertex access range in CPU, we still call the + // ValidateBufferInRangeForVertexBuffer in order to deal with those vertex step + // mode vertex buffer with an array stride of zero. + DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForVertexBuffer(0, 0)); + DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForInstanceBuffer( + instanceCount, firstInstance)); + } - DrawIndexedCmd* draw = allocator->Allocate(Command::DrawIndexed); - draw->indexCount = indexCount; - draw->instanceCount = instanceCount; - draw->firstIndex = firstIndex; - draw->baseVertex = baseVertex; - draw->firstInstance = firstInstance; + DrawIndexedCmd* draw = allocator->Allocate(Command::DrawIndexed); + draw->indexCount = indexCount; + draw->instanceCount = instanceCount; + draw->firstIndex = firstIndex; + draw->baseVertex = baseVertex; + draw->firstInstance = firstInstance; - return {}; - }); + return {}; + }, + "encoding DrawIndexed(%u, %u, %u, %i, %u).", indexCount, instanceCount, firstIndex, + baseVertex, firstInstance); } void RenderEncoderBase::APIDrawIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); - DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); - DAWN_TRY(mCommandBufferState.ValidateCanDraw()); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); + DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); + DAWN_TRY(mCommandBufferState.ValidateCanDraw()); - DAWN_INVALID_IF(indirectOffset % 4 != 0, - "Indirect offset (%u) is not a multiple of 4.", indirectOffset); + DAWN_INVALID_IF(indirectOffset % 4 != 0, + "Indirect offset (%u) is not a multiple of 4.", indirectOffset); - DAWN_INVALID_IF( - indirectOffset >= indirectBuffer->GetSize() || - kDrawIndirectSize > indirectBuffer->GetSize() - indirectOffset, - "Indirect offset (%u) is out of bounds of indirect buffer %s size (%u).", - indirectOffset, indirectBuffer, indirectBuffer->GetSize()); - } + DAWN_INVALID_IF( + indirectOffset >= indirectBuffer->GetSize() || + kDrawIndirectSize > indirectBuffer->GetSize() - indirectOffset, + "Indirect offset (%u) is out of bounds of indirect buffer %s size (%u).", + indirectOffset, indirectBuffer, indirectBuffer->GetSize()); + } - DrawIndirectCmd* cmd = allocator->Allocate(Command::DrawIndirect); - cmd->indirectBuffer = indirectBuffer; - cmd->indirectOffset = indirectOffset; + DrawIndirectCmd* cmd = allocator->Allocate(Command::DrawIndirect); + cmd->indirectBuffer = indirectBuffer; + cmd->indirectOffset = indirectOffset; - mUsageTracker.BufferUsedAs(indirectBuffer, wgpu::BufferUsage::Indirect); + mUsageTracker.BufferUsedAs(indirectBuffer, wgpu::BufferUsage::Indirect); - return {}; - }); + return {}; + }, + "encoding DrawIndirect(%s, %u).", indirectBuffer, indirectOffset); } void RenderEncoderBase::APIDrawIndexedIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); - DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); - DAWN_TRY(mCommandBufferState.ValidateCanDrawIndexed()); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); + DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); + DAWN_TRY(mCommandBufferState.ValidateCanDrawIndexed()); - DAWN_INVALID_IF(indirectOffset % 4 != 0, - "Indirect offset (%u) is not a multiple of 4.", indirectOffset); + DAWN_INVALID_IF(indirectOffset % 4 != 0, + "Indirect offset (%u) is not a multiple of 4.", indirectOffset); - DAWN_INVALID_IF( - (indirectOffset >= indirectBuffer->GetSize() || - kDrawIndexedIndirectSize > indirectBuffer->GetSize() - indirectOffset), - "Indirect offset (%u) is out of bounds of indirect buffer %s size (%u).", - indirectOffset, indirectBuffer, indirectBuffer->GetSize()); - } + DAWN_INVALID_IF( + (indirectOffset >= indirectBuffer->GetSize() || + kDrawIndexedIndirectSize > indirectBuffer->GetSize() - indirectOffset), + "Indirect offset (%u) is out of bounds of indirect buffer %s size (%u).", + indirectOffset, indirectBuffer, indirectBuffer->GetSize()); + } - DrawIndexedIndirectCmd* cmd = - allocator->Allocate(Command::DrawIndexedIndirect); - if (IsValidationEnabled()) { - cmd->indirectBufferLocation = BufferLocation::New(); - mIndirectDrawMetadata.AddIndexedIndirectDraw( - mCommandBufferState.GetIndexFormat(), mCommandBufferState.GetIndexBufferSize(), - indirectBuffer, indirectOffset, cmd->indirectBufferLocation.Get()); - } else { - cmd->indirectBufferLocation = BufferLocation::New(indirectBuffer, indirectOffset); - } + DrawIndexedIndirectCmd* cmd = + allocator->Allocate(Command::DrawIndexedIndirect); + if (IsValidationEnabled()) { + cmd->indirectBufferLocation = BufferLocation::New(); + mIndirectDrawMetadata.AddIndexedIndirectDraw( + mCommandBufferState.GetIndexFormat(), + mCommandBufferState.GetIndexBufferSize(), indirectBuffer, indirectOffset, + cmd->indirectBufferLocation.Get()); + } else { + cmd->indirectBufferLocation = + BufferLocation::New(indirectBuffer, indirectOffset); + } - mUsageTracker.BufferUsedAs(indirectBuffer, wgpu::BufferUsage::Indirect); + mUsageTracker.BufferUsedAs(indirectBuffer, wgpu::BufferUsage::Indirect); - return {}; - }); + return {}; + }, + "encoding DrawIndexedIndirect(%s, %u).", indirectBuffer, indirectOffset); } void RenderEncoderBase::APISetPipeline(RenderPipelineBase* pipeline) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(pipeline)); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(pipeline)); - // TODO(dawn:563): More detail about why the states are incompatible would be nice. - DAWN_INVALID_IF( - pipeline->GetAttachmentState() != mAttachmentState.Get(), - "Attachment state of %s is not compatible with the attachment state of %s", - pipeline, this); - } + // TODO(dawn:563): More detail about why the states are incompatible would be + // nice. + DAWN_INVALID_IF( + pipeline->GetAttachmentState() != mAttachmentState.Get(), + "Attachment state of %s is not compatible with the attachment state of %s", + pipeline, this); + } - mCommandBufferState.SetRenderPipeline(pipeline); + mCommandBufferState.SetRenderPipeline(pipeline); - SetRenderPipelineCmd* cmd = - allocator->Allocate(Command::SetRenderPipeline); - cmd->pipeline = pipeline; + SetRenderPipelineCmd* cmd = + allocator->Allocate(Command::SetRenderPipeline); + cmd->pipeline = pipeline; - return {}; - }); + return {}; + }, + "encoding SetPipeline(%s).", pipeline); } void RenderEncoderBase::APISetIndexBuffer(BufferBase* buffer, wgpu::IndexFormat format, uint64_t offset, uint64_t size) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(buffer)); - DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Index)); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(buffer)); + DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Index)); - DAWN_INVALID_IF(format == wgpu::IndexFormat::Undefined, - "Index format must be specified"); + DAWN_INVALID_IF(format == wgpu::IndexFormat::Undefined, + "Index format must be specified"); - DAWN_INVALID_IF(offset % uint64_t(IndexFormatSize(format)) != 0, - "Index buffer offset (%u) is not a multiple of the size (%u)" - "of %s.", - offset, IndexFormatSize(format), format); + DAWN_INVALID_IF(offset % uint64_t(IndexFormatSize(format)) != 0, + "Index buffer offset (%u) is not a multiple of the size (%u)" + "of %s.", + offset, IndexFormatSize(format), format); - uint64_t bufferSize = buffer->GetSize(); - DAWN_INVALID_IF(offset > bufferSize, - "Index buffer offset (%u) is larger than the size (%u) of %s.", - offset, bufferSize, buffer); + uint64_t bufferSize = buffer->GetSize(); + DAWN_INVALID_IF(offset > bufferSize, + "Index buffer offset (%u) is larger than the size (%u) of %s.", + offset, bufferSize, buffer); - uint64_t remainingSize = bufferSize - offset; + uint64_t remainingSize = bufferSize - offset; - // Temporarily treat 0 as undefined for size, and give a warning - // TODO(dawn:1058): Remove this if block - if (size == 0) { - size = wgpu::kWholeSize; - GetDevice()->EmitDeprecationWarning( - "Using size=0 to indicate default binding size for setIndexBuffer " - "is deprecated. In the future it will result in a zero-size binding. " - "Use `undefined` (wgpu::kWholeSize) or just omit the parameter instead."); - } + // Temporarily treat 0 as undefined for size, and give a warning + // TODO(dawn:1058): Remove this if block + if (size == 0) { + size = wgpu::kWholeSize; + GetDevice()->EmitDeprecationWarning( + "Using size=0 to indicate default binding size for setIndexBuffer " + "is deprecated. In the future it will result in a zero-size binding. " + "Use `undefined` (wgpu::kWholeSize) or just omit the parameter " + "instead."); + } - if (size == wgpu::kWholeSize) { - size = remainingSize; + if (size == wgpu::kWholeSize) { + size = remainingSize; + } else { + DAWN_INVALID_IF(size > remainingSize, + "Index buffer range (offset: %u, size: %u) doesn't fit in " + "the size (%u) of " + "%s.", + offset, size, bufferSize, buffer); + } } else { - DAWN_INVALID_IF( - size > remainingSize, - "Index buffer range (offset: %u, size: %u) doesn't fit in the size (%u) of " - "%s.", - offset, size, bufferSize, buffer); + if (size == wgpu::kWholeSize) { + DAWN_ASSERT(buffer->GetSize() >= offset); + size = buffer->GetSize() - offset; + } } - } else { - if (size == wgpu::kWholeSize) { - DAWN_ASSERT(buffer->GetSize() >= offset); - size = buffer->GetSize() - offset; - } - } - mCommandBufferState.SetIndexBuffer(format, size); + mCommandBufferState.SetIndexBuffer(format, size); - SetIndexBufferCmd* cmd = - allocator->Allocate(Command::SetIndexBuffer); - cmd->buffer = buffer; - cmd->format = format; - cmd->offset = offset; - cmd->size = size; + SetIndexBufferCmd* cmd = + allocator->Allocate(Command::SetIndexBuffer); + cmd->buffer = buffer; + cmd->format = format; + cmd->offset = offset; + cmd->size = size; - mUsageTracker.BufferUsedAs(buffer, wgpu::BufferUsage::Index); + mUsageTracker.BufferUsedAs(buffer, wgpu::BufferUsage::Index); - return {}; - }); + return {}; + }, + "encoding SetIndexBuffer(%s, %s, %u, %u).", buffer, format, offset, size); } void RenderEncoderBase::APISetVertexBuffer(uint32_t slot, BufferBase* buffer, uint64_t offset, uint64_t size) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(buffer)); - DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Vertex)); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(buffer)); + DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Vertex)); - DAWN_INVALID_IF(slot >= kMaxVertexBuffers, - "Vertex buffer slot (%u) is larger the maximum (%u)", slot, - kMaxVertexBuffers - 1); + DAWN_INVALID_IF(slot >= kMaxVertexBuffers, + "Vertex buffer slot (%u) is larger the maximum (%u)", slot, + kMaxVertexBuffers - 1); - DAWN_INVALID_IF(offset % 4 != 0, "Vertex buffer offset (%u) is not a multiple of 4", - offset); + DAWN_INVALID_IF(offset % 4 != 0, + "Vertex buffer offset (%u) is not a multiple of 4", offset); - uint64_t bufferSize = buffer->GetSize(); - DAWN_INVALID_IF(offset > bufferSize, - "Vertex buffer offset (%u) is larger than the size (%u) of %s.", - offset, bufferSize, buffer); + uint64_t bufferSize = buffer->GetSize(); + DAWN_INVALID_IF(offset > bufferSize, + "Vertex buffer offset (%u) is larger than the size (%u) of %s.", + offset, bufferSize, buffer); - uint64_t remainingSize = bufferSize - offset; + uint64_t remainingSize = bufferSize - offset; - // Temporarily treat 0 as undefined for size, and give a warning - // TODO(dawn:1058): Remove this if block - if (size == 0) { - size = wgpu::kWholeSize; - GetDevice()->EmitDeprecationWarning( - "Using size=0 to indicate default binding size for setVertexBuffer " - "is deprecated. In the future it will result in a zero-size binding. " - "Use `undefined` (wgpu::kWholeSize) or just omit the parameter instead."); - } + // Temporarily treat 0 as undefined for size, and give a warning + // TODO(dawn:1058): Remove this if block + if (size == 0) { + size = wgpu::kWholeSize; + GetDevice()->EmitDeprecationWarning( + "Using size=0 to indicate default binding size for setVertexBuffer " + "is deprecated. In the future it will result in a zero-size binding. " + "Use `undefined` (wgpu::kWholeSize) or just omit the parameter " + "instead."); + } - if (size == wgpu::kWholeSize) { - size = remainingSize; + if (size == wgpu::kWholeSize) { + size = remainingSize; + } else { + DAWN_INVALID_IF(size > remainingSize, + "Vertex buffer range (offset: %u, size: %u) doesn't fit in " + "the size (%u) " + "of %s.", + offset, size, bufferSize, buffer); + } } else { - DAWN_INVALID_IF( - size > remainingSize, - "Vertex buffer range (offset: %u, size: %u) doesn't fit in the size (%u) " - "of %s.", - offset, size, bufferSize, buffer); + if (size == wgpu::kWholeSize) { + DAWN_ASSERT(buffer->GetSize() >= offset); + size = buffer->GetSize() - offset; + } } - } else { - if (size == wgpu::kWholeSize) { - DAWN_ASSERT(buffer->GetSize() >= offset); - size = buffer->GetSize() - offset; - } - } - mCommandBufferState.SetVertexBuffer(VertexBufferSlot(uint8_t(slot)), size); + mCommandBufferState.SetVertexBuffer(VertexBufferSlot(uint8_t(slot)), size); - SetVertexBufferCmd* cmd = - allocator->Allocate(Command::SetVertexBuffer); - cmd->slot = VertexBufferSlot(static_cast(slot)); - cmd->buffer = buffer; - cmd->offset = offset; - cmd->size = size; + SetVertexBufferCmd* cmd = + allocator->Allocate(Command::SetVertexBuffer); + cmd->slot = VertexBufferSlot(static_cast(slot)); + cmd->buffer = buffer; + cmd->offset = offset; + cmd->size = size; - mUsageTracker.BufferUsedAs(buffer, wgpu::BufferUsage::Vertex); + mUsageTracker.BufferUsedAs(buffer, wgpu::BufferUsage::Vertex); - return {}; - }); + return {}; + }, + "encoding SetVertexBuffer(%u, %s, %u, %u).", slot, buffer, offset, size); } void RenderEncoderBase::APISetBindGroup(uint32_t groupIndexIn, BindGroupBase* group, uint32_t dynamicOffsetCount, const uint32_t* dynamicOffsets) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - BindGroupIndex groupIndex(groupIndexIn); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + BindGroupIndex groupIndex(groupIndexIn); - if (IsValidationEnabled()) { - DAWN_TRY( - ValidateSetBindGroup(groupIndex, group, dynamicOffsetCount, dynamicOffsets)); - } + if (IsValidationEnabled()) { + DAWN_TRY(ValidateSetBindGroup(groupIndex, group, dynamicOffsetCount, + dynamicOffsets)); + } - RecordSetBindGroup(allocator, groupIndex, group, dynamicOffsetCount, dynamicOffsets); - mCommandBufferState.SetBindGroup(groupIndex, group); - mUsageTracker.AddBindGroup(group); + RecordSetBindGroup(allocator, groupIndex, group, dynamicOffsetCount, + dynamicOffsets); + mCommandBufferState.SetBindGroup(groupIndex, group); + mUsageTracker.AddBindGroup(group); - return {}; - }); + return {}; + }, + "encoding SetBindGroup(%u, %s, %u).", groupIndexIn, group, dynamicOffsetCount); } } // namespace dawn_native diff --git a/src/dawn_native/RenderPassEncoder.cpp b/src/dawn_native/RenderPassEncoder.cpp index b6c015a17f..aa86702e0b 100644 --- a/src/dawn_native/RenderPassEncoder.cpp +++ b/src/dawn_native/RenderPassEncoder.cpp @@ -93,43 +93,52 @@ namespace dawn_native { } void RenderPassEncoder::APIEndPass() { - if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(ValidateProgrammableEncoderEnd()); + if (mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(ValidateProgrammableEncoderEnd()); - DAWN_INVALID_IF( - mOcclusionQueryActive, - "Render pass %s ended with incomplete occlusion query index %u of %s.", - this, mCurrentOcclusionQueryIndex, mOcclusionQuerySet.Get()); - } + DAWN_INVALID_IF( + mOcclusionQueryActive, + "Render pass %s ended with incomplete occlusion query index %u of %s.", + this, mCurrentOcclusionQueryIndex, mOcclusionQuerySet.Get()); + } - allocator->Allocate(Command::EndRenderPass); - DAWN_TRY(mEncodingContext->ExitRenderPass(this, std::move(mUsageTracker), - mCommandEncoder.Get(), - std::move(mIndirectDrawMetadata))); - return {}; - })) { + allocator->Allocate(Command::EndRenderPass); + DAWN_TRY(mEncodingContext->ExitRenderPass(this, std::move(mUsageTracker), + mCommandEncoder.Get(), + std::move(mIndirectDrawMetadata))); + return {}; + }, + "encoding EndPass().")) { } } void RenderPassEncoder::APISetStencilReference(uint32_t reference) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - SetStencilReferenceCmd* cmd = - allocator->Allocate(Command::SetStencilReference); - cmd->reference = reference; + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + SetStencilReferenceCmd* cmd = + allocator->Allocate(Command::SetStencilReference); + cmd->reference = reference; - return {}; - }); + return {}; + }, + "encoding SetStencilReference(%u)", reference); } void RenderPassEncoder::APISetBlendConstant(const Color* color) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - SetBlendConstantCmd* cmd = - allocator->Allocate(Command::SetBlendConstant); - cmd->color = *color; + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + SetBlendConstantCmd* cmd = + allocator->Allocate(Command::SetBlendConstant); + cmd->color = *color; - return {}; - }); + return {}; + }, + "encoding SetBlendConstant(%s).", color); } void RenderPassEncoder::APISetViewport(float x, @@ -138,192 +147,214 @@ namespace dawn_native { float height, float minDepth, float maxDepth) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_INVALID_IF((isnan(x) || isnan(y) || isnan(width) || isnan(height) || - isnan(minDepth) || isnan(maxDepth)), - "A parameter of the viewport (x: %f, y: %f, width: %f, height: %f, " - "minDepth: %f, maxDepth: %f) is NaN.", - x, y, width, height, minDepth, maxDepth); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_INVALID_IF( + (isnan(x) || isnan(y) || isnan(width) || isnan(height) || isnan(minDepth) || + isnan(maxDepth)), + "A parameter of the viewport (x: %f, y: %f, width: %f, height: %f, " + "minDepth: %f, maxDepth: %f) is NaN.", + x, y, width, height, minDepth, maxDepth); - DAWN_INVALID_IF( - x < 0 || y < 0 || width < 0 || height < 0, - "Viewport bounds (x: %f, y: %f, width: %f, height: %f) contains a negative " - "value.", - x, y, width, height); + DAWN_INVALID_IF( + x < 0 || y < 0 || width < 0 || height < 0, + "Viewport bounds (x: %f, y: %f, width: %f, height: %f) contains a negative " + "value.", + x, y, width, height); - DAWN_INVALID_IF( - x + width > mRenderTargetWidth || y + height > mRenderTargetHeight, - "Viewport bounds (x: %f, y: %f, width: %f, height: %f) are not contained in " - "the render target dimensions (%u x %u).", - x, y, width, height, mRenderTargetWidth, mRenderTargetHeight); + DAWN_INVALID_IF( + x + width > mRenderTargetWidth || y + height > mRenderTargetHeight, + "Viewport bounds (x: %f, y: %f, width: %f, height: %f) are not contained " + "in " + "the render target dimensions (%u x %u).", + x, y, width, height, mRenderTargetWidth, mRenderTargetHeight); - // Check for depths being in [0, 1] and min <= max in 3 checks instead of 5. - DAWN_INVALID_IF( - minDepth < 0 || minDepth > maxDepth || maxDepth > 1, - "Viewport minDepth (%f) and maxDepth (%f) are not in [0, 1] or minDepth was " - "greater than maxDepth.", - minDepth, maxDepth); - } + // Check for depths being in [0, 1] and min <= max in 3 checks instead of 5. + DAWN_INVALID_IF(minDepth < 0 || minDepth > maxDepth || maxDepth > 1, + "Viewport minDepth (%f) and maxDepth (%f) are not in [0, 1] or " + "minDepth was " + "greater than maxDepth.", + minDepth, maxDepth); + } - SetViewportCmd* cmd = allocator->Allocate(Command::SetViewport); - cmd->x = x; - cmd->y = y; - cmd->width = width; - cmd->height = height; - cmd->minDepth = minDepth; - cmd->maxDepth = maxDepth; + SetViewportCmd* cmd = allocator->Allocate(Command::SetViewport); + cmd->x = x; + cmd->y = y; + cmd->width = width; + cmd->height = height; + cmd->minDepth = minDepth; + cmd->maxDepth = maxDepth; - return {}; - }); + return {}; + }, + "encoding SetViewport(%f, %f, %f, %f, %f, %f).", x, y, width, height, minDepth, + maxDepth); } void RenderPassEncoder::APISetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_INVALID_IF( - width > mRenderTargetWidth || height > mRenderTargetHeight || - x > mRenderTargetWidth - width || y > mRenderTargetHeight - height, - "Scissor rect (x: %u, y: %u, width: %u, height: %u) is not contained in " - "the render target dimensions (%u x %u).", - x, y, width, height, mRenderTargetWidth, mRenderTargetHeight); - } + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_INVALID_IF( + width > mRenderTargetWidth || height > mRenderTargetHeight || + x > mRenderTargetWidth - width || y > mRenderTargetHeight - height, + "Scissor rect (x: %u, y: %u, width: %u, height: %u) is not contained in " + "the render target dimensions (%u x %u).", + x, y, width, height, mRenderTargetWidth, mRenderTargetHeight); + } - SetScissorRectCmd* cmd = - allocator->Allocate(Command::SetScissorRect); - cmd->x = x; - cmd->y = y; - cmd->width = width; - cmd->height = height; + SetScissorRectCmd* cmd = + allocator->Allocate(Command::SetScissorRect); + cmd->x = x; + cmd->y = y; + cmd->width = width; + cmd->height = height; - return {}; - }); + return {}; + }, + "encoding SetScissorRect(%u, %u, %u, %u).", x, y, width, height); } void RenderPassEncoder::APIExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - for (uint32_t i = 0; i < count; ++i) { - DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i])); - - // TODO(dawn:563): Give more detail about why the states are incompatible. - DAWN_INVALID_IF( - GetAttachmentState() != renderBundles[i]->GetAttachmentState(), - "Attachment state of renderBundles[%i] (%s) is not compatible with " - "attachment state of %s.", - i, renderBundles[i], this); - } - } - - mCommandBufferState = CommandBufferStateTracker{}; - - ExecuteBundlesCmd* cmd = - allocator->Allocate(Command::ExecuteBundles); - cmd->count = count; - - Ref* bundles = allocator->AllocateData>(count); - for (uint32_t i = 0; i < count; ++i) { - bundles[i] = renderBundles[i]; - - const RenderPassResourceUsage& usages = bundles[i]->GetResourceUsage(); - for (uint32_t i = 0; i < usages.buffers.size(); ++i) { - mUsageTracker.BufferUsedAs(usages.buffers[i], usages.bufferUsages[i]); - } - - for (uint32_t i = 0; i < usages.textures.size(); ++i) { - mUsageTracker.AddRenderBundleTextureUsage(usages.textures[i], - usages.textureUsages[i]); - } - + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { if (IsValidationEnabled()) { - mIndirectDrawMetadata.AddBundle(renderBundles[i]); - } - } + for (uint32_t i = 0; i < count; ++i) { + DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i])); - return {}; - }); + // TODO(dawn:563): Give more detail about why the states are incompatible. + DAWN_INVALID_IF( + GetAttachmentState() != renderBundles[i]->GetAttachmentState(), + "Attachment state of renderBundles[%i] (%s) is not compatible with " + "attachment state of %s.", + i, renderBundles[i], this); + } + } + + mCommandBufferState = CommandBufferStateTracker{}; + + ExecuteBundlesCmd* cmd = + allocator->Allocate(Command::ExecuteBundles); + cmd->count = count; + + Ref* bundles = + allocator->AllocateData>(count); + for (uint32_t i = 0; i < count; ++i) { + bundles[i] = renderBundles[i]; + + const RenderPassResourceUsage& usages = bundles[i]->GetResourceUsage(); + for (uint32_t i = 0; i < usages.buffers.size(); ++i) { + mUsageTracker.BufferUsedAs(usages.buffers[i], usages.bufferUsages[i]); + } + + for (uint32_t i = 0; i < usages.textures.size(); ++i) { + mUsageTracker.AddRenderBundleTextureUsage(usages.textures[i], + usages.textureUsages[i]); + } + + if (IsValidationEnabled()) { + mIndirectDrawMetadata.AddBundle(renderBundles[i]); + } + } + + return {}; + }, + "encoding ExecuteBundles(%u, ...)", count); } void RenderPassEncoder::APIBeginOcclusionQuery(uint32_t queryIndex) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_INVALID_IF(mOcclusionQuerySet.Get() == nullptr, - "The occlusionQuerySet in RenderPassDescriptor is not set."); + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_INVALID_IF(mOcclusionQuerySet.Get() == nullptr, + "The occlusionQuerySet in RenderPassDescriptor is not set."); - // The type of querySet has been validated by ValidateRenderPassDescriptor + // The type of querySet has been validated by ValidateRenderPassDescriptor - DAWN_INVALID_IF(queryIndex >= mOcclusionQuerySet->GetQueryCount(), - "Query index (%u) exceeds the number of queries (%u) in %s.", - queryIndex, mOcclusionQuerySet->GetQueryCount(), - mOcclusionQuerySet.Get()); + DAWN_INVALID_IF(queryIndex >= mOcclusionQuerySet->GetQueryCount(), + "Query index (%u) exceeds the number of queries (%u) in %s.", + queryIndex, mOcclusionQuerySet->GetQueryCount(), + mOcclusionQuerySet.Get()); - DAWN_INVALID_IF(mOcclusionQueryActive, - "An occlusion query (%u) in %s is already active.", - mCurrentOcclusionQueryIndex, mOcclusionQuerySet.Get()); + DAWN_INVALID_IF(mOcclusionQueryActive, + "An occlusion query (%u) in %s is already active.", + mCurrentOcclusionQueryIndex, mOcclusionQuerySet.Get()); - DAWN_TRY_CONTEXT( - ValidateQueryIndexOverwrite(mOcclusionQuerySet.Get(), queryIndex, - mUsageTracker.GetQueryAvailabilityMap()), - "validating the occlusion query index (%u) in %s", queryIndex, - mOcclusionQuerySet.Get()); - } + DAWN_TRY_CONTEXT( + ValidateQueryIndexOverwrite(mOcclusionQuerySet.Get(), queryIndex, + mUsageTracker.GetQueryAvailabilityMap()), + "validating the occlusion query index (%u) in %s", queryIndex, + mOcclusionQuerySet.Get()); + } - // Record the current query index for endOcclusionQuery. - mCurrentOcclusionQueryIndex = queryIndex; - mOcclusionQueryActive = true; + // Record the current query index for endOcclusionQuery. + mCurrentOcclusionQueryIndex = queryIndex; + mOcclusionQueryActive = true; - BeginOcclusionQueryCmd* cmd = - allocator->Allocate(Command::BeginOcclusionQuery); - cmd->querySet = mOcclusionQuerySet.Get(); - cmd->queryIndex = queryIndex; + BeginOcclusionQueryCmd* cmd = + allocator->Allocate(Command::BeginOcclusionQuery); + cmd->querySet = mOcclusionQuerySet.Get(); + cmd->queryIndex = queryIndex; - return {}; - }); + return {}; + }, + "encoding BeginOcclusionQuery(%u)", queryIndex); } void RenderPassEncoder::APIEndOcclusionQuery() { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_INVALID_IF(!mOcclusionQueryActive, "No occlusion queries are active."); - } + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_INVALID_IF(!mOcclusionQueryActive, "No occlusion queries are active."); + } - TrackQueryAvailability(mOcclusionQuerySet.Get(), mCurrentOcclusionQueryIndex); + TrackQueryAvailability(mOcclusionQuerySet.Get(), mCurrentOcclusionQueryIndex); - mOcclusionQueryActive = false; + mOcclusionQueryActive = false; - EndOcclusionQueryCmd* cmd = - allocator->Allocate(Command::EndOcclusionQuery); - cmd->querySet = mOcclusionQuerySet.Get(); - cmd->queryIndex = mCurrentOcclusionQueryIndex; + EndOcclusionQueryCmd* cmd = + allocator->Allocate(Command::EndOcclusionQuery); + cmd->querySet = mOcclusionQuerySet.Get(); + cmd->queryIndex = mCurrentOcclusionQueryIndex; - return {}; - }); + return {}; + }, + "encoding EndOcclusionQuery()"); } void RenderPassEncoder::APIWriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) { - mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - if (IsValidationEnabled()) { - DAWN_TRY(GetDevice()->ValidateObject(querySet)); - DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); - DAWN_TRY_CONTEXT(ValidateQueryIndexOverwrite( - querySet, queryIndex, mUsageTracker.GetQueryAvailabilityMap()), - "validating the timestamp query index (%u) of %s", queryIndex, - querySet); - } + mEncodingContext->TryEncode( + this, + [&](CommandAllocator* allocator) -> MaybeError { + if (IsValidationEnabled()) { + DAWN_TRY(GetDevice()->ValidateObject(querySet)); + DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); + DAWN_TRY_CONTEXT( + ValidateQueryIndexOverwrite(querySet, queryIndex, + mUsageTracker.GetQueryAvailabilityMap()), + "validating the timestamp query index (%u) of %s", queryIndex, querySet); + } - TrackQueryAvailability(querySet, queryIndex); + TrackQueryAvailability(querySet, queryIndex); - WriteTimestampCmd* cmd = - allocator->Allocate(Command::WriteTimestamp); - cmd->querySet = querySet; - cmd->queryIndex = queryIndex; + WriteTimestampCmd* cmd = + allocator->Allocate(Command::WriteTimestamp); + cmd->querySet = querySet; + cmd->queryIndex = queryIndex; - return {}; - }); + return {}; + }, + "encoding WriteTimestamp(%s, %u).", querySet, queryIndex); } } // namespace dawn_native