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:
parent
fe1e929d5a
commit
89ddadcd1e
29
dawn.json
29
dawn.json
|
@ -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": {
|
||||
|
|
|
@ -151,6 +151,7 @@
|
|||
"AdapterGetProperties",
|
||||
"AdapterGetLimits",
|
||||
"AdapterHasFeature",
|
||||
"AdapterEnumerateFeatures",
|
||||
"AdapterRequestDevice",
|
||||
"BufferMapAsync",
|
||||
"BufferGetConstMappedRange",
|
||||
|
@ -159,6 +160,8 @@
|
|||
"DeviceCreateComputePipelineAsync",
|
||||
"DeviceCreateRenderPipelineAsync",
|
||||
"DeviceGetLimits",
|
||||
"DeviceHasFeature",
|
||||
"DeviceEnumerateFeatures",
|
||||
"DevicePopErrorScope",
|
||||
"DeviceSetDeviceLostCallback",
|
||||
"DeviceSetUncapturedErrorCallback",
|
||||
|
|
|
@ -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}});
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -23,7 +23,7 @@ using namespace dawn_wire;
|
|||
namespace {
|
||||
|
||||
class WireInjectInstanceTests : public WireTest {
|
||||
public:
|
||||
public:
|
||||
WireInjectInstanceTests() {
|
||||
}
|
||||
~WireInjectInstanceTests() override = default;
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue