Support optional query on adapter power preference

This patch adds DawnAdapterPropertiesPowerPreferenceDescriptor for
querying adapter power preference which is useful to distinguish
different logical adapters created on same physical device but with
different power preferences.

Bug: dawn:1516
Test: dawn_unittests
Change-Id: I12ed6e370f8b57c860520154565765f0ee894831
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/102780
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Jiawei Shao 2022-09-23 00:29:46 +00:00 committed by Dawn LUCI CQ
parent 3354bf0d91
commit 5a0f8d32a2
5 changed files with 314 additions and 98 deletions

View File

@ -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"}
]
}
}

View File

@ -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<const {{as_cppEnum(value.name)}}*>(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<std::vector<{{namespace}}::SType>> 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}}

View File

@ -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<std::vector<{{namespace}}::SType>> oneOfConstraints);
MaybeError ValidateSTypes(const ChainedStructOut* chain,
std::vector<std::vector<{{namespace}}::SType>> oneOfConstraints);
template <typename T>
MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType) {
@ -48,6 +52,12 @@ namespace {{native_namespace}} {
"Unsupported sType (%s). Expected (%s)", chain->sType, sType);
return {};
}
template <typename T>
MaybeError ValidateSingleSTypeInner(const ChainedStructOut* chain, T sType) {
DAWN_INVALID_IF(chain->sType != sType,
"Unsupported sType (%s). Expected (%s)", chain->sType, sType);
return {};
}
template <typename T, typename... Args>
MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType, Args... sTypes) {
@ -56,6 +66,13 @@ namespace {{native_namespace}} {
}
return ValidateSingleSTypeInner(chain, sTypes...);
}
template <typename T, typename... Args>
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 <typename T>
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 <typename T, typename... Args>
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}}

View File

@ -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();

View File

@ -19,14 +19,26 @@
// 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::ChainedStruct* chained = nullptr;
dawn::native::FindInChain(chained, &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;
@ -39,8 +51,18 @@ TEST(ChainUtilsTests, FindPresentInChain) {
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;
@ -50,8 +72,18 @@ TEST(ChainUtilsTests, FindMissingInChain) {
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;
@ -63,8 +95,20 @@ TEST(ChainUtilsTests, ValidateDuplicateSTypes) {
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;
@ -80,6 +124,19 @@ TEST(ChainUtilsTests, ValidateUnspecifiedSTypes) {
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
// constraint.
TEST(ChainUtilsTests, ValidateOneOfFailure) {
@ -98,6 +155,7 @@ 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;
@ -112,32 +170,69 @@ TEST(ChainUtilsTests, ValidateSuccess) {
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) {
{
const dawn::native::ChainedStruct* chain = nullptr;
dawn::native::MaybeError result =
dawn::native::ValidateSTypes(nullptr, {
dawn::native::ValidateSTypes(chain, {
{wgpu::SType::ShaderModuleSPIRVDescriptor},
{wgpu::SType::PrimitiveDepthClipControl},
});
ASSERT_TRUE(result.IsSuccess());
result = dawn::native::ValidateSTypes(nullptr, {});
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) {
{
const dawn::native::ChainedStruct* chain = nullptr;
dawn::native::MaybeError result =
dawn::native::ValidateSingleSType(nullptr, wgpu::SType::ShaderModuleSPIRVDescriptor);
dawn::native::ValidateSingleSType(chain, wgpu::SType::ShaderModuleSPIRVDescriptor);
ASSERT_TRUE(result.IsSuccess());
result = dawn::native::ValidateSingleSType(nullptr, wgpu::SType::ShaderModuleSPIRVDescriptor,
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;
@ -153,15 +248,29 @@ TEST(ChainUtilsTests, ValidateSingleMultiChain) {
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 one of constraint is met.
TEST(ChainUtilsTests, ValidateSingleSatisfied) {
{
dawn::native::ShaderModuleWGSLDescriptor chain1;
dawn::native::MaybeError result =
dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleWGSLDescriptor);
ASSERT_TRUE(result.IsSuccess());
result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleSPIRVDescriptor,
result =
dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleSPIRVDescriptor,
wgpu::SType::ShaderModuleWGSLDescriptor);
ASSERT_TRUE(result.IsSuccess());
@ -170,8 +279,17 @@ TEST(ChainUtilsTests, ValidateSingleSatisfied) {
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::MaybeError result =
@ -179,8 +297,20 @@ TEST(ChainUtilsTests, ValidateSingleUnsatisfied) {
ASSERT_TRUE(result.IsError());
result.AcquireError();
result = dawn::native::ValidateSingleSType(&chain1, wgpu::SType::ShaderModuleSPIRVDescriptor,
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();
}
}