diff --git a/dawn.json b/dawn.json index d8f8a34436..dfe2afe847 100644 --- a/dawn.json +++ b/dawn.json @@ -2526,7 +2526,8 @@ {"value": 1002, "name": "dawn toggles device descriptor", "tags": ["dawn", "native"]}, {"value": 1003, "name": "dawn encoder internal usage descriptor", "tags": ["dawn"]}, {"value": 1004, "name": "dawn instance descriptor", "tags": ["dawn", "native"]}, - {"value": 1005, "name": "dawn cache device descriptor", "tags": ["dawn", "native"]} + {"value": 1005, "name": "dawn cache device descriptor", "tags": ["dawn", "native"]}, + {"value": 1006, "name": "dawn adapter properties power preference", "tags": ["dawn", "native"]} ] }, "texture": { @@ -2929,5 +2930,14 @@ "members": [ {"name": "use internal usages", "type": "bool", "default": "false"} ] + }, + "dawn adapter properties power preference": { + "category": "structure", + "chained": "out", + "chain roots": ["adapter properties"], + "tags": ["dawn"], + "members": [ + {"name": "power preference", "type": "power preference", "default": "undefined"} + ] } } diff --git a/generator/templates/dawn/native/ChainUtils.cpp b/generator/templates/dawn/native/ChainUtils.cpp index 71f932e0ea..95f5e43409 100644 --- a/generator/templates/dawn/native/ChainUtils.cpp +++ b/generator/templates/dawn/native/ChainUtils.cpp @@ -25,10 +25,12 @@ namespace {{native_namespace}} { {% set namespace = metadata.namespace %} {% for value in types["s type"].values %} {% if value.valid %} - void FindInChain(const ChainedStruct* chain, const {{as_cppEnum(value.name)}}** out) { + {% set const_qualifier = "const " if types[value.name.get()].chained == "in" else "" %} + {% set chained_struct_type = "ChainedStruct" if types[value.name.get()].chained == "in" else "ChainedStructOut" %} + void FindInChain({{const_qualifier}}{{chained_struct_type}}* chain, {{const_qualifier}}{{as_cppEnum(value.name)}}** out) { for (; chain; chain = chain->nextInChain) { if (chain->sType == {{namespace}}::SType::{{as_cppEnum(value.name)}}) { - *out = static_cast(chain); + *out = static_cast<{{const_qualifier}}{{as_cppEnum(value.name)}}*>(chain); break; } } @@ -62,4 +64,30 @@ MaybeError ValidateSTypes(const ChainedStruct* chain, return {}; } +MaybeError ValidateSTypes(const ChainedStructOut* chain, + std::vector> oneOfConstraints) { + std::unordered_set<{{namespace}}::SType> allSTypes; + for (; chain; chain = chain->nextInChain) { + DAWN_INVALID_IF(allSTypes.find(chain->sType) != allSTypes.end(), + "Extension chain has duplicate sType %s.", chain->sType); + allSTypes.insert(chain->sType); + } + + for (const auto& oneOfConstraint : oneOfConstraints) { + bool satisfied = false; + for ({{namespace}}::SType oneOfSType : oneOfConstraint) { + if (allSTypes.find(oneOfSType) != allSTypes.end()) { + DAWN_INVALID_IF(satisfied, + "sType %s is part of a group of exclusive sTypes that is already present.", + oneOfSType); + satisfied = true; + allSTypes.erase(oneOfSType); + } + } + } + + DAWN_INVALID_IF(!allSTypes.empty(), "Unsupported sType %s.", *allSTypes.begin()); + return {}; +} + } // namespace {{native_namespace}} diff --git a/generator/templates/dawn/native/ChainUtils.h b/generator/templates/dawn/native/ChainUtils.h index 3377220d44..3b5a926a7a 100644 --- a/generator/templates/dawn/native/ChainUtils.h +++ b/generator/templates/dawn/native/ChainUtils.h @@ -28,7 +28,9 @@ namespace {{native_namespace}} { {% for value in types["s type"].values %} {% if value.valid %} - void FindInChain(const ChainedStruct* chain, const {{as_cppEnum(value.name)}}** out); + {% set const_qualifier = "const " if types[value.name.get()].chained == "in" else "" %} + {% set chained_struct_type = "ChainedStruct" if types[value.name.get()].chained == "in" else "ChainedStructOut" %} + void FindInChain({{const_qualifier}}{{chained_struct_type}}* chain, {{const_qualifier}}{{as_cppEnum(value.name)}}** out); {% endif %} {% endfor %} @@ -41,6 +43,8 @@ namespace {{native_namespace}} { {% set namespace = metadata.namespace %} MaybeError ValidateSTypes(const ChainedStruct* chain, std::vector> oneOfConstraints); + MaybeError ValidateSTypes(const ChainedStructOut* chain, + std::vector> oneOfConstraints); template MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType) { @@ -48,6 +52,12 @@ namespace {{native_namespace}} { "Unsupported sType (%s). Expected (%s)", chain->sType, sType); return {}; } + template + MaybeError ValidateSingleSTypeInner(const ChainedStructOut* chain, T sType) { + DAWN_INVALID_IF(chain->sType != sType, + "Unsupported sType (%s). Expected (%s)", chain->sType, sType); + return {}; + } template MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType, Args... sTypes) { @@ -56,6 +66,13 @@ namespace {{native_namespace}} { } return ValidateSingleSTypeInner(chain, sTypes...); } + template + MaybeError ValidateSingleSTypeInner(const ChainedStructOut* chain, T sType, Args... sTypes) { + if (chain->sType == sType) { + return {}; + } + return ValidateSingleSTypeInner(chain, sTypes...); + } // Verifies that |chain| contains a single ChainedStruct of type |sType| or no ChainedStructs // at all. @@ -68,6 +85,15 @@ namespace {{native_namespace}} { "Chain can only contain a single chained struct."); return ValidateSingleSTypeInner(chain, sType); } + template + MaybeError ValidateSingleSType(const ChainedStructOut* chain, T sType) { + if (chain == nullptr) { + return {}; + } + DAWN_INVALID_IF(chain->nextInChain != nullptr, + "Chain can only contain a single chained struct."); + return ValidateSingleSTypeInner(chain, sType); + } // Verifies that |chain| contains a single ChainedStruct with a type enumerated in the // parameter pack or no ChainedStructs at all. @@ -80,6 +106,15 @@ namespace {{native_namespace}} { "Chain can only contain a single chained struct."); return ValidateSingleSTypeInner(chain, sType, sTypes...); } + template + MaybeError ValidateSingleSType(const ChainedStructOut* chain, T sType, Args... sTypes) { + if (chain == nullptr) { + return {}; + } + DAWN_INVALID_IF(chain->nextInChain != nullptr, + "Chain can only contain a single chained struct."); + return ValidateSingleSTypeInner(chain, sType, sTypes...); + } } // namespace {{native_namespace}} diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp index 0234e2c094..c3063866d8 100644 --- a/src/dawn/native/Adapter.cpp +++ b/src/dawn/native/Adapter.cpp @@ -86,6 +86,19 @@ bool AdapterBase::APIGetLimits(SupportedLimits* limits) const { } void AdapterBase::APIGetProperties(AdapterProperties* properties) const { + MaybeError result = ValidateSingleSType(properties->nextInChain, + wgpu::SType::DawnAdapterPropertiesPowerPreference); + if (result.IsError()) { + mInstance->ConsumedError(result.AcquireError()); + return; + } + + DawnAdapterPropertiesPowerPreference* powerPreferenceDesc = nullptr; + FindInChain(properties->nextInChain, &powerPreferenceDesc); + if (powerPreferenceDesc != nullptr) { + powerPreferenceDesc->powerPreference = wgpu::PowerPreference::Undefined; + } + properties->vendorID = mVendorId; properties->vendorName = mVendorName.c_str(); properties->architecture = mArchitectureName.c_str(); diff --git a/src/dawn/tests/unittests/ChainUtilsTests.cpp b/src/dawn/tests/unittests/ChainUtilsTests.cpp index c1bea5b9d6..45055f18bc 100644 --- a/src/dawn/tests/unittests/ChainUtilsTests.cpp +++ b/src/dawn/tests/unittests/ChainUtilsTests.cpp @@ -19,65 +19,122 @@ // Checks that we cannot find any structs in an empty chain TEST(ChainUtilsTests, FindEmptyChain) { - const dawn::native::PrimitiveDepthClipControl* info = nullptr; - dawn::native::FindInChain(nullptr, &info); + { + const dawn::native::PrimitiveDepthClipControl* info = nullptr; + const dawn::native::ChainedStruct* chained = nullptr; + dawn::native::FindInChain(chained, &info); - ASSERT_EQ(nullptr, info); + ASSERT_EQ(nullptr, info); + } + + { + dawn::native::DawnAdapterPropertiesPowerPreference* info = nullptr; + dawn::native::ChainedStructOut* chained = nullptr; + dawn::native::FindInChain(chained, &info); + + ASSERT_EQ(nullptr, info); + } } // Checks that searching a chain for a present struct returns that struct TEST(ChainUtilsTests, FindPresentInChain) { - dawn::native::PrimitiveDepthClipControl chain1; - dawn::native::ShaderModuleSPIRVDescriptor chain2; - chain1.nextInChain = &chain2; - const dawn::native::PrimitiveDepthClipControl* info1 = nullptr; - const dawn::native::ShaderModuleSPIRVDescriptor* info2 = nullptr; - dawn::native::FindInChain(&chain1, &info1); - dawn::native::FindInChain(&chain1, &info2); + { + dawn::native::PrimitiveDepthClipControl chain1; + dawn::native::ShaderModuleSPIRVDescriptor chain2; + chain1.nextInChain = &chain2; + const dawn::native::PrimitiveDepthClipControl* info1 = nullptr; + const dawn::native::ShaderModuleSPIRVDescriptor* info2 = nullptr; + dawn::native::FindInChain(&chain1, &info1); + dawn::native::FindInChain(&chain1, &info2); - ASSERT_NE(nullptr, info1); - ASSERT_NE(nullptr, info2); + ASSERT_NE(nullptr, info1); + ASSERT_NE(nullptr, info2); + } + + { + dawn::native::DawnAdapterPropertiesPowerPreference chain; + dawn::native::DawnAdapterPropertiesPowerPreference* output = nullptr; + dawn::native::FindInChain(&chain, &output); + + ASSERT_NE(nullptr, output); + } } // Checks that searching a chain for a struct that doesn't exist returns a nullptr TEST(ChainUtilsTests, FindMissingInChain) { - dawn::native::PrimitiveDepthClipControl chain1; - dawn::native::ShaderModuleSPIRVDescriptor chain2; - chain1.nextInChain = &chain2; - const dawn::native::SurfaceDescriptorFromMetalLayer* info = nullptr; - dawn::native::FindInChain(&chain1, &info); + { + dawn::native::PrimitiveDepthClipControl chain1; + dawn::native::ShaderModuleSPIRVDescriptor chain2; + chain1.nextInChain = &chain2; + const dawn::native::SurfaceDescriptorFromMetalLayer* info = nullptr; + dawn::native::FindInChain(&chain1, &info); - ASSERT_EQ(nullptr, info); + ASSERT_EQ(nullptr, info); + } + + { + dawn::native::AdapterProperties adapterProperties; + dawn::native::DawnAdapterPropertiesPowerPreference* output = nullptr; + dawn::native::FindInChain(adapterProperties.nextInChain, &output); + + ASSERT_EQ(nullptr, output); + } } // Checks that validation rejects chains with duplicate STypes TEST(ChainUtilsTests, ValidateDuplicateSTypes) { - dawn::native::PrimitiveDepthClipControl chain1; - dawn::native::ShaderModuleSPIRVDescriptor chain2; - dawn::native::PrimitiveDepthClipControl chain3; - chain1.nextInChain = &chain2; - chain2.nextInChain = &chain3; + { + dawn::native::PrimitiveDepthClipControl chain1; + dawn::native::ShaderModuleSPIRVDescriptor chain2; + dawn::native::PrimitiveDepthClipControl chain3; + chain1.nextInChain = &chain2; + chain2.nextInChain = &chain3; - dawn::native::MaybeError result = dawn::native::ValidateSTypes(&chain1, {}); - ASSERT_TRUE(result.IsError()); - result.AcquireError(); + dawn::native::MaybeError result = dawn::native::ValidateSTypes(&chain1, {}); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } + + { + dawn::native::DawnAdapterPropertiesPowerPreference chain1; + dawn::native::DawnAdapterPropertiesPowerPreference chain2; + chain1.nextInChain = &chain2; + + dawn::native::MaybeError result = dawn::native::ValidateSTypes(&chain1, {}); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } } // Checks that validation rejects chains that contain unspecified STypes TEST(ChainUtilsTests, ValidateUnspecifiedSTypes) { - dawn::native::PrimitiveDepthClipControl chain1; - dawn::native::ShaderModuleSPIRVDescriptor chain2; - dawn::native::ShaderModuleWGSLDescriptor chain3; - chain1.nextInChain = &chain2; - chain2.nextInChain = &chain3; + { + dawn::native::PrimitiveDepthClipControl chain1; + dawn::native::ShaderModuleSPIRVDescriptor chain2; + dawn::native::ShaderModuleWGSLDescriptor chain3; + chain1.nextInChain = &chain2; + chain2.nextInChain = &chain3; - dawn::native::MaybeError result = - dawn::native::ValidateSTypes(&chain1, { - {wgpu::SType::PrimitiveDepthClipControl}, - {wgpu::SType::ShaderModuleSPIRVDescriptor}, - }); - ASSERT_TRUE(result.IsError()); - result.AcquireError(); + dawn::native::MaybeError result = + dawn::native::ValidateSTypes(&chain1, { + {wgpu::SType::PrimitiveDepthClipControl}, + {wgpu::SType::ShaderModuleSPIRVDescriptor}, + }); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } + + { + dawn::native::DawnAdapterPropertiesPowerPreference chain1; + dawn::native::ChainedStructOut chain2; + chain2.sType = wgpu::SType::RenderPassDescriptorMaxDrawCount; + chain1.nextInChain = &chain2; + + dawn::native::MaybeError result = dawn::native::ValidateSTypes( + &chain1, {{wgpu::SType::DawnAdapterPropertiesPowerPreference}}); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } } // Checks that validation rejects chains that contain multiple STypes from the same oneof @@ -98,89 +155,162 @@ TEST(ChainUtilsTests, ValidateOneOfFailure) { // Checks that validation accepts chains that match the constraints. TEST(ChainUtilsTests, ValidateSuccess) { - dawn::native::PrimitiveDepthClipControl chain1; - dawn::native::ShaderModuleSPIRVDescriptor chain2; - chain1.nextInChain = &chain2; + { + dawn::native::PrimitiveDepthClipControl chain1; + dawn::native::ShaderModuleSPIRVDescriptor chain2; + chain1.nextInChain = &chain2; - dawn::native::MaybeError result = dawn::native::ValidateSTypes( - &chain1, - { - {wgpu::SType::ShaderModuleSPIRVDescriptor, wgpu::SType::ShaderModuleWGSLDescriptor}, - {wgpu::SType::PrimitiveDepthClipControl}, - {wgpu::SType::SurfaceDescriptorFromMetalLayer}, - }); - ASSERT_TRUE(result.IsSuccess()); + dawn::native::MaybeError result = dawn::native::ValidateSTypes( + &chain1, + { + {wgpu::SType::ShaderModuleSPIRVDescriptor, wgpu::SType::ShaderModuleWGSLDescriptor}, + {wgpu::SType::PrimitiveDepthClipControl}, + {wgpu::SType::SurfaceDescriptorFromMetalLayer}, + }); + ASSERT_TRUE(result.IsSuccess()); + } + + { + dawn::native::DawnAdapterPropertiesPowerPreference chain1; + dawn::native::MaybeError result = dawn::native::ValidateSTypes( + &chain1, {{wgpu::SType::DawnAdapterPropertiesPowerPreference}}); + ASSERT_TRUE(result.IsSuccess()); + } } // Checks that validation always passes on empty chains. TEST(ChainUtilsTests, ValidateEmptyChain) { - dawn::native::MaybeError result = - dawn::native::ValidateSTypes(nullptr, { - {wgpu::SType::ShaderModuleSPIRVDescriptor}, - {wgpu::SType::PrimitiveDepthClipControl}, - }); - ASSERT_TRUE(result.IsSuccess()); + { + const dawn::native::ChainedStruct* chain = nullptr; + dawn::native::MaybeError result = + dawn::native::ValidateSTypes(chain, { + {wgpu::SType::ShaderModuleSPIRVDescriptor}, + {wgpu::SType::PrimitiveDepthClipControl}, + }); + ASSERT_TRUE(result.IsSuccess()); - result = dawn::native::ValidateSTypes(nullptr, {}); - ASSERT_TRUE(result.IsSuccess()); + result = dawn::native::ValidateSTypes(chain, {}); + ASSERT_TRUE(result.IsSuccess()); + } + + { + dawn::native::ChainedStructOut* chain = nullptr; + dawn::native::MaybeError result = dawn::native::ValidateSTypes( + chain, {{wgpu::SType::DawnAdapterPropertiesPowerPreference}}); + ASSERT_TRUE(result.IsSuccess()); + + result = dawn::native::ValidateSTypes(chain, {}); + ASSERT_TRUE(result.IsSuccess()); + } } // Checks that singleton validation always passes on empty chains. TEST(ChainUtilsTests, ValidateSingleEmptyChain) { - dawn::native::MaybeError result = - dawn::native::ValidateSingleSType(nullptr, wgpu::SType::ShaderModuleSPIRVDescriptor); - ASSERT_TRUE(result.IsSuccess()); + { + const dawn::native::ChainedStruct* chain = nullptr; + dawn::native::MaybeError result = + dawn::native::ValidateSingleSType(chain, wgpu::SType::ShaderModuleSPIRVDescriptor); + ASSERT_TRUE(result.IsSuccess()); - result = dawn::native::ValidateSingleSType(nullptr, wgpu::SType::ShaderModuleSPIRVDescriptor, - wgpu::SType::PrimitiveDepthClipControl); - ASSERT_TRUE(result.IsSuccess()); + result = dawn::native::ValidateSingleSType(chain, wgpu::SType::ShaderModuleSPIRVDescriptor, + wgpu::SType::PrimitiveDepthClipControl); + ASSERT_TRUE(result.IsSuccess()); + } + + { + dawn::native::ChainedStructOut* chain = nullptr; + dawn::native::MaybeError result = dawn::native::ValidateSingleSType( + chain, wgpu::SType::DawnAdapterPropertiesPowerPreference); + ASSERT_TRUE(result.IsSuccess()); + + result = dawn::native::ValidateSingleSType( + chain, wgpu::SType::DawnAdapterPropertiesPowerPreference, + wgpu::SType::PrimitiveDepthClipControl); + ASSERT_TRUE(result.IsSuccess()); + } } // Checks that singleton validation always fails on chains with multiple children. TEST(ChainUtilsTests, ValidateSingleMultiChain) { - dawn::native::PrimitiveDepthClipControl chain1; - dawn::native::ShaderModuleSPIRVDescriptor chain2; - chain1.nextInChain = &chain2; + { + dawn::native::PrimitiveDepthClipControl chain1; + dawn::native::ShaderModuleSPIRVDescriptor chain2; + chain1.nextInChain = &chain2; - dawn::native::MaybeError result = - dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClipControl); - ASSERT_TRUE(result.IsError()); - result.AcquireError(); + dawn::native::MaybeError result = + dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClipControl); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); - result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClipControl, - wgpu::SType::ShaderModuleSPIRVDescriptor); - ASSERT_TRUE(result.IsError()); - result.AcquireError(); + result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::PrimitiveDepthClipControl, + wgpu::SType::ShaderModuleSPIRVDescriptor); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } + + { + dawn::native::DawnAdapterPropertiesPowerPreference chain1; + dawn::native::DawnAdapterPropertiesPowerPreference chain2; + chain1.nextInChain = &chain2; + + dawn::native::MaybeError result = dawn::native::ValidateSingleSType( + &chain1, wgpu::SType::DawnAdapterPropertiesPowerPreference); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } } -// Checks that singleton validation passes when the oneof constraint is met. +// Checks that singleton validation passes when the one of constraint is met. TEST(ChainUtilsTests, ValidateSingleSatisfied) { - dawn::native::ShaderModuleWGSLDescriptor chain1; + { + dawn::native::ShaderModuleWGSLDescriptor chain1; - dawn::native::MaybeError result = - dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor); - ASSERT_TRUE(result.IsSuccess()); + dawn::native::MaybeError result = + dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor); + ASSERT_TRUE(result.IsSuccess()); - result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleSPIRVDescriptor, - wgpu::SType::ShaderModuleWGSLDescriptor); - ASSERT_TRUE(result.IsSuccess()); + result = + dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleSPIRVDescriptor, + wgpu::SType::ShaderModuleWGSLDescriptor); + ASSERT_TRUE(result.IsSuccess()); - result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor, - wgpu::SType::ShaderModuleSPIRVDescriptor); - ASSERT_TRUE(result.IsSuccess()); + result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor, + wgpu::SType::ShaderModuleSPIRVDescriptor); + ASSERT_TRUE(result.IsSuccess()); + } + + { + dawn::native::DawnAdapterPropertiesPowerPreference chain1; + dawn::native::MaybeError result = dawn::native::ValidateSingleSType( + &chain1, wgpu::SType::DawnAdapterPropertiesPowerPreference); + ASSERT_TRUE(result.IsSuccess()); + } } // Checks that singleton validation passes when the oneof constraint is not met. TEST(ChainUtilsTests, ValidateSingleUnsatisfied) { - dawn::native::PrimitiveDepthClipControl chain1; + { + dawn::native::PrimitiveDepthClipControl chain1; - dawn::native::MaybeError result = - dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor); - ASSERT_TRUE(result.IsError()); - result.AcquireError(); + dawn::native::MaybeError result = + dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); - result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleSPIRVDescriptor, - wgpu::SType::ShaderModuleWGSLDescriptor); - ASSERT_TRUE(result.IsError()); - result.AcquireError(); + result = + dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleSPIRVDescriptor, + wgpu::SType::ShaderModuleWGSLDescriptor); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } + + { + dawn::native::ChainedStructOut chain1; + chain1.sType = wgpu::SType::ShaderModuleWGSLDescriptor; + + dawn::native::MaybeError result = dawn::native::ValidateSingleSType( + &chain1, wgpu::SType::DawnAdapterPropertiesPowerPreference); + ASSERT_TRUE(result.IsError()); + result.AcquireError(); + } }