ValidationTest: Make custom device creation go through a virtual method

Previously tests that needed to use a device that wasn't the default
device created a new one via a method that only supported customizing
extensions. Instead of adding a second function the device creation is
made completely customizable by querying the test's device via a
overridable method.

This heavily refactors the QuerySet tests to use the new methods
(previously they were using 3 different devices in the same fixture) but
loses a little bit of coverage of what happens when some query
operations are done with mixed devices.

This is required for a follow-up CL that adds tests for a device created
with the "disallow_unsafe_api" toggle that needs to be set on device
creation.

Bug: chromium:1138528

Change-Id: Ic2f5d876adca251b34ea594f70f344ac7669910e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/31442
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2020-11-03 10:18:05 +00:00 committed by Commit Bot service account
parent 71d2e1d23d
commit 43ef0a365b
9 changed files with 193 additions and 244 deletions

View File

@ -36,6 +36,8 @@ class BindGroupValidationTest : public ValidationTest {
} }
void SetUp() override { void SetUp() override {
ValidationTest::SetUp();
// Create objects to use as resources inside test bind groups. // Create objects to use as resources inside test bind groups.
{ {
wgpu::BufferDescriptor descriptor; wgpu::BufferDescriptor descriptor;
@ -1069,6 +1071,8 @@ constexpr uint32_t kBindingSize = 9;
class SetBindGroupValidationTest : public ValidationTest { class SetBindGroupValidationTest : public ValidationTest {
public: public:
void SetUp() override { void SetUp() override {
ValidationTest::SetUp();
mBindGroupLayout = utils::MakeBindGroupLayout( mBindGroupLayout = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment, device, {{0, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
wgpu::BindingType::UniformBuffer, true}, wgpu::BindingType::UniformBuffer, true},
@ -1509,6 +1513,8 @@ TEST_F(SetBindGroupValidationTest, ErrorBindGroup) {
class SetBindGroupPersistenceValidationTest : public ValidationTest { class SetBindGroupPersistenceValidationTest : public ValidationTest {
protected: protected:
void SetUp() override { void SetUp() override {
ValidationTest::SetUp();
mVsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( mVsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
#version 450 #version 450
void main() { void main() {

View File

@ -1769,12 +1769,13 @@ TEST_F(CopyCommandTest_T2T, CopyWithinSameTexture) {
} }
class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest { class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
public: protected:
CopyCommandTest_CompressedTextureFormats() : CopyCommandTest() { wgpu::Device CreateTestDevice() override {
device = CreateDeviceFromAdapter(adapter, {"texture_compression_bc"}); dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = {"texture_compression_bc"};
return wgpu::Device::Acquire(adapter.CreateDevice(&descriptor));
} }
protected:
wgpu::Texture Create2DTexture(wgpu::TextureFormat format, wgpu::Texture Create2DTexture(wgpu::TextureFormat format,
uint32_t mipmapLevels = 1, uint32_t mipmapLevels = 1,
uint32_t width = kWidth, uint32_t width = kWidth,

View File

@ -38,9 +38,10 @@ class ErrorScopeValidationTest : public ValidationTest {
} }
void TearDown() override { void TearDown() override {
ValidationTest::TearDown();
// Delete mocks so that expectations are checked // Delete mocks so that expectations are checked
mockDevicePopErrorScopeCallback = nullptr; mockDevicePopErrorScopeCallback = nullptr;
ValidationTest::TearDown();
} }
}; };

View File

@ -18,15 +18,6 @@
class QuerySetValidationTest : public ValidationTest { class QuerySetValidationTest : public ValidationTest {
protected: protected:
void SetUp() override {
ValidationTest::SetUp();
// Initialize the device with required extensions
deviceWithPipelineStatistics =
CreateDeviceFromAdapter(adapter, {"pipeline_statistics_query"});
deviceWithTimestamp = CreateDeviceFromAdapter(adapter, {"timestamp_query"});
}
wgpu::QuerySet CreateQuerySet( wgpu::QuerySet CreateQuerySet(
wgpu::Device cDevice, wgpu::Device cDevice,
wgpu::QueryType queryType, wgpu::QueryType queryType,
@ -43,43 +34,17 @@ class QuerySetValidationTest : public ValidationTest {
return cDevice.CreateQuerySet(&descriptor); return cDevice.CreateQuerySet(&descriptor);
} }
wgpu::Device deviceWithPipelineStatistics;
wgpu::Device deviceWithTimestamp;
}; };
// Test creating query set with/without extensions // Test creating query set without extensions
TEST_F(QuerySetValidationTest, Creation) { TEST_F(QuerySetValidationTest, CreationWithoutExtensions) {
// Create query set for Occlusion query // Creating a query set for occlusion queries succeeds without any extensions enabled.
{
// Success on default device without any extension enabled
// Occlusion query does not require any extension.
CreateQuerySet(device, wgpu::QueryType::Occlusion, 1); CreateQuerySet(device, wgpu::QueryType::Occlusion, 1);
// Success on the device with extension enabled. // Creating a query set for other types of queries fails without extensions enabled.
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::Occlusion, 1);
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 1);
}
// Create query set for PipelineStatistics query
{
// Fail on default device without any extension enabled
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1, ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations})); {wgpu::PipelineStatisticName::VertexShaderInvocations}));
// Success on the device if the extension is enabled.
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations});
}
// Create query set for Timestamp query
{
// Fail on default device without any extension enabled
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Timestamp, 1)); ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Timestamp, 1));
// Success on the device if the extension is enabled.
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 1);
}
} }
// Test creating query set with invalid type // Test creating query set with invalid type
@ -87,54 +52,10 @@ TEST_F(QuerySetValidationTest, InvalidQueryType) {
ASSERT_DEVICE_ERROR(CreateQuerySet(device, static_cast<wgpu::QueryType>(0xFFFFFFFF), 1)); ASSERT_DEVICE_ERROR(CreateQuerySet(device, static_cast<wgpu::QueryType>(0xFFFFFFFF), 1));
} }
// Test creating query set with unnecessary pipeline statistics // Test creating query set with unnecessary pipeline statistics for occlusion queries
TEST_F(QuerySetValidationTest, UnnecessaryPipelineStatistics) { TEST_F(QuerySetValidationTest, UnnecessaryPipelineStatistics) {
// Fail to create with pipeline statistics for Occlusion query
{
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Occlusion, 1, ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Occlusion, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations})); {wgpu::PipelineStatisticName::VertexShaderInvocations}));
}
// Fail to create with pipeline statistics for Timestamp query
{
ASSERT_DEVICE_ERROR(CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations}));
}
}
// Test creating query set with invalid pipeline statistics
TEST_F(QuerySetValidationTest, InvalidPipelineStatistics) {
// Success to create with all pipeline statistics names which are not in the same order as
// defined in webgpu header file
{
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::ClipperInvocations,
wgpu::PipelineStatisticName::ClipperPrimitivesOut,
wgpu::PipelineStatisticName::ComputeShaderInvocations,
wgpu::PipelineStatisticName::FragmentShaderInvocations,
wgpu::PipelineStatisticName::VertexShaderInvocations});
}
// Fail to create with empty pipeline statistics
{
ASSERT_DEVICE_ERROR(CreateQuerySet(deviceWithPipelineStatistics,
wgpu::QueryType::PipelineStatistics, 1, {}));
}
// Fail to create with invalid pipeline statistics
{
ASSERT_DEVICE_ERROR(CreateQuerySet(deviceWithPipelineStatistics,
wgpu::QueryType::PipelineStatistics, 1,
{static_cast<wgpu::PipelineStatisticName>(0xFFFFFFFF)}));
}
// Fail to create with duplicate pipeline statistics
{
ASSERT_DEVICE_ERROR(CreateQuerySet(deviceWithPipelineStatistics,
wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations,
wgpu::PipelineStatisticName::VertexShaderInvocations}));
}
} }
// Test destroying a destroyed query set // Test destroying a destroyed query set
@ -147,47 +68,61 @@ TEST_F(QuerySetValidationTest, DestroyDestroyedQuerySet) {
querySet.Destroy(); querySet.Destroy();
} }
class TimestampQueryValidationTest : public QuerySetValidationTest {}; class TimestampQueryValidationTest : public QuerySetValidationTest {
protected:
wgpu::Device CreateTestDevice() override {
dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = {"timestamp_query"};
return wgpu::Device::Acquire(adapter.CreateDevice(&descriptor));
}
};
// Test creating query set with only the timestamp extension enabled.
TEST_F(TimestampQueryValidationTest, Creation) {
// Creating a query set for occlusion queries succeeds.
CreateQuerySet(device, wgpu::QueryType::Occlusion, 1);
// Creating a query set for pipeline statistics queries fails.
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations}));
// Creating a query set for timestamp queries succeeds.
CreateQuerySet(device, wgpu::QueryType::Timestamp, 1);
// Fail to create with pipeline statistics for Timestamp query
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Timestamp, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations}));
}
// Test creating query set with unnecessary pipeline statistics for timestamp queries
TEST_F(TimestampQueryValidationTest, UnnecessaryPipelineStatistics) {
// Fail to create with pipeline statistics for Occlusion query
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Timestamp, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations}));
}
// Test write timestamp on command encoder // Test write timestamp on command encoder
TEST_F(TimestampQueryValidationTest, WriteTimestampOnCommandEncoder) { TEST_F(TimestampQueryValidationTest, WriteTimestampOnCommandEncoder) {
wgpu::QuerySet timestampQuerySet = wgpu::QuerySet timestampQuerySet = CreateQuerySet(device, wgpu::QueryType::Timestamp, 2);
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 2); wgpu::QuerySet occlusionQuerySet = CreateQuerySet(device, wgpu::QueryType::Occlusion, 2);
wgpu::QuerySet occlusionQuerySet =
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 2);
// Success on command encoder // Success on command encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(timestampQuerySet, 0); encoder.WriteTimestamp(timestampQuerySet, 0);
encoder.Finish(); encoder.Finish();
} }
// Not allow to write timestamp from another device
{
// Write timestamp from default device
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(timestampQuerySet, 0);
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Not allow to write timestamp to the query set with other query type
{
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
encoder.WriteTimestamp(occlusionQuerySet, 0);
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Fail to write timestamp to the index which exceeds the number of queries in query set // Fail to write timestamp to the index which exceeds the number of queries in query set
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(timestampQuerySet, 2); encoder.WriteTimestamp(timestampQuerySet, 2);
ASSERT_DEVICE_ERROR(encoder.Finish()); ASSERT_DEVICE_ERROR(encoder.Finish());
} }
// Fail to write timestamp to the same index twice on command encoder // Fail to write timestamp to the same index twice on command encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(timestampQuerySet, 0); encoder.WriteTimestamp(timestampQuerySet, 0);
encoder.WriteTimestamp(timestampQuerySet, 0); encoder.WriteTimestamp(timestampQuerySet, 0);
ASSERT_DEVICE_ERROR(encoder.Finish()); ASSERT_DEVICE_ERROR(encoder.Finish());
@ -195,11 +130,11 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnCommandEncoder) {
// Fail to submit timestamp query with a destroyed query set // Fail to submit timestamp query with a destroyed query set
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(timestampQuerySet, 0); encoder.WriteTimestamp(timestampQuerySet, 0);
wgpu::CommandBuffer commands = encoder.Finish(); wgpu::CommandBuffer commands = encoder.Finish();
wgpu::Queue queue = deviceWithTimestamp.GetDefaultQueue(); wgpu::Queue queue = device.GetDefaultQueue();
timestampQuerySet.Destroy(); timestampQuerySet.Destroy();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands)); ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
} }
@ -207,33 +142,21 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnCommandEncoder) {
// Test write timestamp on compute pass encoder // Test write timestamp on compute pass encoder
TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) { TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
wgpu::QuerySet timestampQuerySet = wgpu::QuerySet timestampQuerySet = CreateQuerySet(device, wgpu::QueryType::Timestamp, 2);
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 2); wgpu::QuerySet occlusionQuerySet = CreateQuerySet(device, wgpu::QueryType::Occlusion, 2);
wgpu::QuerySet occlusionQuerySet =
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 2);
// Success on compute pass encoder // Success on compute pass encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass(); wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
pass.EndPass(); pass.EndPass();
encoder.Finish(); encoder.Finish();
} }
// Not allow to write timestamp from another device
{
// Write timestamp from default device
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.WriteTimestamp(timestampQuerySet, 0);
pass.EndPass();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Not allow to write timestamp to the query set with other query type // Not allow to write timestamp to the query set with other query type
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass(); wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.WriteTimestamp(occlusionQuerySet, 0); pass.WriteTimestamp(occlusionQuerySet, 0);
pass.EndPass(); pass.EndPass();
@ -242,7 +165,7 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
// Fail to write timestamp to the index which exceeds the number of queries in query set // Fail to write timestamp to the index which exceeds the number of queries in query set
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass(); wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.WriteTimestamp(timestampQuerySet, 2); pass.WriteTimestamp(timestampQuerySet, 2);
pass.EndPass(); pass.EndPass();
@ -251,7 +174,7 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
// Fail to write timestamp to the same index twice on compute encoder // Fail to write timestamp to the same index twice on compute encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass(); wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
@ -261,7 +184,7 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
// Fail to write timestamp to the same index twice on command encoder and compute encoder // Fail to write timestamp to the same index twice on command encoder and compute encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(timestampQuerySet, 0); encoder.WriteTimestamp(timestampQuerySet, 0);
wgpu::ComputePassEncoder pass = encoder.BeginComputePass(); wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
@ -271,13 +194,13 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
// Fail to submit timestamp query with a destroyed query set // Fail to submit timestamp query with a destroyed query set
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass(); wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
pass.EndPass(); pass.EndPass();
wgpu::CommandBuffer commands = encoder.Finish(); wgpu::CommandBuffer commands = encoder.Finish();
wgpu::Queue queue = deviceWithTimestamp.GetDefaultQueue(); wgpu::Queue queue = device.GetDefaultQueue();
timestampQuerySet.Destroy(); timestampQuerySet.Destroy();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands)); ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
} }
@ -285,35 +208,23 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
// Test write timestamp on render pass encoder // Test write timestamp on render pass encoder
TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) { TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) {
DummyRenderPass renderPass(deviceWithTimestamp); DummyRenderPass renderPass(device);
wgpu::QuerySet timestampQuerySet = wgpu::QuerySet timestampQuerySet = CreateQuerySet(device, wgpu::QueryType::Timestamp, 2);
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 2); wgpu::QuerySet occlusionQuerySet = CreateQuerySet(device, wgpu::QueryType::Occlusion, 2);
wgpu::QuerySet occlusionQuerySet =
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 2);
// Success on render pass encoder // Success on render pass encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
pass.EndPass(); pass.EndPass();
encoder.Finish(); encoder.Finish();
} }
// Not allow to write timestamp from another device
{
// Write timestamp from default device
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.WriteTimestamp(timestampQuerySet, 0);
pass.EndPass();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Not allow to write timestamp to the query set with other query type // Not allow to write timestamp to the query set with other query type
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.WriteTimestamp(occlusionQuerySet, 0); pass.WriteTimestamp(occlusionQuerySet, 0);
pass.EndPass(); pass.EndPass();
@ -322,7 +233,7 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) {
// Fail to write timestamp to the index which exceeds the number of queries in query set // Fail to write timestamp to the index which exceeds the number of queries in query set
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.WriteTimestamp(timestampQuerySet, 2); pass.WriteTimestamp(timestampQuerySet, 2);
pass.EndPass(); pass.EndPass();
@ -331,7 +242,7 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) {
// Fail to write timestamp to the same index twice on command encoder and render encoder // Fail to write timestamp to the same index twice on command encoder and render encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
@ -341,7 +252,7 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) {
// Fail to write timestamp to the same index twice on command encoder and render encoder // Fail to write timestamp to the same index twice on command encoder and render encoder
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(timestampQuerySet, 0); encoder.WriteTimestamp(timestampQuerySet, 0);
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
@ -351,18 +262,70 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) {
// Fail to submit timestamp query with a destroyed query set // Fail to submit timestamp query with a destroyed query set
{ {
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.WriteTimestamp(timestampQuerySet, 0); pass.WriteTimestamp(timestampQuerySet, 0);
pass.EndPass(); pass.EndPass();
wgpu::CommandBuffer commands = encoder.Finish(); wgpu::CommandBuffer commands = encoder.Finish();
wgpu::Queue queue = deviceWithTimestamp.GetDefaultQueue(); wgpu::Queue queue = device.GetDefaultQueue();
timestampQuerySet.Destroy(); timestampQuerySet.Destroy();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands)); ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
} }
} }
class PipelineStatisticsQueryValidationTest : public QuerySetValidationTest {
protected:
wgpu::Device CreateTestDevice() override {
dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = {"pipeline_statistics_query"};
return wgpu::Device::Acquire(adapter.CreateDevice(&descriptor));
}
};
// Test creating query set with only the pipeline statistics extension enabled.
TEST_F(PipelineStatisticsQueryValidationTest, Creation) {
// Creating a query set for occlusion queries succeeds.
CreateQuerySet(device, wgpu::QueryType::Occlusion, 1);
// Creating a query set for timestamp queries fails.
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Timestamp, 1));
// Creating a query set for pipeline statistics queries succeeds.
CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations});
}
// Test creating query set with invalid pipeline statistics
TEST_F(PipelineStatisticsQueryValidationTest, InvalidPipelineStatistics) {
// Success to create with all pipeline statistics names which are not in the same order as
// defined in webgpu header file
{
CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::ClipperInvocations,
wgpu::PipelineStatisticName::ClipperPrimitivesOut,
wgpu::PipelineStatisticName::ComputeShaderInvocations,
wgpu::PipelineStatisticName::FragmentShaderInvocations,
wgpu::PipelineStatisticName::VertexShaderInvocations});
}
// Fail to create with empty pipeline statistics
{ ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1, {})); }
// Fail to create with invalid pipeline statistics
{
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1,
{static_cast<wgpu::PipelineStatisticName>(0xFFFFFFFF)}));
}
// Fail to create with duplicate pipeline statistics
{
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticName::VertexShaderInvocations,
wgpu::PipelineStatisticName::VertexShaderInvocations}));
}
}
class ResolveQuerySetValidationTest : public QuerySetValidationTest { class ResolveQuerySetValidationTest : public QuerySetValidationTest {
protected: protected:
wgpu::Buffer CreateBuffer(wgpu::Device cDevice, uint64_t size, wgpu::BufferUsage usage) { wgpu::Buffer CreateBuffer(wgpu::Device cDevice, uint64_t size, wgpu::BufferUsage usage) {
@ -392,13 +355,6 @@ TEST_F(ResolveQuerySetValidationTest, ResolveInvalidQuerySetAndIndexCount) {
queue.Submit(1, &commands); queue.Submit(1, &commands);
} }
// Fail to resolve query set from another device
{
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
encoder.ResolveQuerySet(querySet, 0, kQueryCount, destination, 0);
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Fail to resolve query set if first query out of range // Fail to resolve query set if first query out of range
{ {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
@ -446,10 +402,11 @@ TEST_F(ResolveQuerySetValidationTest, ResolveToInvalidBufferAndOffset) {
// Fail to resolve query set to a buffer created from another device // Fail to resolve query set to a buffer created from another device
{ {
wgpu::Buffer bufferOnTimestamp = wgpu::Device otherDevice = adapter.CreateDevice();
CreateBuffer(deviceWithTimestamp, kBufferSize, wgpu::BufferUsage::QueryResolve); wgpu::Buffer bufferOnOther =
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder(); CreateBuffer(otherDevice, kBufferSize, wgpu::BufferUsage::QueryResolve);
encoder.ResolveQuerySet(querySet, 0, kQueryCount, bufferOnTimestamp, 0); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.ResolveQuerySet(querySet, 0, kQueryCount, bufferOnOther, 0);
ASSERT_DEVICE_ERROR(encoder.Finish()); ASSERT_DEVICE_ERROR(encoder.Finish());
} }

View File

@ -520,12 +520,13 @@ namespace {
} }
class WriteTextureTest_CompressedTextureFormats : public QueueWriteTextureValidationTest { class WriteTextureTest_CompressedTextureFormats : public QueueWriteTextureValidationTest {
public: protected:
WriteTextureTest_CompressedTextureFormats() : QueueWriteTextureValidationTest() { wgpu::Device CreateTestDevice() override {
device = CreateDeviceFromAdapter(adapter, {"texture_compression_bc"}); dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = {"texture_compression_bc"};
return wgpu::Device::Acquire(adapter.CreateDevice(&descriptor));
} }
protected:
wgpu::Texture Create2DTexture(wgpu::TextureFormat format, wgpu::Texture Create2DTexture(wgpu::TextureFormat format,
uint32_t mipmapLevels = 1, uint32_t mipmapLevels = 1,
uint32_t width = kWidth, uint32_t width = kWidth,

View File

@ -20,6 +20,22 @@
class StorageTextureValidationTests : public ValidationTest { class StorageTextureValidationTests : public ValidationTest {
protected: protected:
void SetUp() override {
ValidationTest::SetUp();
mDefaultVSModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
#version 450
void main() {
gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
})");
mDefaultFSModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
#version 450
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = vec4(1.f, 0.f, 0.f, 1.f);
})");
}
static const char* GetGLSLFloatImageTypeDeclaration(wgpu::TextureViewDimension dimension) { static const char* GetGLSLFloatImageTypeDeclaration(wgpu::TextureViewDimension dimension) {
switch (dimension) { switch (dimension) {
case wgpu::TextureViewDimension::e1D: case wgpu::TextureViewDimension::e1D:
@ -97,19 +113,8 @@ class StorageTextureValidationTests : public ValidationTest {
return device.CreateTexture(&descriptor); return device.CreateTexture(&descriptor);
} }
const wgpu::ShaderModule mDefaultVSModule = wgpu::ShaderModule mDefaultVSModule;
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( wgpu::ShaderModule mDefaultFSModule;
#version 450
void main() {
gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
})");
const wgpu::ShaderModule mDefaultFSModule =
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
#version 450
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = vec4(1.f, 0.f, 0.f, 1.f);
})");
const std::array<wgpu::BindingType, 2> kSupportedStorageTextureBindingTypes = { const std::array<wgpu::BindingType, 2> kSupportedStorageTextureBindingTypes = {
wgpu::BindingType::ReadonlyStorageTexture, wgpu::BindingType::WriteonlyStorageTexture}; wgpu::BindingType::ReadonlyStorageTexture, wgpu::BindingType::WriteonlyStorageTexture};

View File

@ -24,6 +24,8 @@ namespace {
class TextureValidationTest : public ValidationTest { class TextureValidationTest : public ValidationTest {
protected: protected:
void SetUp() override { void SetUp() override {
ValidationTest::SetUp();
queue = device.GetDefaultQueue(); queue = device.GetDefaultQueue();
} }
@ -377,15 +379,26 @@ namespace {
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
} }
// Test that the creation of a texture with BC format will fail when the extension
// textureCompressionBC is not enabled.
TEST_F(TextureValidationTest, UseBCFormatWithoutEnablingExtension) {
for (wgpu::TextureFormat format : utils::kBCFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
}
// TODO(jiawei.shao@intel.com): add tests to verify we cannot create 1D or 3D textures with // TODO(jiawei.shao@intel.com): add tests to verify we cannot create 1D or 3D textures with
// compressed texture formats. // compressed texture formats.
class CompressedTextureFormatsValidationTests : public TextureValidationTest { class CompressedTextureFormatsValidationTests : public TextureValidationTest {
public: protected:
CompressedTextureFormatsValidationTests() : TextureValidationTest() { wgpu::Device CreateTestDevice() override {
device = CreateDeviceFromAdapter(adapter, {"texture_compression_bc"}); dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = {"texture_compression_bc"};
return wgpu::Device::Acquire(adapter.CreateDevice(&descriptor));
} }
protected:
wgpu::TextureDescriptor CreateDefaultTextureDescriptor() { wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
wgpu::TextureDescriptor descriptor = wgpu::TextureDescriptor descriptor =
TextureValidationTest::CreateDefaultTextureDescriptor(); TextureValidationTest::CreateDefaultTextureDescriptor();
@ -393,22 +406,13 @@ namespace {
wgpu::TextureUsage::Sampled; wgpu::TextureUsage::Sampled;
return descriptor; return descriptor;
} }
const std::array<wgpu::TextureFormat, 14> kBCFormats = {
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::BC4RSnorm,
wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::BC5RGSnorm,
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBFloat,
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb};
}; };
// Test the validation of texture size when creating textures in compressed texture formats. // Test the validation of texture size when creating textures in compressed texture formats.
TEST_F(CompressedTextureFormatsValidationTests, TextureSize) { TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
// Test that it is invalid to use a number that is not a multiple of 4 (the compressed block // Test that it is invalid to use a number that is not a multiple of 4 (the compressed block
// width and height of all BC formats) as the width or height of textures in BC formats. // width and height of all BC formats) as the width or height of textures in BC formats.
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : utils::kBCFormats) {
{ {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor(); wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format; descriptor.format = format;
@ -440,18 +444,6 @@ namespace {
} }
} }
// Test the creation of a texture with BC format will fail when the extension
// textureCompressionBC is not enabled.
TEST_F(CompressedTextureFormatsValidationTests, UseBCFormatWithoutEnablingExtension) {
const std::vector<const char*> kEmptyVector;
wgpu::Device deviceWithoutExtension = CreateDeviceFromAdapter(adapter, kEmptyVector);
for (wgpu::TextureFormat format : kBCFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
ASSERT_DEVICE_ERROR(deviceWithoutExtension.CreateTexture(&descriptor));
}
}
// Test the validation of texture usages when creating textures in compressed texture formats. // Test the validation of texture usages when creating textures in compressed texture formats.
TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) { TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) {
// Test that only CopySrc, CopyDst and Sampled are accepted as the texture usage of the // Test that only CopySrc, CopyDst and Sampled are accepted as the texture usage of the
@ -461,7 +453,7 @@ namespace {
wgpu::TextureUsage::Storage, wgpu::TextureUsage::Storage,
wgpu::TextureUsage::Present, wgpu::TextureUsage::Present,
}; };
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : utils::kBCFormats) {
for (wgpu::TextureUsage usage : invalidUsages) { for (wgpu::TextureUsage usage : invalidUsages) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor(); wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format; descriptor.format = format;
@ -475,7 +467,7 @@ namespace {
TEST_F(CompressedTextureFormatsValidationTests, SampleCount) { TEST_F(CompressedTextureFormatsValidationTests, SampleCount) {
// Test that it is invalid to specify SampleCount > 1 when we create a texture in BC // Test that it is invalid to specify SampleCount > 1 when we create a texture in BC
// formats. // formats.
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : utils::kBCFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor(); wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format; descriptor.format = format;
descriptor.sampleCount = 4; descriptor.sampleCount = 4;
@ -486,7 +478,7 @@ namespace {
// Test the validation of creating 2D array textures in compressed texture formats. // Test the validation of creating 2D array textures in compressed texture formats.
TEST_F(CompressedTextureFormatsValidationTests, 2DArrayTexture) { TEST_F(CompressedTextureFormatsValidationTests, 2DArrayTexture) {
// Test that it is allowed to create a 2D array texture in BC formats. // Test that it is allowed to create a 2D array texture in BC formats.
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : utils::kBCFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor(); wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format; descriptor.format = format;
descriptor.size.depth = 6; descriptor.size.depth = 6;

View File

@ -19,7 +19,7 @@
#include "dawn/webgpu.h" #include "dawn/webgpu.h"
#include "dawn_native/NullBackend.h" #include "dawn_native/NullBackend.h"
ValidationTest::ValidationTest() { void ValidationTest::SetUp() {
instance = std::make_unique<dawn_native::Instance>(); instance = std::make_unique<dawn_native::Instance>();
instance->DiscoverDefaultAdapters(); instance->DiscoverDefaultAdapters();
@ -42,25 +42,8 @@ ValidationTest::ValidationTest() {
dawnProcSetProcs(&dawn_native::GetProcs()); dawnProcSetProcs(&dawn_native::GetProcs());
device = CreateDeviceFromAdapter(adapter, std::vector<const char*>()); device = CreateTestDevice();
} device.SetUncapturedErrorCallback(ValidationTest::OnDeviceError, this);
wgpu::Device ValidationTest::CreateDeviceFromAdapter(
dawn_native::Adapter adapterToTest,
const std::vector<const char*>& requiredExtensions) {
wgpu::Device deviceToTest;
// Always keep this code path to test creating a device without a device descriptor.
if (requiredExtensions.empty()) {
deviceToTest = wgpu::Device::Acquire(adapterToTest.CreateDevice());
} else {
dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = requiredExtensions;
deviceToTest = wgpu::Device::Acquire(adapterToTest.CreateDevice(&descriptor));
}
deviceToTest.SetUncapturedErrorCallback(ValidationTest::OnDeviceError, this);
return deviceToTest;
} }
ValidationTest::~ValidationTest() { ValidationTest::~ValidationTest() {
@ -114,6 +97,10 @@ bool ValidationTest::HasWGSL() const {
#endif #endif
} }
wgpu::Device ValidationTest::CreateTestDevice() {
return wgpu::Device::Acquire(adapter.CreateDevice());
}
// static // static
void ValidationTest::OnDeviceError(WGPUErrorType type, const char* message, void* userdata) { void ValidationTest::OnDeviceError(WGPUErrorType type, const char* message, void* userdata) {
ASSERT(type != WGPUErrorType_NoError); ASSERT(type != WGPUErrorType_NoError);

View File

@ -50,12 +50,9 @@
class ValidationTest : public testing::Test { class ValidationTest : public testing::Test {
public: public:
ValidationTest();
~ValidationTest() override; ~ValidationTest() override;
wgpu::Device CreateDeviceFromAdapter(dawn_native::Adapter adapter, void SetUp() override;
const std::vector<const char*>& requiredExtensions);
void TearDown() override; void TearDown() override;
void StartExpectDeviceError(); void StartExpectDeviceError();
@ -81,6 +78,8 @@ class ValidationTest : public testing::Test {
bool HasWGSL() const; bool HasWGSL() const;
protected: protected:
virtual wgpu::Device CreateTestDevice();
wgpu::Device device; wgpu::Device device;
dawn_native::Adapter adapter; dawn_native::Adapter adapter;
std::unique_ptr<dawn_native::Instance> instance; std::unique_ptr<dawn_native::Instance> instance;