Add validation for GPURender/ComputePassTimestampLocation

Disallow duplicate location in timestampWrites in a render/compute pass
to match WebGPU SPEC.

Bug: dawn:1250
Change-Id: Id9e3b54530d37ffc0c00aa15c23312bb1ea30d00
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/90460
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Hao Li <hao.x.li@intel.com>
This commit is contained in:
Hao Li 2022-06-07 03:13:53 +00:00 committed by Dawn LUCI CQ
parent 7437540e77
commit e7099d4f3b
2 changed files with 61 additions and 11 deletions

View File

@ -14,6 +14,7 @@
#include "dawn/native/CommandEncoder.h" #include "dawn/native/CommandEncoder.h"
#include <unordered_set>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -414,6 +415,30 @@ MaybeError ValidateRenderPassDepthStencilAttachment(
return {}; return {};
} }
MaybeError ValidateTimestampLocationOnRenderPass(
wgpu::RenderPassTimestampLocation location,
const std::unordered_set<wgpu::RenderPassTimestampLocation>& writtenLocations) {
DAWN_TRY(ValidateRenderPassTimestampLocation(location));
DAWN_INVALID_IF(writtenLocations.find(location) != writtenLocations.end(),
"There are two same RenderPassTimestampLocation %u in a render pass.",
location);
return {};
}
MaybeError ValidateTimestampLocationOnComputePass(
wgpu::ComputePassTimestampLocation location,
const std::unordered_set<wgpu::ComputePassTimestampLocation>& writtenLocations) {
DAWN_TRY(ValidateComputePassTimestampLocation(location));
DAWN_INVALID_IF(writtenLocations.find(location) != writtenLocations.end(),
"There are two same ComputePassTimestampLocation %u in a compute pass.",
location);
return {};
}
MaybeError ValidateRenderPassDescriptor(DeviceBase* device, MaybeError ValidateRenderPassDescriptor(DeviceBase* device,
const RenderPassDescriptor* descriptor, const RenderPassDescriptor* descriptor,
uint32_t* width, uint32_t* width,
@ -465,15 +490,22 @@ MaybeError ValidateRenderPassDescriptor(DeviceBase* device,
// not validated and encoded one by one, but encoded together after passing the // not validated and encoded one by one, but encoded together after passing the
// validation. // validation.
QueryAvailabilityMap usedQueries; QueryAvailabilityMap usedQueries;
// TODO(https://crbug.com/dawn/1452):
// 1. Add an enum that's TimestampLocationMask and has bit values.
// 2. Add a function with a switch that converts from one to the other.
// 3. type alias the ityp::bitset for that to call it TimestampLocationSet.
// 4. Use it here.
std::unordered_set<wgpu::RenderPassTimestampLocation> writtenLocations;
for (uint32_t i = 0; i < descriptor->timestampWriteCount; ++i) { for (uint32_t i = 0; i < descriptor->timestampWriteCount; ++i) {
QuerySetBase* querySet = descriptor->timestampWrites[i].querySet; QuerySetBase* querySet = descriptor->timestampWrites[i].querySet;
DAWN_ASSERT(querySet != nullptr); DAWN_ASSERT(querySet != nullptr);
uint32_t queryIndex = descriptor->timestampWrites[i].queryIndex; uint32_t queryIndex = descriptor->timestampWrites[i].queryIndex;
DAWN_TRY_CONTEXT(ValidateTimestampQuery(device, querySet, queryIndex), DAWN_TRY_CONTEXT(ValidateTimestampQuery(device, querySet, queryIndex),
"validating querySet and queryIndex of timestampWrites[%u].", i); "validating querySet and queryIndex of timestampWrites[%u].", i);
DAWN_TRY_CONTEXT( DAWN_TRY_CONTEXT(ValidateTimestampLocationOnRenderPass(
ValidateRenderPassTimestampLocation(descriptor->timestampWrites[i].location), descriptor->timestampWrites[i].location, writtenLocations),
"validating location of timestampWrites[%u].", i); "validating location of timestampWrites[%u].", i);
writtenLocations.insert(descriptor->timestampWrites[i].location);
auto checkIt = usedQueries.find(querySet); auto checkIt = usedQueries.find(querySet);
DAWN_INVALID_IF(checkIt != usedQueries.end() && checkIt->second[queryIndex], DAWN_INVALID_IF(checkIt != usedQueries.end() && checkIt->second[queryIndex],
@ -503,14 +535,21 @@ MaybeError ValidateComputePassDescriptor(const DeviceBase* device,
if (descriptor->timestampWriteCount > 0) { if (descriptor->timestampWriteCount > 0) {
DAWN_ASSERT(descriptor->timestampWrites != nullptr); DAWN_ASSERT(descriptor->timestampWrites != nullptr);
// TODO(https://crbug.com/dawn/1452):
// 1. Add an enum that's TimestampLocationMask and has bit values.
// 2. Add a function with a switch that converts from one to the other.
// 3. type alias the ityp::bitset for that to call it TimestampLocationSet.
// 4. Use it here.
std::unordered_set<wgpu::ComputePassTimestampLocation> writtenLocations;
for (uint32_t i = 0; i < descriptor->timestampWriteCount; ++i) { for (uint32_t i = 0; i < descriptor->timestampWriteCount; ++i) {
DAWN_ASSERT(descriptor->timestampWrites[i].querySet != nullptr); DAWN_ASSERT(descriptor->timestampWrites[i].querySet != nullptr);
DAWN_TRY_CONTEXT(ValidateTimestampQuery(device, descriptor->timestampWrites[i].querySet, DAWN_TRY_CONTEXT(ValidateTimestampQuery(device, descriptor->timestampWrites[i].querySet,
descriptor->timestampWrites[i].queryIndex), descriptor->timestampWrites[i].queryIndex),
"validating querySet and queryIndex of timestampWrites[%u].", i); "validating querySet and queryIndex of timestampWrites[%u].", i);
DAWN_TRY_CONTEXT( DAWN_TRY_CONTEXT(ValidateTimestampLocationOnComputePass(
ValidateComputePassTimestampLocation(descriptor->timestampWrites[i].location), descriptor->timestampWrites[i].location, writtenLocations),
"validating location of timestampWrites[%u].", i); "validating location of timestampWrites[%u].", i);
writtenLocations.insert(descriptor->timestampWrites[i].location);
} }
} }

View File

@ -352,13 +352,23 @@ TEST_F(TimestampQueryValidationTest, TimestampWritesOnComputePass) {
encoder.Finish(); encoder.Finish();
} }
// Success to write timestamps at same location of compute pass // Success to write timestamps at same location of different compute pass
{
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
EncodeComputePassWithTimestampWrites(
encoder, {{querySet, 0, wgpu::ComputePassTimestampLocation::Beginning}});
EncodeComputePassWithTimestampWrites(
encoder, {{querySet, 0, wgpu::ComputePassTimestampLocation::Beginning}});
encoder.Finish();
}
// Fail to write timestamps at same location of a compute pass
{ {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
EncodeComputePassWithTimestampWrites( EncodeComputePassWithTimestampWrites(
encoder, {{querySet, 0, wgpu::ComputePassTimestampLocation::Beginning}, encoder, {{querySet, 0, wgpu::ComputePassTimestampLocation::Beginning},
{querySet, 1, wgpu::ComputePassTimestampLocation::Beginning}}); {querySet, 1, wgpu::ComputePassTimestampLocation::Beginning}});
encoder.Finish(); ASSERT_DEVICE_ERROR(encoder.Finish());
} }
// Fail to write timestamps at invalid location of compute pass // Fail to write timestamps at invalid location of compute pass
@ -427,7 +437,8 @@ TEST_F(TimestampQueryValidationTest, TimestampWritesOnRenderPass) {
ASSERT_DEVICE_ERROR(encoder.Finish()); ASSERT_DEVICE_ERROR(encoder.Finish());
} }
// Success to write timestamps to the same query index twice on different render pass // Success to write timestamps to the same query index and location twice on different render
// pass
{ {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
EncodeRenderPassWithTimestampWrites( EncodeRenderPassWithTimestampWrites(
@ -449,13 +460,13 @@ TEST_F(TimestampQueryValidationTest, TimestampWritesOnRenderPass) {
ASSERT_DEVICE_ERROR(encoder.Finish()); ASSERT_DEVICE_ERROR(encoder.Finish());
} }
// Success to write timestamps at same location of render pass // Fail to write timestamps at same location of a render pass
{ {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
EncodeRenderPassWithTimestampWrites( EncodeRenderPassWithTimestampWrites(
encoder, {{querySet, 0, wgpu::RenderPassTimestampLocation::Beginning}, encoder, {{querySet, 0, wgpu::RenderPassTimestampLocation::Beginning},
{querySet, 1, wgpu::RenderPassTimestampLocation::Beginning}}); {querySet, 1, wgpu::RenderPassTimestampLocation::Beginning}});
encoder.Finish(); ASSERT_DEVICE_ERROR(encoder.Finish());
} }
// Fail to write timestamps at invalid location of render pass // Fail to write timestamps at invalid location of render pass