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:
parent
3354bf0d91
commit
5a0f8d32a2
12
dawn.json
12
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"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue