Add Device::GetSupportedSurfaceUsage() method.
This method will return supported usage flags that can be used to create a swap chain. Bug: dawn:1760 Change-Id: I7699c2c4ef7142c6bd06e72239d6e4f9112f15a3 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/127440 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Quyen Le <lehoangquyen@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
7eb37948ab
commit
335573116c
10
dawn.json
10
dawn.json
|
@ -1251,6 +1251,13 @@
|
||||||
"args": [
|
"args": [
|
||||||
{"name": "descriptor", "type": "texture descriptor", "annotation": "const*"}
|
{"name": "descriptor", "type": "texture descriptor", "annotation": "const*"}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "get supported surface usage",
|
||||||
|
"returns": "texture usage",
|
||||||
|
"args": [
|
||||||
|
{"name": "surface", "type": "surface"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1467,7 +1474,8 @@
|
||||||
{"value": 1004, "name": "dawn native", "tags": ["dawn", "native"]},
|
{"value": 1004, "name": "dawn native", "tags": ["dawn", "native"]},
|
||||||
{"value": 1005, "name": "chromium experimental dp4a", "tags": ["dawn"]},
|
{"value": 1005, "name": "chromium experimental dp4a", "tags": ["dawn"]},
|
||||||
{"value": 1006, "name": "timestamp query inside passes", "tags": ["dawn"]},
|
{"value": 1006, "name": "timestamp query inside passes", "tags": ["dawn"]},
|
||||||
{"value": 1007, "name": "implicit device synchronization", "tags": ["dawn", "native"]}
|
{"value": 1007, "name": "implicit device synchronization", "tags": ["dawn", "native"]},
|
||||||
|
{"value": 1008, "name": "surface capabilities", "tags": ["dawn", "native"]}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filter mode": {
|
"filter mode": {
|
||||||
|
|
|
@ -228,6 +228,7 @@
|
||||||
"DeviceCreateErrorTexture",
|
"DeviceCreateErrorTexture",
|
||||||
"DeviceGetAdapter",
|
"DeviceGetAdapter",
|
||||||
"DeviceGetQueue",
|
"DeviceGetQueue",
|
||||||
|
"DeviceGetSupportedSurfaceUsage",
|
||||||
"DeviceInjectError"
|
"DeviceInjectError"
|
||||||
],
|
],
|
||||||
"client_special_objects": [
|
"client_special_objects": [
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Surface Capabilities
|
||||||
|
|
||||||
|
The `surface-capabilities` feature allows querying a surface's capabilities and creating a swap chain with additional usage flags.
|
||||||
|
|
||||||
|
Additional functionality:
|
||||||
|
- Adds `wgpu::Device::GetSupportedSurfaceUsage(wgpu::Surface)` method for querying the surface's supported usage flags. One or the combination of these flags can be used to create a swap chain.
|
||||||
|
|
||||||
|
Example Usage:
|
||||||
|
```
|
||||||
|
wgpu::TextureUsage supportedUsage = device.GetSupportedSurfaceUsage(surface);
|
||||||
|
|
||||||
|
wgpu::SwapChainDescriptor desc = {};
|
||||||
|
// set usage flags.
|
||||||
|
desc.usage = supportedUsage;
|
||||||
|
|
||||||
|
device.CreateSwapChain(surface, &desc);
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- If this feature is not enabled, only `wgpu::TextureUsage::RenderAttachment` flag is allowed to be used in `wgpu::SwapChainDescriptor::usage`.
|
|
@ -1242,6 +1242,15 @@ TextureBase* DeviceBase::APICreateTexture(const TextureDescriptor* descriptor) {
|
||||||
return result.Detach();
|
return result.Detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wgpu::TextureUsage DeviceBase::APIGetSupportedSurfaceUsage(Surface* surface) {
|
||||||
|
wgpu::TextureUsage result;
|
||||||
|
if (ConsumedError(GetSupportedSurfaceUsage(surface), &result,
|
||||||
|
"calling %s.GetSupportedSurfaceUsage().", this)) {
|
||||||
|
return wgpu::TextureUsage::None;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// For Dawn Wire
|
// For Dawn Wire
|
||||||
|
|
||||||
BufferBase* DeviceBase::APICreateErrorBuffer(const BufferDescriptor* desc) {
|
BufferBase* DeviceBase::APICreateErrorBuffer(const BufferDescriptor* desc) {
|
||||||
|
@ -1814,6 +1823,18 @@ ResultOrError<Ref<TextureViewBase>> DeviceBase::CreateTextureView(
|
||||||
return CreateTextureViewImpl(texture, &desc);
|
return CreateTextureViewImpl(texture, &desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> DeviceBase::GetSupportedSurfaceUsage(
|
||||||
|
const Surface* surface) const {
|
||||||
|
DAWN_TRY(ValidateIsAlive());
|
||||||
|
|
||||||
|
if (IsValidationEnabled()) {
|
||||||
|
DAWN_INVALID_IF(!HasFeature(Feature::SurfaceCapabilities), "%s is not enabled.",
|
||||||
|
wgpu::FeatureName::SurfaceCapabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetSupportedSurfaceUsageImpl(surface);
|
||||||
|
}
|
||||||
|
|
||||||
// Other implementation details
|
// Other implementation details
|
||||||
|
|
||||||
DynamicUploader* DeviceBase::GetDynamicUploader() const {
|
DynamicUploader* DeviceBase::GetDynamicUploader() const {
|
||||||
|
|
|
@ -261,6 +261,8 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
ResultOrError<Ref<TextureViewBase>> CreateTextureView(TextureBase* texture,
|
ResultOrError<Ref<TextureViewBase>> CreateTextureView(TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor);
|
const TextureViewDescriptor* descriptor);
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsage(const Surface* surface) const;
|
||||||
|
|
||||||
// Implementation of API object creation methods. DO NOT use them in a reentrant manner.
|
// Implementation of API object creation methods. DO NOT use them in a reentrant manner.
|
||||||
BindGroupBase* APICreateBindGroup(const BindGroupDescriptor* descriptor);
|
BindGroupBase* APICreateBindGroup(const BindGroupDescriptor* descriptor);
|
||||||
BindGroupLayoutBase* APICreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
|
BindGroupLayoutBase* APICreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
|
||||||
|
@ -284,6 +286,8 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
SwapChainBase* APICreateSwapChain(Surface* surface, const SwapChainDescriptor* descriptor);
|
SwapChainBase* APICreateSwapChain(Surface* surface, const SwapChainDescriptor* descriptor);
|
||||||
TextureBase* APICreateTexture(const TextureDescriptor* descriptor);
|
TextureBase* APICreateTexture(const TextureDescriptor* descriptor);
|
||||||
|
|
||||||
|
wgpu::TextureUsage APIGetSupportedSurfaceUsage(Surface* surface);
|
||||||
|
|
||||||
InternalPipelineStore* GetInternalPipelineStore();
|
InternalPipelineStore* GetInternalPipelineStore();
|
||||||
|
|
||||||
// For Dawn Wire
|
// For Dawn Wire
|
||||||
|
@ -492,6 +496,9 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
const RenderPipelineDescriptor* descriptor) = 0;
|
const RenderPipelineDescriptor* descriptor) = 0;
|
||||||
virtual void SetLabelImpl();
|
virtual void SetLabelImpl();
|
||||||
|
|
||||||
|
virtual ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const = 0;
|
||||||
|
|
||||||
virtual MaybeError TickImpl() = 0;
|
virtual MaybeError TickImpl() = 0;
|
||||||
void FlushCallbackTaskQueue();
|
void FlushCallbackTaskQueue();
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,11 @@ static constexpr FeatureEnumAndInfoList kFeatureNameAndInfoList = {{
|
||||||
"Public API methods (except encoding) will have implicit device synchronization. So they "
|
"Public API methods (except encoding) will have implicit device synchronization. So they "
|
||||||
"will be safe to be used on multiple threads.",
|
"will be safe to be used on multiple threads.",
|
||||||
"https://bugs.chromium.org/p/dawn/issues/detail?id=1662", FeatureInfo::FeatureState::Stable}},
|
"https://bugs.chromium.org/p/dawn/issues/detail?id=1662", FeatureInfo::FeatureState::Stable}},
|
||||||
|
{Feature::SurfaceCapabilities,
|
||||||
|
{"surface-capabilities",
|
||||||
|
"Support querying Surface's capabilities such as supported usage flags. This feature also "
|
||||||
|
"enables swap chain to be created with usage other than RenderAttachment.",
|
||||||
|
"https://bugs.chromium.org/p/dawn/issues/detail?id=1760", FeatureInfo::FeatureState::Stable}},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
Feature FromAPIFeature(wgpu::FeatureName feature) {
|
Feature FromAPIFeature(wgpu::FeatureName feature) {
|
||||||
|
@ -146,6 +151,8 @@ Feature FromAPIFeature(wgpu::FeatureName feature) {
|
||||||
return Feature::BGRA8UnormStorage;
|
return Feature::BGRA8UnormStorage;
|
||||||
case wgpu::FeatureName::ImplicitDeviceSynchronization:
|
case wgpu::FeatureName::ImplicitDeviceSynchronization:
|
||||||
return Feature::ImplicitDeviceSynchronization;
|
return Feature::ImplicitDeviceSynchronization;
|
||||||
|
case wgpu::FeatureName::SurfaceCapabilities:
|
||||||
|
return Feature::SurfaceCapabilities;
|
||||||
}
|
}
|
||||||
return Feature::InvalidEnum;
|
return Feature::InvalidEnum;
|
||||||
}
|
}
|
||||||
|
@ -186,6 +193,8 @@ wgpu::FeatureName ToAPIFeature(Feature feature) {
|
||||||
return wgpu::FeatureName::BGRA8UnormStorage;
|
return wgpu::FeatureName::BGRA8UnormStorage;
|
||||||
case Feature::ImplicitDeviceSynchronization:
|
case Feature::ImplicitDeviceSynchronization:
|
||||||
return wgpu::FeatureName::ImplicitDeviceSynchronization;
|
return wgpu::FeatureName::ImplicitDeviceSynchronization;
|
||||||
|
case Feature::SurfaceCapabilities:
|
||||||
|
return wgpu::FeatureName::SurfaceCapabilities;
|
||||||
|
|
||||||
case Feature::EnumCount:
|
case Feature::EnumCount:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -46,6 +46,7 @@ enum class Feature {
|
||||||
MultiPlanarFormats,
|
MultiPlanarFormats,
|
||||||
DawnNative,
|
DawnNative,
|
||||||
ImplicitDeviceSynchronization,
|
ImplicitDeviceSynchronization,
|
||||||
|
SurfaceCapabilities,
|
||||||
|
|
||||||
EnumCount,
|
EnumCount,
|
||||||
InvalidEnum = EnumCount,
|
InvalidEnum = EnumCount,
|
||||||
|
|
|
@ -57,9 +57,20 @@ MaybeError ValidateSwapChainDescriptor(const DeviceBase* device,
|
||||||
"Format (%s) is not %s, which is (currently) the only accepted format.",
|
"Format (%s) is not %s, which is (currently) the only accepted format.",
|
||||||
descriptor->format, kRequireSwapChainFormat);
|
descriptor->format, kRequireSwapChainFormat);
|
||||||
|
|
||||||
|
if (device->HasFeature(Feature::SurfaceCapabilities)) {
|
||||||
|
wgpu::TextureUsage validUsage;
|
||||||
|
DAWN_TRY_ASSIGN(validUsage, device->GetSupportedSurfaceUsage(surface));
|
||||||
|
DAWN_INVALID_IF(
|
||||||
|
(descriptor->usage | validUsage) != validUsage,
|
||||||
|
"Usage (%s) is not supported, %s are (currently) the only accepted usage flags.",
|
||||||
|
descriptor->usage, validUsage);
|
||||||
|
} else {
|
||||||
DAWN_INVALID_IF(descriptor->usage != wgpu::TextureUsage::RenderAttachment,
|
DAWN_INVALID_IF(descriptor->usage != wgpu::TextureUsage::RenderAttachment,
|
||||||
"Usage (%s) is not %s, which is (currently) the only accepted usage.",
|
"Usage (%s) is not %s, which is (currently) the only accepted usage. Other "
|
||||||
descriptor->usage, wgpu::TextureUsage::RenderAttachment);
|
"usage flags require enabling %s",
|
||||||
|
descriptor->usage, wgpu::TextureUsage::RenderAttachment,
|
||||||
|
wgpu::FeatureName::SurfaceCapabilities);
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INVALID_IF(descriptor->width == 0 || descriptor->height == 0,
|
DAWN_INVALID_IF(descriptor->width == 0 || descriptor->height == 0,
|
||||||
"Swap Chain size (width: %u, height: %u) is empty.", descriptor->width,
|
"Swap Chain size (width: %u, height: %u) is empty.", descriptor->width,
|
||||||
|
|
|
@ -27,6 +27,13 @@ Device::Device(AdapterBase* adapter,
|
||||||
|
|
||||||
Device::~Device() = default;
|
Device::~Device() = default;
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const {
|
||||||
|
wgpu::TextureUsage usages =
|
||||||
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
|
||||||
|
return usages;
|
||||||
|
}
|
||||||
|
|
||||||
const PlatformFunctions* Device::GetFunctions() const {
|
const PlatformFunctions* Device::GetFunctions() const {
|
||||||
return ToBackend(GetAdapter())->GetBackend()->GetFunctions();
|
return ToBackend(GetAdapter())->GetBackend()->GetFunctions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ class Device : public DeviceBase {
|
||||||
const TogglesState& deviceToggles);
|
const TogglesState& deviceToggles);
|
||||||
~Device() override;
|
~Device() override;
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const override;
|
||||||
|
|
||||||
const PlatformFunctions* GetFunctions() const;
|
const PlatformFunctions* GetFunctions() const;
|
||||||
ComPtr<IDXGIFactory4> GetFactory() const;
|
ComPtr<IDXGIFactory4> GetFactory() const;
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ MaybeError Adapter::InitializeImpl() {
|
||||||
|
|
||||||
void Adapter::InitializeSupportedFeaturesImpl() {
|
void Adapter::InitializeSupportedFeaturesImpl() {
|
||||||
EnableFeature(Feature::TextureCompressionBC);
|
EnableFeature(Feature::TextureCompressionBC);
|
||||||
|
EnableFeature(Feature::SurfaceCapabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
|
MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
|
||||||
|
|
|
@ -121,6 +121,7 @@ void Adapter::InitializeSupportedFeaturesImpl() {
|
||||||
EnableFeature(Feature::IndirectFirstInstance);
|
EnableFeature(Feature::IndirectFirstInstance);
|
||||||
EnableFeature(Feature::RG11B10UfloatRenderable);
|
EnableFeature(Feature::RG11B10UfloatRenderable);
|
||||||
EnableFeature(Feature::DepthClipControl);
|
EnableFeature(Feature::DepthClipControl);
|
||||||
|
EnableFeature(Feature::SurfaceCapabilities);
|
||||||
|
|
||||||
if (AreTimestampQueriesSupported()) {
|
if (AreTimestampQueriesSupported()) {
|
||||||
EnableFeature(Feature::TimestampQuery);
|
EnableFeature(Feature::TimestampQuery);
|
||||||
|
|
|
@ -517,6 +517,7 @@ class Adapter : public AdapterBase {
|
||||||
EnableFeature(Feature::ShaderF16);
|
EnableFeature(Feature::ShaderF16);
|
||||||
EnableFeature(Feature::RG11B10UfloatRenderable);
|
EnableFeature(Feature::RG11B10UfloatRenderable);
|
||||||
EnableFeature(Feature::BGRA8UnormStorage);
|
EnableFeature(Feature::BGRA8UnormStorage);
|
||||||
|
EnableFeature(Feature::SurfaceCapabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeVendorArchitectureImpl() override {
|
void InitializeVendorArchitectureImpl() override {
|
||||||
|
|
|
@ -130,6 +130,9 @@ class Device final : public DeviceBase {
|
||||||
WGPUCreateRenderPipelineAsyncCallback callback,
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
void* userdata) override;
|
void* userdata) override;
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const override;
|
||||||
|
|
||||||
void DestroyImpl() override;
|
void DestroyImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
bool HasPendingCommands() const override;
|
bool HasPendingCommands() const override;
|
||||||
|
|
|
@ -240,6 +240,13 @@ void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPip
|
||||||
RenderPipeline::InitializeAsync(std::move(renderPipeline), callback, userdata);
|
RenderPipeline::InitializeAsync(std::move(renderPipeline), callback, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const {
|
||||||
|
wgpu::TextureUsage usages =
|
||||||
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
|
||||||
|
return usages;
|
||||||
|
}
|
||||||
|
|
||||||
ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() {
|
ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() {
|
||||||
uint64_t frontendCompletedSerial{GetCompletedCommandSerial()};
|
uint64_t frontendCompletedSerial{GetCompletedCommandSerial()};
|
||||||
// sometimes we increase the serials, in which case the completed serial in
|
// sometimes we increase the serials, in which case the completed serial in
|
||||||
|
|
|
@ -188,6 +188,11 @@ ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
|
||||||
return AcquireRef(new TextureView(texture, descriptor));
|
return AcquireRef(new TextureView(texture, descriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const {
|
||||||
|
return wgpu::TextureUsage::RenderAttachment;
|
||||||
|
}
|
||||||
|
|
||||||
void Device::DestroyImpl() {
|
void Device::DestroyImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,9 @@ class Device final : public DeviceBase {
|
||||||
TextureBase* texture,
|
TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor) override;
|
const TextureViewDescriptor* descriptor) override;
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const override;
|
||||||
|
|
||||||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
void DestroyImpl() override;
|
void DestroyImpl() override;
|
||||||
|
|
|
@ -253,6 +253,13 @@ ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
|
||||||
return AcquireRef(new TextureView(texture, descriptor));
|
return AcquireRef(new TextureView(texture, descriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const {
|
||||||
|
wgpu::TextureUsage usages =
|
||||||
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
|
||||||
|
return usages;
|
||||||
|
}
|
||||||
|
|
||||||
void Device::SubmitFenceSync() {
|
void Device::SubmitFenceSync() {
|
||||||
if (!mHasPendingCommands) {
|
if (!mHasPendingCommands) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -125,6 +125,9 @@ class Device final : public DeviceBase {
|
||||||
Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
|
Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
|
||||||
const RenderPipelineDescriptor* descriptor) override;
|
const RenderPipelineDescriptor* descriptor) override;
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const override;
|
||||||
|
|
||||||
GLenum GetBGRAInternalFormat() const;
|
GLenum GetBGRAInternalFormat() const;
|
||||||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||||
void DestroyImpl() override;
|
void DestroyImpl() override;
|
||||||
|
|
|
@ -263,6 +263,8 @@ void Adapter::InitializeSupportedFeaturesImpl() {
|
||||||
// features.
|
// features.
|
||||||
EnableFeature(Feature::MultiPlanarFormats);
|
EnableFeature(Feature::MultiPlanarFormats);
|
||||||
#endif // DAWN_PLATFORM_IS(ANDROID) || DAWN_PLATFORM_IS(CHROMEOS)
|
#endif // DAWN_PLATFORM_IS(ANDROID) || DAWN_PLATFORM_IS(CHROMEOS)
|
||||||
|
|
||||||
|
EnableFeature(Feature::SurfaceCapabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
|
MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
|
||||||
|
|
|
@ -217,6 +217,11 @@ void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPip
|
||||||
RenderPipeline::InitializeAsync(std::move(renderPipeline), callback, userdata);
|
RenderPipeline::InitializeAsync(std::move(renderPipeline), callback, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const {
|
||||||
|
return SwapChain::GetSupportedSurfaceUsage(this, surface);
|
||||||
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
RecycleCompletedCommands();
|
RecycleCompletedCommands();
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,9 @@ class Device final : public DeviceBase {
|
||||||
WGPUCreateRenderPipelineAsyncCallback callback,
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
void* userdata) override;
|
void* userdata) override;
|
||||||
|
|
||||||
|
ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsageImpl(
|
||||||
|
const Surface* surface) const override;
|
||||||
|
|
||||||
ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice);
|
ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice);
|
||||||
void GatherQueueFromDevice();
|
void GatherQueueFromDevice();
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace dawn::native::vulkan {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
ResultOrError<VkSurfaceKHR> CreateVulkanSurface(Adapter* adapter, Surface* surface) {
|
ResultOrError<VkSurfaceKHR> CreateVulkanSurface(const Adapter* adapter, const Surface* surface) {
|
||||||
const VulkanGlobalInfo& info = adapter->GetVulkanInstance()->GetGlobalInfo();
|
const VulkanGlobalInfo& info = adapter->GetVulkanInstance()->GetGlobalInfo();
|
||||||
const VulkanFunctions& fn = adapter->GetVulkanInstance()->GetFunctions();
|
const VulkanFunctions& fn = adapter->GetVulkanInstance()->GetFunctions();
|
||||||
VkInstance instance = adapter->GetVulkanInstance()->GetVkInstance();
|
VkInstance instance = adapter->GetVulkanInstance()->GetVkInstance();
|
||||||
|
@ -205,6 +205,33 @@ uint32_t MinImageCountForPresentMode(VkPresentModeKHR mode) {
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
// static
|
||||||
|
ResultOrError<wgpu::TextureUsage> SwapChain::GetSupportedSurfaceUsage(const Device* device,
|
||||||
|
const Surface* surface) {
|
||||||
|
Adapter* adapter = ToBackend(device->GetAdapter());
|
||||||
|
const VulkanFunctions& fn = adapter->GetVulkanInstance()->GetFunctions();
|
||||||
|
VkInstance instanceVk = adapter->GetVulkanInstance()->GetVkInstance();
|
||||||
|
VkPhysicalDevice physicalDeviceVk = adapter->GetPhysicalDevice();
|
||||||
|
|
||||||
|
VkSurfaceKHR surfaceVk;
|
||||||
|
VkSurfaceCapabilitiesKHR surfaceCapsVk;
|
||||||
|
DAWN_TRY_ASSIGN(surfaceVk, CreateVulkanSurface(adapter, surface));
|
||||||
|
|
||||||
|
DAWN_TRY(CheckVkSuccess(
|
||||||
|
fn.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDeviceVk, surfaceVk, &surfaceCapsVk),
|
||||||
|
"GetPhysicalDeviceSurfaceCapabilitiesKHR"));
|
||||||
|
|
||||||
|
wgpu::TextureUsage supportedUsages = wgpu::TextureUsage::RenderAttachment;
|
||||||
|
|
||||||
|
if (surfaceCapsVk.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
|
||||||
|
supportedUsages |= wgpu::TextureUsage::TextureBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn.DestroySurfaceKHR(instanceVk, surfaceVk, nullptr);
|
||||||
|
|
||||||
|
return supportedUsages;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
|
ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
|
||||||
Surface* surface,
|
Surface* surface,
|
||||||
|
|
|
@ -33,6 +33,10 @@ class SwapChain : public SwapChainBase {
|
||||||
Surface* surface,
|
Surface* surface,
|
||||||
SwapChainBase* previousSwapChain,
|
SwapChainBase* previousSwapChain,
|
||||||
const SwapChainDescriptor* descriptor);
|
const SwapChainDescriptor* descriptor);
|
||||||
|
|
||||||
|
static ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsage(const Device* device,
|
||||||
|
const Surface* surface);
|
||||||
|
|
||||||
~SwapChain() override;
|
~SwapChain() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -12,10 +12,12 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "dawn/tests/DawnTest.h"
|
#include <vector>
|
||||||
|
|
||||||
#include "dawn/common/Constants.h"
|
#include "dawn/common/Constants.h"
|
||||||
#include "dawn/common/Log.h"
|
#include "dawn/common/Log.h"
|
||||||
|
#include "dawn/tests/DawnTest.h"
|
||||||
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
||||||
#include "dawn/utils/WGPUHelpers.h"
|
#include "dawn/utils/WGPUHelpers.h"
|
||||||
#include "webgpu/webgpu_glfw.h"
|
#include "webgpu/webgpu_glfw.h"
|
||||||
|
|
||||||
|
@ -235,4 +237,162 @@ TEST_P(SwapChainTests, SwitchingDevice) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that calling Device.GetSupportedSurfaceUsage() will throw an error because
|
||||||
|
// SurfaceCapabilities is not enabled.
|
||||||
|
TEST_P(SwapChainTests, ErrorGetSurfaceSupportedUsage) {
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
|
||||||
|
EXPECT_FALSE(device.HasFeature(wgpu::FeatureName::SurfaceCapabilities));
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR_MSG(
|
||||||
|
{
|
||||||
|
auto usageFlags = device.GetSupportedSurfaceUsage(surface);
|
||||||
|
EXPECT_EQ(usageFlags, wgpu::TextureUsage::None);
|
||||||
|
},
|
||||||
|
testing::HasSubstr("FeatureName::SurfaceCapabilities is not enabled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that creating swapchain with TextureBinding usage without enabling SurfaceCapabilities
|
||||||
|
// feature should fail.
|
||||||
|
TEST_P(SwapChainTests, ErrorCreateWithTextureBindingUsage) {
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
|
||||||
|
EXPECT_FALSE(device.HasFeature(wgpu::FeatureName::SurfaceCapabilities));
|
||||||
|
|
||||||
|
auto desc = baseDescriptor;
|
||||||
|
desc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR_MSG(
|
||||||
|
{ auto swapchain = device.CreateSwapChain(surface, &desc); },
|
||||||
|
testing::HasSubstr("require enabling FeatureName::SurfaceCapabilities"));
|
||||||
|
}
|
||||||
|
|
||||||
|
class SwapChainWithAdditionalUsageTests : public SwapChainTests {
|
||||||
|
protected:
|
||||||
|
std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
|
||||||
|
std::vector<wgpu::FeatureName> features;
|
||||||
|
if (!UsesWire() && SupportsFeatures({wgpu::FeatureName::SurfaceCapabilities})) {
|
||||||
|
features.push_back(wgpu::FeatureName::SurfaceCapabilities);
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp() override {
|
||||||
|
SwapChainTests::SetUp();
|
||||||
|
|
||||||
|
// If parent class skipped the test, we should skip as well.
|
||||||
|
if (surface == nullptr) {
|
||||||
|
GTEST_SKIP();
|
||||||
|
}
|
||||||
|
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::SurfaceCapabilities}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SampleTexture(wgpu::TextureView view,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
utils::RGBA8 expectedColor) {
|
||||||
|
wgpu::TextureDescriptor texDescriptor;
|
||||||
|
texDescriptor.size = {width, height, 1};
|
||||||
|
texDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
texDescriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc |
|
||||||
|
wgpu::TextureUsage::CopyDst;
|
||||||
|
texDescriptor.mipLevelCount = 1;
|
||||||
|
texDescriptor.sampleCount = 1;
|
||||||
|
|
||||||
|
wgpu::Texture dstTexture = device.CreateTexture(&texDescriptor);
|
||||||
|
wgpu::TextureView dstView = dstTexture.CreateView();
|
||||||
|
|
||||||
|
// Create a render pipeline to blit |view| into |dstView|.
|
||||||
|
utils::ComboRenderPipelineDescriptor pipelineDesc;
|
||||||
|
pipelineDesc.vertex.module = utils::CreateShaderModule(device, R"(
|
||||||
|
@vertex
|
||||||
|
fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
|
||||||
|
var pos = array(
|
||||||
|
vec2f(-1.0, -1.0),
|
||||||
|
vec2f(-1.0, 1.0),
|
||||||
|
vec2f( 1.0, -1.0),
|
||||||
|
vec2f(-1.0, 1.0),
|
||||||
|
vec2f( 1.0, -1.0),
|
||||||
|
vec2f( 1.0, 1.0));
|
||||||
|
return vec4f(pos[VertexIndex], 0.0, 1.0);
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
pipelineDesc.cFragment.module = utils::CreateShaderModule(device, R"(
|
||||||
|
@group(0) @binding(0) var texture : texture_2d<f32>;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@builtin(position) coord: vec4f) -> @location(0) vec4f {
|
||||||
|
return textureLoad(texture, vec2i(coord.xy), 0);
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
pipelineDesc.cTargets[0].format = texDescriptor.format;
|
||||||
|
|
||||||
|
// Submit a render pass to perform the blit from |view| to |dstView|.
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
{
|
||||||
|
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc);
|
||||||
|
|
||||||
|
wgpu::BindGroup bindGroup =
|
||||||
|
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, view}});
|
||||||
|
|
||||||
|
utils::ComboRenderPassDescriptor renderPassInfo({dstView});
|
||||||
|
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassInfo);
|
||||||
|
pass.SetPipeline(pipeline);
|
||||||
|
pass.SetBindGroup(0, bindGroup);
|
||||||
|
pass.Draw(6);
|
||||||
|
pass.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
EXPECT_TEXTURE_EQ(expectedColor, dstTexture, {0, 0});
|
||||||
|
EXPECT_TEXTURE_EQ(expectedColor, dstTexture, {width - 1, height - 1});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(SwapChainWithAdditionalUsageTests, GetSurfaceSupportedUsage) {
|
||||||
|
auto usageFlags = device.GetSupportedSurfaceUsage(surface);
|
||||||
|
EXPECT_NE(usageFlags, wgpu::TextureUsage::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that sampling from swapchain is supported.
|
||||||
|
TEST_P(SwapChainWithAdditionalUsageTests, SamplingFromSwapChain) {
|
||||||
|
// Skip all tests if readable surface doesn't support texture binding
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(
|
||||||
|
(device.GetSupportedSurfaceUsage(surface) & wgpu::TextureUsage::TextureBinding) == 0);
|
||||||
|
|
||||||
|
auto desc = baseDescriptor;
|
||||||
|
desc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
|
||||||
|
|
||||||
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
|
||||||
|
ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
|
||||||
|
|
||||||
|
SampleTexture(swapchain.GetCurrentTextureView(), baseDescriptor.width, baseDescriptor.height,
|
||||||
|
utils::RGBA8::kRed);
|
||||||
|
|
||||||
|
swapchain.Present();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that including unsupported usage flag will result in error.
|
||||||
|
TEST_P(SwapChainWithAdditionalUsageTests, ErrorIncludeUnsupportedUsage) {
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
|
||||||
|
|
||||||
|
auto supportedUsage = device.GetSupportedSurfaceUsage(surface);
|
||||||
|
|
||||||
|
// Assuming StorageBinding is not supported.
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF((supportedUsage & wgpu::TextureUsage::StorageBinding) != 0);
|
||||||
|
|
||||||
|
auto desc = baseDescriptor;
|
||||||
|
desc.usage = supportedUsage | wgpu::TextureUsage::StorageBinding;
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR_MSG({ auto swapchain = device.CreateSwapChain(surface, &desc); },
|
||||||
|
testing::HasSubstr("is not supported"));
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(SwapChainTests, MetalBackend(), VulkanBackend());
|
DAWN_INSTANTIATE_TEST(SwapChainTests, MetalBackend(), VulkanBackend());
|
||||||
|
DAWN_INSTANTIATE_TEST(SwapChainWithAdditionalUsageTests,
|
||||||
|
D3D12Backend(),
|
||||||
|
MetalBackend(),
|
||||||
|
NullBackend(),
|
||||||
|
VulkanBackend());
|
||||||
|
|
|
@ -121,6 +121,11 @@ class DeviceMock : public DeviceBase {
|
||||||
(TextureBase*, const TextureViewDescriptor*),
|
(TextureBase*, const TextureViewDescriptor*),
|
||||||
(override));
|
(override));
|
||||||
|
|
||||||
|
MOCK_METHOD(ResultOrError<wgpu::TextureUsage>,
|
||||||
|
GetSupportedSurfaceUsageImpl,
|
||||||
|
(const Surface*),
|
||||||
|
(const, override));
|
||||||
|
|
||||||
MOCK_METHOD(MaybeError, TickImpl, (), (override));
|
MOCK_METHOD(MaybeError, TickImpl, (), (override));
|
||||||
|
|
||||||
MOCK_METHOD(ResultOrError<ExecutionSerial>, CheckAndUpdateCompletedSerials, (), (override));
|
MOCK_METHOD(ResultOrError<ExecutionSerial>, CheckAndUpdateCompletedSerials, (), (override));
|
||||||
|
|
|
@ -25,6 +25,7 @@ bool IsFeatureSupported(WGPUFeatureName feature) {
|
||||||
case WGPUFeatureName_DawnNative:
|
case WGPUFeatureName_DawnNative:
|
||||||
case WGPUFeatureName_DawnShaderFloat16: // Deprecated
|
case WGPUFeatureName_DawnShaderFloat16: // Deprecated
|
||||||
case WGPUFeatureName_ImplicitDeviceSynchronization:
|
case WGPUFeatureName_ImplicitDeviceSynchronization:
|
||||||
|
case WGPUFeatureName_SurfaceCapabilities:
|
||||||
return false;
|
return false;
|
||||||
case WGPUFeatureName_Depth32FloatStencil8:
|
case WGPUFeatureName_Depth32FloatStencil8:
|
||||||
case WGPUFeatureName_TimestampQuery:
|
case WGPUFeatureName_TimestampQuery:
|
||||||
|
|
|
@ -221,6 +221,12 @@ WGPUAdapter Device::GetAdapter() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WGPUTextureUsage Device::GetSupportedSurfaceUsage(WGPUSurface) {
|
||||||
|
// Not implemented in the wire.
|
||||||
|
UNREACHABLE();
|
||||||
|
return WGPUTextureUsage_RenderAttachment;
|
||||||
|
}
|
||||||
|
|
||||||
WGPUQueue Device::GetQueue() {
|
WGPUQueue Device::GetQueue() {
|
||||||
// The queue is lazily created because if a Device is created by
|
// The queue is lazily created because if a Device is created by
|
||||||
// Reserve/Inject, we cannot send the GetQueue message until
|
// Reserve/Inject, we cannot send the GetQueue message until
|
||||||
|
|
|
@ -70,6 +70,7 @@ class Device final : public ObjectBase {
|
||||||
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
|
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
|
||||||
|
|
||||||
WGPUAdapter GetAdapter(); // Not implemented in the wire.
|
WGPUAdapter GetAdapter(); // Not implemented in the wire.
|
||||||
|
WGPUTextureUsage GetSupportedSurfaceUsage(WGPUSurface); // Not implemented in the wire.
|
||||||
WGPUQueue GetQueue();
|
WGPUQueue GetQueue();
|
||||||
|
|
||||||
void CancelCallbacksForDisconnect() override;
|
void CancelCallbacksForDisconnect() override;
|
||||||
|
|
Loading…
Reference in New Issue