Compat: Reject CubeArrays via Validation

Bug: dawn:1825
Change-Id: I32917a479c3eea457c8f315cfc089351b64292b6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133320
Commit-Queue: Gregg Tavares <gman@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gregg Tavares 2023-05-24 12:39:46 +00:00 committed by Dawn LUCI CQ
parent 23c0451377
commit 0bdf2da9b8
11 changed files with 114 additions and 19 deletions

View File

@ -89,7 +89,7 @@
{ "name": "instance id", "type": "ObjectId", "id_type": "instance" }, { "name": "instance id", "type": "ObjectId", "id_type": "instance" },
{ "name": "request serial", "type": "uint64_t" }, { "name": "request serial", "type": "uint64_t" },
{ "name": "adapter object handle", "type": "ObjectHandle", "handle_type": "adapter"}, { "name": "adapter object handle", "type": "ObjectHandle", "handle_type": "adapter"},
{ "name": "options", "type": "request adapter options", "annotation": "const*" } { "name": "options", "type": "request adapter options", "annotation": "const*", "optional": true }
], ],
"adapter request device": [ "adapter request device": [
{ "name": "adapter id", "type": "ObjectId", "id_type": "adapter" }, { "name": "adapter id", "type": "ObjectId", "id_type": "adapter" },

View File

@ -1434,6 +1434,10 @@ bool DeviceBase::IsRobustnessEnabled() const {
return !IsToggleEnabled(Toggle::DisableRobustness); return !IsToggleEnabled(Toggle::DisableRobustness);
} }
bool DeviceBase::IsCompatibilityMode() const {
return mAdapter->GetFeatureLevel() == FeatureLevel::Compatibility;
}
bool DeviceBase::AllowUnsafeAPIs() const { bool DeviceBase::AllowUnsafeAPIs() const {
// TODO(dawn:1685) Currently allows if either toggle are set accordingly. // TODO(dawn:1685) Currently allows if either toggle are set accordingly.
return IsToggleEnabled(Toggle::AllowUnsafeAPIs) || !IsToggleEnabled(Toggle::DisallowUnsafeAPIs); return IsToggleEnabled(Toggle::AllowUnsafeAPIs) || !IsToggleEnabled(Toggle::DisallowUnsafeAPIs);

View File

@ -360,6 +360,7 @@ class DeviceBase : public RefCountedWithExternalCount {
bool IsToggleEnabled(Toggle toggle) const; bool IsToggleEnabled(Toggle toggle) const;
bool IsValidationEnabled() const; bool IsValidationEnabled() const;
bool IsRobustnessEnabled() const; bool IsRobustnessEnabled() const;
bool IsCompatibilityMode() const;
bool AllowUnsafeAPIs() const; bool AllowUnsafeAPIs() const;
size_t GetLazyClearCountForTesting(); size_t GetLazyClearCountForTesting();
void IncrementLazyClearCountForTesting(); void IncrementLazyClearCountForTesting();

View File

@ -20,6 +20,7 @@
#include "dawn/common/Assert.h" #include "dawn/common/Assert.h"
#include "dawn/common/Constants.h" #include "dawn/common/Constants.h"
#include "dawn/common/Math.h" #include "dawn/common/Math.h"
#include "dawn/native/Adapter.h"
#include "dawn/native/ChainUtils_autogen.h" #include "dawn/native/ChainUtils_autogen.h"
#include "dawn/native/Device.h" #include "dawn/native/Device.h"
#include "dawn/native/EnumMaskIterator.h" #include "dawn/native/EnumMaskIterator.h"
@ -178,7 +179,8 @@ MaybeError ValidateSampleCount(const TextureDescriptor* descriptor,
return {}; return {};
} }
MaybeError ValidateTextureViewDimensionCompatibility(const TextureBase* texture, MaybeError ValidateTextureViewDimensionCompatibility(const DeviceBase* device,
const TextureBase* texture,
const TextureViewDescriptor* descriptor) { const TextureViewDescriptor* descriptor) {
DAWN_INVALID_IF(!IsArrayLayerValidForTextureViewDimension(descriptor->dimension, DAWN_INVALID_IF(!IsArrayLayerValidForTextureViewDimension(descriptor->dimension,
descriptor->arrayLayerCount), descriptor->arrayLayerCount),
@ -207,8 +209,11 @@ MaybeError ValidateTextureViewDimensionCompatibility(const TextureBase* texture,
"(%u) and height (%u) are not equal.", "(%u) and height (%u) are not equal.",
descriptor->dimension, texture, texture->GetSize().width, descriptor->dimension, texture, texture->GetSize().width,
texture->GetSize().height); texture->GetSize().height);
DAWN_INVALID_IF(descriptor->dimension == wgpu::TextureViewDimension::CubeArray &&
device->IsCompatibilityMode(),
"A %s texture view for %s is not supported in compatibility mode",
descriptor->dimension, texture);
break; break;
case wgpu::TextureViewDimension::e1D: case wgpu::TextureViewDimension::e1D:
case wgpu::TextureViewDimension::e2D: case wgpu::TextureViewDimension::e2D:
case wgpu::TextureViewDimension::e2DArray: case wgpu::TextureViewDimension::e2DArray:
@ -436,7 +441,7 @@ MaybeError ValidateTextureViewDescriptor(const DeviceBase* device,
descriptor->baseMipLevel, descriptor->mipLevelCount, texture->GetNumMipLevels()); descriptor->baseMipLevel, descriptor->mipLevelCount, texture->GetNumMipLevels());
DAWN_TRY(ValidateCanViewTextureAs(device, texture, *viewFormat, descriptor->aspect)); DAWN_TRY(ValidateCanViewTextureAs(device, texture, *viewFormat, descriptor->aspect));
DAWN_TRY(ValidateTextureViewDimensionCompatibility(texture, descriptor)); DAWN_TRY(ValidateTextureViewDimensionCompatibility(device, texture, descriptor));
return {}; return {};
} }

View File

@ -327,6 +327,7 @@ dawn_test("dawn_unittests") {
"unittests/validation/BindGroupValidationTests.cpp", "unittests/validation/BindGroupValidationTests.cpp",
"unittests/validation/BufferValidationTests.cpp", "unittests/validation/BufferValidationTests.cpp",
"unittests/validation/CommandBufferValidationTests.cpp", "unittests/validation/CommandBufferValidationTests.cpp",
"unittests/validation/CompatValidationTests.cpp",
"unittests/validation/ComputeIndirectValidationTests.cpp", "unittests/validation/ComputeIndirectValidationTests.cpp",
"unittests/validation/ComputeValidationTests.cpp", "unittests/validation/ComputeValidationTests.cpp",
"unittests/validation/CopyCommandsValidationTests.cpp", "unittests/validation/CopyCommandsValidationTests.cpp",

View File

@ -21,6 +21,7 @@
#include <regex> #include <regex>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <tuple>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
@ -128,10 +129,13 @@ struct ParamTogglesHelper {
DawnTestBase::PrintToStringParamName::PrintToStringParamName(const char* test) : mTest(test) {} DawnTestBase::PrintToStringParamName::PrintToStringParamName(const char* test) : mTest(test) {}
std::string DawnTestBase::PrintToStringParamName::SanitizeParamName(std::string paramName, std::string DawnTestBase::PrintToStringParamName::SanitizeParamName(
size_t index) const { std::string paramName,
const wgpu::AdapterProperties& properties,
size_t index) const {
// Sanitize the adapter name for GoogleTest // Sanitize the adapter name for GoogleTest
std::string sanitizedName = std::regex_replace(paramName, std::regex("[^a-zA-Z0-9]+"), "_"); std::string sanitizedName = std::regex_replace(paramName, std::regex("[^a-zA-Z0-9]+"), "_") +
(properties.compatibilityMode ? "_compat" : "");
// Strip trailing underscores, if any. // Strip trailing underscores, if any.
while (sanitizedName.back() == '_') { while (sanitizedName.back() == '_') {
@ -437,11 +441,15 @@ void DawnTestEnvironment::SelectPreferredAdapterProperties(const dawn::native::I
} }
} }
std::set<std::pair<wgpu::BackendType, std::string>> adapterNameSet; std::set<std::tuple<wgpu::BackendType, std::string, bool>> adapterNameSet;
for (const dawn::native::Adapter& adapter : instance->GetAdapters()) { for (const dawn::native::Adapter& adapter : instance->GetAdapters()) {
wgpu::AdapterProperties properties; wgpu::AdapterProperties properties;
adapter.GetProperties(&properties); adapter.GetProperties(&properties);
if (properties.compatibilityMode) {
continue;
}
// All adapters are selected by default. // All adapters are selected by default.
bool selected = true; bool selected = true;
// The adapter is deselected if: // The adapter is deselected if:
@ -479,8 +487,8 @@ void DawnTestEnvironment::SelectPreferredAdapterProperties(const dawn::native::I
// In Windows Remote Desktop sessions we may be able to discover multiple adapters that // In Windows Remote Desktop sessions we may be able to discover multiple adapters that
// have the same name and backend type. We will just choose one adapter from them in our // have the same name and backend type. We will just choose one adapter from them in our
// tests. // tests.
const auto adapterTypeAndName = const auto adapterTypeAndName = std::tuple(
std::make_pair(properties.backendType, std::string(properties.name)); properties.backendType, std::string(properties.name), properties.compatibilityMode);
if (adapterNameSet.find(adapterTypeAndName) == adapterNameSet.end()) { if (adapterNameSet.find(adapterTypeAndName) == adapterNameSet.end()) {
adapterNameSet.insert(adapterTypeAndName); adapterNameSet.insert(adapterTypeAndName);
mAdapterProperties.emplace_back(properties, selected); mAdapterProperties.emplace_back(properties, selected);
@ -493,10 +501,11 @@ std::vector<AdapterTestParam> DawnTestEnvironment::GetAvailableAdapterTestParams
size_t numParams) { size_t numParams) {
std::vector<AdapterTestParam> testParams; std::vector<AdapterTestParam> testParams;
for (size_t i = 0; i < numParams; ++i) { for (size_t i = 0; i < numParams; ++i) {
const auto& backendTestParams = params[i];
for (const auto& adapterProperties : mAdapterProperties) { for (const auto& adapterProperties : mAdapterProperties) {
if (params[i].backendType == adapterProperties.backendType && if (backendTestParams.backendType == adapterProperties.backendType &&
adapterProperties.selected) { adapterProperties.selected) {
testParams.push_back(AdapterTestParam(params[i], adapterProperties)); testParams.push_back(AdapterTestParam(backendTestParams, adapterProperties));
} }
} }
} }
@ -590,7 +599,8 @@ void DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo(
<< properties.adapterName << "\" - \"" << properties.driverDescription << properties.adapterName << "\" - \"" << properties.driverDescription
<< (properties.selected ? " [Selected]" : "") << "\"\n" << (properties.selected ? " [Selected]" : "") << "\"\n"
<< " type: " << properties.AdapterTypeName() << " type: " << properties.AdapterTypeName()
<< ", backend: " << properties.ParamName() << "\n" << ", backend: " << properties.ParamName()
<< ", compatibilityMode: " << (properties.compatibilityMode ? "true" : "false") << "\n"
<< " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str() << "\n"; << " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str() << "\n";
if (strlen(properties.vendorName) || strlen(properties.architecture)) { if (strlen(properties.vendorName) || strlen(properties.architecture)) {
@ -684,6 +694,7 @@ DawnTestBase::DawnTestBase(const AdapterTestParam& param) : mParam(param) {
const auto& param = gCurrentTest->mParam; const auto& param = gCurrentTest->mParam;
return (param.adapterProperties.selected && return (param.adapterProperties.selected &&
properties.compatibilityMode == param.adapterProperties.compatibilityMode &&
properties.deviceID == param.adapterProperties.deviceID && properties.deviceID == param.adapterProperties.deviceID &&
properties.vendorID == param.adapterProperties.vendorID && properties.vendorID == param.adapterProperties.vendorID &&
properties.adapterType == param.adapterProperties.adapterType && properties.adapterType == param.adapterProperties.adapterType &&
@ -881,6 +892,10 @@ bool DawnTestBase::IsFullBackendValidationEnabled() const {
return gTestEnv->GetBackendValidationLevel() == dawn::native::BackendValidationLevel::Full; return gTestEnv->GetBackendValidationLevel() == dawn::native::BackendValidationLevel::Full;
} }
bool DawnTestBase::IsCompatibilityMode() const {
return mParam.adapterProperties.compatibilityMode;
}
bool DawnTestBase::RunSuppressedTests() const { bool DawnTestBase::RunSuppressedTests() const {
return gTestEnv->RunSuppressedTests(); return gTestEnv->RunSuppressedTests();
} }

View File

@ -258,6 +258,7 @@ class DawnTestBase {
bool IsImplicitDeviceSyncEnabled() const; bool IsImplicitDeviceSyncEnabled() const;
bool IsBackendValidationEnabled() const; bool IsBackendValidationEnabled() const;
bool IsFullBackendValidationEnabled() const; bool IsFullBackendValidationEnabled() const;
bool IsCompatibilityMode() const;
bool RunSuppressedTests() const; bool RunSuppressedTests() const;
bool IsDXC() const; bool IsDXC() const;
@ -283,11 +284,14 @@ class DawnTestBase {
struct PrintToStringParamName { struct PrintToStringParamName {
explicit PrintToStringParamName(const char* test); explicit PrintToStringParamName(const char* test);
std::string SanitizeParamName(std::string paramName, size_t index) const; std::string SanitizeParamName(std::string paramName,
const wgpu::AdapterProperties& properties,
size_t index) const;
template <class ParamType> template <class ParamType>
std::string operator()(const ::testing::TestParamInfo<ParamType>& info) const { std::string operator()(const ::testing::TestParamInfo<ParamType>& info) const {
return SanitizeParamName(::testing::PrintToStringParamName()(info), info.index); return SanitizeParamName(::testing::PrintToStringParamName()(info),
info.param.adapterProperties, info.index);
} }
std::string mTest; std::string mTest;

View File

@ -319,7 +319,7 @@ class TextureViewSamplingTest : public DawnTest {
uint32_t textureViewLayerCount, uint32_t textureViewLayerCount,
bool isCubeMapArray) { bool isCubeMapArray) {
// TODO(crbug.com/dawn/1300): OpenGLES does not support cube map arrays. // TODO(crbug.com/dawn/1300): OpenGLES does not support cube map arrays.
DAWN_TEST_UNSUPPORTED_IF(isCubeMapArray && IsOpenGLES()); DAWN_TEST_UNSUPPORTED_IF(isCubeMapArray && IsCompatibilityMode());
constexpr uint32_t kMipLevels = 1u; constexpr uint32_t kMipLevels = 1u;
InitTexture(textureArrayLayers, kMipLevels); InitTexture(textureArrayLayers, kMipLevels);

View File

@ -0,0 +1,58 @@
// Copyright 2023 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <limits>
#include <string>
#include "dawn/tests/unittests/validation/ValidationTest.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/WGPUHelpers.h"
namespace dawn {
namespace {
class CompatValidationTest : public ValidationTest {
protected:
bool UseCompatibilityMode() const override { return true; }
};
TEST_F(CompatValidationTest, CanNotCreateCubeArrayTextureView) {
wgpu::TextureDescriptor descriptor;
descriptor.size = {1, 1, 6};
descriptor.dimension = wgpu::TextureDimension::e2D;
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
descriptor.usage = wgpu::TextureUsage::TextureBinding;
wgpu::Texture cubeTexture = device.CreateTexture(&descriptor);
{
wgpu::TextureViewDescriptor cubeViewDescriptor;
cubeViewDescriptor.dimension = wgpu::TextureViewDimension::Cube;
cubeViewDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
cubeTexture.CreateView(&cubeViewDescriptor);
}
{
wgpu::TextureViewDescriptor cubeArrayViewDescriptor;
cubeArrayViewDescriptor.dimension = wgpu::TextureViewDimension::CubeArray;
cubeArrayViewDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
ASSERT_DEVICE_ERROR(cubeTexture.CreateView(&cubeArrayViewDescriptor));
}
cubeTexture.Destroy();
}
} // anonymous namespace
} // namespace dawn

View File

@ -99,10 +99,12 @@ ValidationTest::ValidationTest() {
wgpu::AdapterProperties adapterProperties; wgpu::AdapterProperties adapterProperties;
adapter.GetProperties(&adapterProperties); adapter.GetProperties(&adapterProperties);
if (adapterProperties.backendType == wgpu::BackendType::Null) { if (adapterProperties.backendType == wgpu::BackendType::Null &&
adapterProperties.compatibilityMode == gCurrentTest->UseCompatibilityMode()) {
gCurrentTest->mBackendAdapter = adapter; gCurrentTest->mBackendAdapter = adapter;
WGPUAdapter cAdapter = adapter.Get(); WGPUAdapter cAdapter = adapter.Get();
ASSERT(cAdapter); ASSERT(cAdapter);
dawn::native::GetProcs().adapterReference(cAdapter); dawn::native::GetProcs().adapterReference(cAdapter);
callback(WGPURequestAdapterStatus_Success, cAdapter, nullptr, userdata); callback(WGPURequestAdapterStatus_Success, cAdapter, nullptr, userdata);
return; return;
@ -153,9 +155,8 @@ void ValidationTest::SetUp() {
// RequestAdapter is overriden to ignore RequestAdapterOptions and always select the null // RequestAdapter is overriden to ignore RequestAdapterOptions and always select the null
// adapter. // adapter.
wgpu::RequestAdapterOptions options = {};
mInstance.RequestAdapter( mInstance.RequestAdapter(
&options, nullptr,
[](WGPURequestAdapterStatus, WGPUAdapter cAdapter, const char*, void* userdata) { [](WGPURequestAdapterStatus, WGPUAdapter cAdapter, const char*, void* userdata) {
*static_cast<wgpu::Adapter*>(userdata) = wgpu::Adapter::Acquire(cAdapter); *static_cast<wgpu::Adapter*>(userdata) = wgpu::Adapter::Acquire(cAdapter);
}, },
@ -311,6 +312,10 @@ WGPUDevice ValidationTest::CreateTestDevice(dawn::native::Adapter dawnAdapter,
return dawnAdapter.CreateDevice(&deviceDescriptor); return dawnAdapter.CreateDevice(&deviceDescriptor);
} }
bool ValidationTest::UseCompatibilityMode() const {
return false;
}
// 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

@ -140,6 +140,8 @@ class ValidationTest : public testing::Test {
wgpu::Device RequestDeviceSync(const wgpu::DeviceDescriptor& deviceDesc); wgpu::Device RequestDeviceSync(const wgpu::DeviceDescriptor& deviceDesc);
virtual bool UseCompatibilityMode() const;
wgpu::Device device; wgpu::Device device;
wgpu::Adapter adapter; wgpu::Adapter adapter;
WGPUDevice backendDevice; WGPUDevice backendDevice;