Add feature queries to dawn_native/dawn_wire

This is so we can implement the adapter/device APIs fully
on dawn_wire.

Bug: dawn:689
Change-Id: I47f68157d081f359f871e0efe0d974dfe53de7d7
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/71521
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2021-12-15 00:12:30 +00:00 committed by Dawn LUCI CQ
parent fe1e929d5a
commit 89ddadcd1e
15 changed files with 130 additions and 17 deletions

View File

@ -97,6 +97,14 @@
{"name": "feature", "type": "feature name"}
]
},
{
"tags": ["dawn"],
"name": "enumerate features",
"returns": "uint32_t",
"args": [
{"name": "features", "type": "feature name", "annotation": "*"}
]
},
{
"name": "request device",
"args": [
@ -1057,6 +1065,22 @@
{"name": "limits", "type": "supported limits", "annotation": "*"}
]
},
{
"tags": ["dawn"],
"name": "has feature",
"returns": "bool",
"args": [
{"name": "feature", "type": "feature name"}
]
},
{
"tags": ["dawn"],
"name": "enumerate features",
"returns": "uint32_t",
"args": [
{"name": "features", "type": "feature name", "annotation": "*"}
]
},
{
"name": "get queue",
"returns": "queue"
@ -1297,7 +1321,10 @@
{"value": 7, "name": "texture compression ETC2"},
{"value": 8, "name": "texture compression ASTC"},
{"value": 9, "name": "indirect first instance"},
{"value": 1000, "name": "depth clamping", "tags": ["emscripten", "dawn"]}
{"value": 1000, "name": "depth clamping", "tags": ["emscripten", "dawn"]},
{"value": 1001, "name": "dawn shader float 16", "tags": ["dawn"]},
{"value": 1002, "name": "dawn internal usages", "tags": ["dawn"]},
{"value": 1003, "name": "dawn multi planar formats", "tags": ["dawn"]}
]
},
"filter mode": {

View File

@ -151,6 +151,7 @@
"AdapterGetProperties",
"AdapterGetLimits",
"AdapterHasFeature",
"AdapterEnumerateFeatures",
"AdapterRequestDevice",
"BufferMapAsync",
"BufferGetConstMappedRange",
@ -159,6 +160,8 @@
"DeviceCreateComputePipelineAsync",
"DeviceCreateRenderPipelineAsync",
"DeviceGetLimits",
"DeviceHasFeature",
"DeviceEnumerateFeatures",
"DevicePopErrorScope",
"DeviceSetDeviceLostCallback",
"DeviceSetUncapturedErrorCallback",

View File

@ -43,7 +43,7 @@ namespace dawn_native {
{% for arg in method.arguments %}
{% set varName = as_varName(arg.name) %}
{% if arg.type.category in ["enum", "bitmask"] %}
{% if arg.type.category in ["enum", "bitmask"] and arg.annotation == "value" %}
auto {{varName}}_ = static_cast<{{as_frontendType(arg.type)}}>({{varName}});
{% elif arg.annotation != "value" or arg.type.category == "object" %}
auto {{varName}}_ = reinterpret_cast<{{decorate("", as_frontendType(arg.type), arg)}}>({{varName}});

View File

@ -64,6 +64,8 @@ namespace dawn_wire { namespace client {
{% endif %}
{% for arg in method.arguments %}
//* Commands with mutable pointers should not be autogenerated.
{{assert(arg.annotation != "*")}}
cmd.{{as_varName(arg.name)}} = {{as_varName(arg.name)}};
{% endfor %}

View File

@ -86,6 +86,10 @@ namespace dawn_native {
return mSupportedFeatures.IsEnabled(feature);
}
uint32_t AdapterBase::APIEnumerateFeatures(wgpu::FeatureName* features) const {
return mSupportedFeatures.EnumerateFeatures(features);
}
void AdapterBase::APIRequestDevice(const DeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata) {

View File

@ -40,6 +40,7 @@ namespace dawn_native {
bool APIGetLimits(SupportedLimits* limits) const;
void APIGetProperties(AdapterProperties* properties) const;
bool APIHasFeature(wgpu::FeatureName feature) const;
uint32_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
void APIRequestDevice(const DeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata);

View File

@ -1197,7 +1197,7 @@ namespace dawn_native {
}
}
bool DeviceBase::APIGetLimits(SupportedLimits* limits) {
bool DeviceBase::APIGetLimits(SupportedLimits* limits) const {
ASSERT(limits != nullptr);
if (limits->nextInChain != nullptr) {
return false;
@ -1206,6 +1206,14 @@ namespace dawn_native {
return true;
}
bool DeviceBase::APIHasFeature(wgpu::FeatureName feature) const {
return mEnabledFeatures.IsEnabled(feature);
}
uint32_t DeviceBase::APIEnumerateFeatures(wgpu::FeatureName* features) const {
return mEnabledFeatures.EnumerateFeatures(features);
}
void DeviceBase::APIInjectError(wgpu::ErrorType type, const char* message) {
if (ConsumedError(ValidateErrorType(type))) {
return;

View File

@ -257,7 +257,9 @@ namespace dawn_native {
QueueBase* APIGetQueue();
bool APIGetLimits(SupportedLimits* limits);
bool APIGetLimits(SupportedLimits* limits) const;
bool APIHasFeature(wgpu::FeatureName feature) const;
uint32_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
void APIInjectError(wgpu::ErrorType type, const char* message);
bool APITick();

View File

@ -106,6 +106,12 @@ namespace dawn_native {
return Feature::Depth24UnormStencil8;
case wgpu::FeatureName::Depth32FloatStencil8:
return Feature::Depth32FloatStencil8;
case wgpu::FeatureName::DawnShaderFloat16:
return Feature::ShaderFloat16;
case wgpu::FeatureName::DawnInternalUsages:
return Feature::DawnInternalUsages;
case wgpu::FeatureName::DawnMultiPlanarFormats:
return Feature::MultiPlanarFormats;
case wgpu::FeatureName::IndirectFirstInstance:
return Feature::InvalidEnum;
@ -113,6 +119,36 @@ namespace dawn_native {
return Feature::InvalidEnum;
}
wgpu::FeatureName ToAPIFeature(Feature feature) {
switch (feature) {
case Feature::TextureCompressionBC:
return wgpu::FeatureName::TextureCompressionBC;
case Feature::TextureCompressionETC2:
return wgpu::FeatureName::TextureCompressionETC2;
case Feature::TextureCompressionASTC:
return wgpu::FeatureName::TextureCompressionASTC;
case Feature::PipelineStatisticsQuery:
return wgpu::FeatureName::PipelineStatisticsQuery;
case Feature::TimestampQuery:
return wgpu::FeatureName::TimestampQuery;
case Feature::DepthClamping:
return wgpu::FeatureName::DepthClamping;
case Feature::Depth24UnormStencil8:
return wgpu::FeatureName::Depth24UnormStencil8;
case Feature::Depth32FloatStencil8:
return wgpu::FeatureName::Depth32FloatStencil8;
case Feature::ShaderFloat16:
return wgpu::FeatureName::DawnShaderFloat16;
case Feature::DawnInternalUsages:
return wgpu::FeatureName::DawnInternalUsages;
case Feature::MultiPlanarFormats:
return wgpu::FeatureName::DawnMultiPlanarFormats;
case Feature::EnumCount:
UNREACHABLE();
}
}
} // anonymous namespace
void FeaturesSet::EnableFeature(Feature feature) {
@ -132,6 +168,17 @@ namespace dawn_native {
return f != Feature::InvalidEnum && IsEnabled(f);
}
uint32_t FeaturesSet::EnumerateFeatures(wgpu::FeatureName* features) const {
for (uint32_t i : IterateBitSet(featuresBitSet)) {
wgpu::FeatureName feature = ToAPIFeature(static_cast<Feature>(i));
if (features != nullptr) {
*features = feature;
features += 1;
}
}
return featuresBitSet.count();
}
std::vector<const char*> FeaturesSet::GetEnabledFeatureNames() const {
std::vector<const char*> enabledFeatureNames(featuresBitSet.count());

View File

@ -19,6 +19,7 @@
#include <unordered_map>
#include <vector>
#include "common/ityp_bitset.h"
#include "dawn/webgpu_cpp.h"
#include "dawn_native/DawnNative.h"
@ -52,6 +53,9 @@ namespace dawn_native {
void EnableFeature(Feature feature);
bool IsEnabled(Feature feature) const;
bool IsEnabled(wgpu::FeatureName feature) const;
// Returns |count|, the number of features. Writes out all |count| values if |features| is
// non-null.
uint32_t EnumerateFeatures(wgpu::FeatureName* features) const;
std::vector<const char*> GetEnabledFeatureNames() const;
void InitializeDeviceProperties(WGPUDeviceProperties* properties) const;
};

View File

@ -28,6 +28,10 @@ namespace dawn_wire { namespace client {
UNREACHABLE();
}
uint32_t Adapter::EnumerateFeatures(WGPUFeatureName* features) const {
UNREACHABLE();
}
void Adapter::RequestDevice(const WGPUDeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata) {

View File

@ -29,6 +29,7 @@ namespace dawn_wire { namespace client {
bool GetLimits(WGPUSupportedLimits* limits) const;
void GetProperties(WGPUAdapterProperties* properties) const;
bool HasFeature(WGPUFeatureName feature) const;
uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
void RequestDevice(const WGPUDeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata);

View File

@ -196,12 +196,20 @@ namespace dawn_wire { namespace client {
return Buffer::CreateError(this);
}
bool Device::GetLimits(WGPUSupportedLimits* limits) {
bool Device::GetLimits(WGPUSupportedLimits* limits) const {
// Not implemented in the wire.
UNREACHABLE();
return false;
}
bool Device::HasFeature(WGPUFeatureName feature) const {
UNREACHABLE();
}
uint32_t Device::EnumerateFeatures(WGPUFeatureName* features) const {
UNREACHABLE();
}
WGPUQueue Device::GetQueue() {
// The queue is lazily created because if a Device is created by
// Reserve/Inject, we cannot send the GetQueue message until

View File

@ -64,7 +64,9 @@ namespace dawn_wire { namespace client {
WGPUCreatePipelineAsyncStatus status,
const char* message);
bool GetLimits(WGPUSupportedLimits* limits);
bool GetLimits(WGPUSupportedLimits* limits) const;
bool HasFeature(WGPUFeatureName feature) const;
uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
WGPUQueue GetQueue();
void CancelCallbacksForDisconnect() override;

View File

@ -36,13 +36,14 @@ namespace {
WGPUInstance serverInstance = api.GetNewInstance();
EXPECT_CALL(api, InstanceReference(serverInstance));
ASSERT_TRUE(
GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
reservation.generation));
WGPUSurfaceDescriptor surfaceDesc = {};
wgpuInstanceCreateSurface(reservation.instance, &surfaceDesc);
WGPUSurface serverSurface = api.GetNewSurface();
EXPECT_CALL(api, InstanceCreateSurface(serverInstance, NotNull())).WillOnce(Return(serverSurface));
EXPECT_CALL(api, InstanceCreateSurface(serverInstance, NotNull()))
.WillOnce(Return(serverSurface));
FlushClient();
}
@ -55,19 +56,18 @@ namespace {
ASSERT_NE(reservation1.instance, reservation2.instance);
}
// Test that injecting the same id fails.
TEST_F(WireInjectInstanceTests, InjectExistingID) {
ReservedInstance reservation = GetWireClient()->ReserveInstance();
WGPUInstance serverInstance = api.GetNewInstance();
EXPECT_CALL(api, InstanceReference(serverInstance));
ASSERT_TRUE(
GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
reservation.generation));
// ID already in use, call fails.
ASSERT_FALSE(
GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
ASSERT_FALSE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
reservation.generation));
}
// Test that the server only borrows the instance and does a single reference-release
@ -77,8 +77,8 @@ namespace {
// Injecting the instance adds a reference
WGPUInstance serverInstance = api.GetNewInstance();
EXPECT_CALL(api, InstanceReference(serverInstance));
ASSERT_TRUE(
GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
reservation.generation));
// Releasing the instance removes a single reference.
wgpuInstanceRelease(reservation.instance);