From 4faf3d31ba97b0d98695cd1dedca8514052e252e Mon Sep 17 00:00:00 2001 From: Peng Huang Date: Thu, 6 Apr 2023 18:02:13 +0000 Subject: [PATCH] d3d11: add Device, Queue, Sampler, etc Bug: dawn:1705 Change-Id: I0cfc54a3be2c9dc4471d0b5b9cb7d6066519bcf1 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/126300 Commit-Queue: Peng Huang Reviewed-by: Austin Eng Kokoro: Kokoro --- src/dawn/native/BUILD.gn | 11 + src/dawn/native/CMakeLists.txt | 12 +- src/dawn/native/d3d11/AdapterD3D11.cpp | 42 +- src/dawn/native/d3d11/AdapterD3D11.h | 3 +- .../d3d11/CommandRecordingContextD3D11.cpp | 95 ++++ .../d3d11/CommandRecordingContextD3D11.h | 51 +++ src/dawn/native/d3d11/DeviceD3D11.cpp | 429 ++++++++++++++++++ src/dawn/native/d3d11/DeviceD3D11.h | 144 ++++++ src/dawn/native/d3d11/DeviceInfoD3D11.cpp | 9 +- src/dawn/native/d3d11/DeviceInfoD3D11.h | 2 +- src/dawn/native/d3d11/Forward.h | 69 +++ src/dawn/native/d3d11/QueueD3D11.cpp | 44 ++ src/dawn/native/d3d11/QueueD3D11.h | 46 ++ src/dawn/native/d3d11/SamplerD3D11.cpp | 102 +++++ src/dawn/native/d3d11/SamplerD3D11.h | 43 ++ src/dawn/native/d3d11/UtilsD3D11.cpp | 46 ++ src/dawn/native/d3d11/UtilsD3D11.h | 28 ++ 17 files changed, 1149 insertions(+), 27 deletions(-) create mode 100644 src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp create mode 100644 src/dawn/native/d3d11/CommandRecordingContextD3D11.h create mode 100644 src/dawn/native/d3d11/DeviceD3D11.cpp create mode 100644 src/dawn/native/d3d11/DeviceD3D11.h create mode 100644 src/dawn/native/d3d11/Forward.h create mode 100644 src/dawn/native/d3d11/QueueD3D11.cpp create mode 100644 src/dawn/native/d3d11/QueueD3D11.h create mode 100644 src/dawn/native/d3d11/SamplerD3D11.cpp create mode 100644 src/dawn/native/d3d11/SamplerD3D11.h create mode 100644 src/dawn/native/d3d11/UtilsD3D11.cpp create mode 100644 src/dawn/native/d3d11/UtilsD3D11.h diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn index e902a6f92a..92eaa8489e 100644 --- a/src/dawn/native/BUILD.gn +++ b/src/dawn/native/BUILD.gn @@ -427,11 +427,22 @@ source_set("sources") { "d3d11/AdapterD3D11.h", "d3d11/BackendD3D11.cpp", "d3d11/BackendD3D11.h", + "d3d11/CommandRecordingContextD3D11.cpp", + "d3d11/CommandRecordingContextD3D11.h", "d3d11/D3D11Backend.cpp", + "d3d11/DeviceD3D11.cpp", + "d3d11/DeviceD3D11.h", "d3d11/DeviceInfoD3D11.cpp", "d3d11/DeviceInfoD3D11.h", + "d3d11/Forward.h", "d3d11/PlatformFunctionsD3D11.cpp", "d3d11/PlatformFunctionsD3D11.h", + "d3d11/QueueD3D11.cpp", + "d3d11/QueueD3D11.h", + "d3d11/SamplerD3D11.cpp", + "d3d11/SamplerD3D11.h", + "d3d11/UtilsD3D11.cpp", + "d3d11/UtilsD3D11.h", ] } diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt index 960e3d8b17..71c22d308e 100644 --- a/src/dawn/native/CMakeLists.txt +++ b/src/dawn/native/CMakeLists.txt @@ -284,12 +284,22 @@ if (DAWN_ENABLE_D3D11) "d3d11/AdapterD3D11.h" "d3d11/BackendD3D11.cpp" "d3d11/BackendD3D11.h" + "d3d11/CommandRecordingContextD3D11.cpp" + "d3d11/CommandRecordingContextD3D11.h" "d3d11/D3D11Backend.cpp" + "d3d11/DeviceD3D11.cpp" + "d3d11/DeviceD3D11.h" "d3d11/DeviceInfoD3D11.cpp" "d3d11/DeviceInfoD3D11.h" + "d3d11/Forward.h" "d3d11/PlatformFunctionsD3D11.cpp" "d3d11/PlatformFunctionsD3D11.h" - + "d3d11/QueueD3D11.cpp" + "d3d11/QueueD3D11.h" + "d3d11/SamplerD3D11.cpp" + "d3d11/SamplerD3D11.h" + "d3d11/UtilsD3D11.cpp" + "d3d11/UtilsD3D11.h" ) endif() diff --git a/src/dawn/native/d3d11/AdapterD3D11.cpp b/src/dawn/native/d3d11/AdapterD3D11.cpp index 9906936004..86c2731342 100644 --- a/src/dawn/native/d3d11/AdapterD3D11.cpp +++ b/src/dawn/native/d3d11/AdapterD3D11.cpp @@ -21,6 +21,7 @@ #include "dawn/native/Instance.h" #include "dawn/native/d3d/D3DError.h" #include "dawn/native/d3d11/BackendD3D11.h" +#include "dawn/native/d3d11/DeviceD3D11.h" #include "dawn/native/d3d11/PlatformFunctionsD3D11.h" namespace dawn::native::d3d11 { @@ -41,8 +42,25 @@ const DeviceInfo& Adapter::GetDeviceInfo() const { return mDeviceInfo; } -ComPtr Adapter::GetD3D11Device() const { - return mD3d11Device; +ResultOrError> Adapter::CreateD3D11Device() { + ComPtr device = std::move(mD3d11Device); + if (!device) { + const PlatformFunctions* functions = static_cast(GetBackend())->GetFunctions(); + const D3D_FEATURE_LEVEL featureLevels[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0}; + + UINT flags = 0; + if (GetInstance()->IsBackendValidationEnabled()) { + flags |= D3D11_CREATE_DEVICE_DEBUG; + } + + DAWN_TRY(CheckHRESULT(functions->d3d11CreateDevice( + GetHardwareAdapter(), D3D_DRIVER_TYPE_UNKNOWN, + /*Software=*/nullptr, flags, featureLevels, + std::size(featureLevels), D3D11_SDK_VERSION, &device, + /*pFeatureLevel=*/nullptr, /*[out] ppImmediateContext=*/nullptr), + "D3D11CreateDevice failed")); + } + return device; } MaybeError Adapter::InitializeImpl() { @@ -50,21 +68,10 @@ MaybeError Adapter::InitializeImpl() { // D3D11 cannot check for feature support without a device. // Create the device to populate the adapter properties then reuse it when needed for actual // rendering. - const PlatformFunctions* functions = static_cast(GetBackend())->GetFunctions(); - const D3D_FEATURE_LEVEL featureLevels[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0}; + DAWN_TRY_ASSIGN(mD3d11Device, CreateD3D11Device()); - UINT flags = 0; - if (GetInstance()->IsBackendValidationEnabled()) { - flags |= D3D11_CREATE_DEVICE_DEBUG; - } - - DAWN_TRY(CheckHRESULT(functions->d3d11CreateDevice( - GetHardwareAdapter(), D3D_DRIVER_TYPE_UNKNOWN, /*Software=*/nullptr, - flags, featureLevels, std::size(featureLevels), D3D11_SDK_VERSION, - &mD3d11Device, &mFeatureLevel, /*[out] ppImmediateContext=*/nullptr), - "D3D11CreateDevice failed")); - - DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this)); + mFeatureLevel = mD3d11Device->GetFeatureLevel(); + DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(mD3d11Device)); // Base::InitializeImpl() cannot distinguish between discrete and integrated GPUs, so we need to // overwrite it. @@ -150,8 +157,7 @@ void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {} ResultOrError> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor, const TogglesState& deviceToggles) { - // TODO(dawn:1705): Implement D3D11 backend. - return DAWN_UNIMPLEMENTED_ERROR("D3D11 backend is not implemented yet"); + return Device::Create(this, descriptor, deviceToggles); } // Resets the backend device and creates a new one. If any D3D11 objects belonging to the diff --git a/src/dawn/native/d3d11/AdapterD3D11.h b/src/dawn/native/d3d11/AdapterD3D11.h index 51f4540ac2..ff63d922d6 100644 --- a/src/dawn/native/d3d11/AdapterD3D11.h +++ b/src/dawn/native/d3d11/AdapterD3D11.h @@ -35,7 +35,7 @@ class Adapter : public d3d::Adapter { bool SupportsExternalImages() const override; const DeviceInfo& GetDeviceInfo() const; - ComPtr GetD3D11Device() const; + ResultOrError> CreateD3D11Device(); private: using Base = d3d::Adapter; @@ -55,7 +55,6 @@ class Adapter : public d3d::Adapter { const TogglesState& toggles) const override; ComPtr mD3d11Device; D3D_FEATURE_LEVEL mFeatureLevel; - DeviceInfo mDeviceInfo = {}; }; diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp new file mode 100644 index 0000000000..c42430515d --- /dev/null +++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp @@ -0,0 +1,95 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/native/d3d11/CommandRecordingContextD3D11.h" + +#include +#include + +#include "dawn/native/d3d/D3DError.h" +#include "dawn/native/d3d11/DeviceD3D11.h" +#include "dawn/native/d3d11/Forward.h" +#include "dawn/platform/DawnPlatform.h" +#include "dawn/platform/tracing/TraceEvent.h" + +namespace dawn::native::d3d11 { + +MaybeError CommandRecordingContext::Open(Device* device) { + ASSERT(!IsOpen()); + ASSERT(device); + + if (!mD3D11DeviceContext4) { + ID3D11Device* d3d11Device = device->GetD3D11Device(); + + ComPtr d3d11DeviceContext; + device->GetD3D11Device()->GetImmediateContext(&d3d11DeviceContext); + + ComPtr d3d11DeviceContext4; + DAWN_TRY( + CheckHRESULT(d3d11DeviceContext.As(&d3d11DeviceContext4), + "D3D11 querying immediate context for ID3D11DeviceContext4 interface")); + + mD3D11Device = d3d11Device; + mD3D11DeviceContext4 = std::move(d3d11DeviceContext4); + } + + mIsOpen = true; + mNeedsSubmit = false; + + return {}; +} + +MaybeError CommandRecordingContext::ExecuteCommandList(Device* device) { + // Consider using deferred DeviceContext. + return {}; +} + +ID3D11Device* CommandRecordingContext::GetD3D11Device() const { + return mD3D11Device.Get(); +} + +ID3D11DeviceContext* CommandRecordingContext::GetD3D11DeviceContext() const { + return mD3D11DeviceContext4.Get(); +} + +ID3D11DeviceContext1* CommandRecordingContext::GetD3D11DeviceContext1() const { + return mD3D11DeviceContext4.Get(); +} + +ID3D11DeviceContext4* CommandRecordingContext::GetD3D11DeviceContext4() const { + return mD3D11DeviceContext4.Get(); +} + +void CommandRecordingContext::Release() { + if (mIsOpen) { + mIsOpen = false; + mNeedsSubmit = false; + mD3D11DeviceContext4 = nullptr; + mD3D11Device = nullptr; + } +} + +bool CommandRecordingContext::IsOpen() const { + return mIsOpen; +} + +bool CommandRecordingContext::NeedsSubmit() const { + return mNeedsSubmit; +} + +void CommandRecordingContext::SetNeedsSubmit() { + mNeedsSubmit = true; +} + +} // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h new file mode 100644 index 0000000000..9fbba544dc --- /dev/null +++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h @@ -0,0 +1,51 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_D3D11_COMMANDRECORDINGCONTEXT_D3D11_H_ +#define SRC_DAWN_NATIVE_D3D11_COMMANDRECORDINGCONTEXT_D3D11_H_ + +#include "dawn/common/RefCounted.h" +#include "dawn/native/Error.h" +#include "dawn/native/d3d/d3d_platform.h" + +namespace dawn::native::d3d11 { +class CommandAllocatorManager; +class Device; + +class CommandRecordingContext { + public: + MaybeError Open(Device* device); + + void Release(); + bool IsOpen() const; + bool NeedsSubmit() const; + void SetNeedsSubmit(); + + MaybeError ExecuteCommandList(Device* device); + + ID3D11Device* GetD3D11Device() const; + ID3D11DeviceContext* GetD3D11DeviceContext() const; + ID3D11DeviceContext1* GetD3D11DeviceContext1() const; + ID3D11DeviceContext4* GetD3D11DeviceContext4() const; + + private: + bool mIsOpen = false; + bool mNeedsSubmit = false; + ComPtr mD3D11Device; + ComPtr mD3D11DeviceContext4; +}; + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_COMMANDRECORDINGCONTEXT_D3D11_H_ diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp new file mode 100644 index 0000000000..647a9ba160 --- /dev/null +++ b/src/dawn/native/d3d11/DeviceD3D11.cpp @@ -0,0 +1,429 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/native/d3d11/DeviceD3D11.h" + +#include +#include +#include +#include + +#include "dawn/common/GPUInfo.h" +#include "dawn/native/Buffer.h" +#include "dawn/native/ComputePipeline.h" +#include "dawn/native/D3D11Backend.h" +#include "dawn/native/DynamicUploader.h" +#include "dawn/native/Instance.h" +#include "dawn/native/RenderPipeline.h" +#include "dawn/native/Texture.h" +#include "dawn/native/d3d/D3DError.h" +#include "dawn/native/d3d11/AdapterD3D11.h" +#include "dawn/native/d3d11/BackendD3D11.h" +#include "dawn/native/d3d11/PlatformFunctionsD3D11.h" +#include "dawn/native/d3d11/QueueD3D11.h" +#include "dawn/native/d3d11/SamplerD3D11.h" +#include "dawn/platform/DawnPlatform.h" +#include "dawn/platform/tracing/TraceEvent.h" + +namespace dawn::native::d3d11 { +namespace { + +static constexpr uint64_t kMaxDebugMessagesToPrint = 5; + +void AppendDebugLayerMessagesToError(ID3D11InfoQueue* infoQueue, + uint64_t totalErrors, + ErrorData* error) { + ASSERT(totalErrors > 0); + ASSERT(error != nullptr); + + uint64_t errorsToPrint = std::min(kMaxDebugMessagesToPrint, totalErrors); + for (uint64_t i = 0; i < errorsToPrint; ++i) { + std::ostringstream messageStream; + SIZE_T messageLength = 0; + HRESULT hr = infoQueue->GetMessage(i, nullptr, &messageLength); + if (FAILED(hr)) { + messageStream << " ID3D11InfoQueue::GetMessage failed with " << hr; + error->AppendBackendMessage(messageStream.str()); + continue; + } + + std::unique_ptr messageData(new uint8_t[messageLength]); + D3D11_MESSAGE* message = reinterpret_cast(messageData.get()); + hr = infoQueue->GetMessage(i, message, &messageLength); + if (FAILED(hr)) { + messageStream << " ID3D11InfoQueue::GetMessage failed with " << hr; + error->AppendBackendMessage(messageStream.str()); + continue; + } + + messageStream << message->pDescription << " (" << message->ID << ")"; + error->AppendBackendMessage(messageStream.str()); + } + if (errorsToPrint < totalErrors) { + std::ostringstream messages; + messages << (totalErrors - errorsToPrint) << " messages silenced"; + error->AppendBackendMessage(messages.str()); + } + + // We only print up to the first kMaxDebugMessagesToPrint errors + infoQueue->ClearStoredMessages(); +} + +} // namespace + +// static +ResultOrError> Device::Create(Adapter* adapter, + const DeviceDescriptor* descriptor, + const TogglesState& deviceToggles) { + Ref device = AcquireRef(new Device(adapter, descriptor, deviceToggles)); + DAWN_TRY(device->Initialize(descriptor)); + return device; +} + +MaybeError Device::Initialize(const DeviceDescriptor* descriptor) { + DAWN_TRY_ASSIGN(mD3d11Device, ToBackend(GetAdapter())->CreateD3D11Device()); + ASSERT(mD3d11Device != nullptr); + + DAWN_TRY(DeviceBase::Initialize(Queue::Create(this, &descriptor->defaultQueue))); + + // Get the ID3D11Device5 interface which is need for creating fences. + // TODO(dawn:1741): Handle the case where ID3D11Device5 is not available. + DAWN_TRY(CheckHRESULT(mD3d11Device.As(&mD3d11Device5), "D3D11: getting ID3D11Device5")); + + // Create the fence. + DAWN_TRY( + CheckHRESULT(mD3d11Device5->CreateFence(0, D3D11_FENCE_FLAG_SHARED, IID_PPV_ARGS(&mFence)), + "D3D11: creating fence")); + + DAWN_TRY(CheckHRESULT(mFence->CreateSharedHandle(nullptr, GENERIC_ALL, nullptr, &mFenceHandle), + "D3D11: creating fence shared handle")); + + // Create the fence event. + mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + SetLabelImpl(); + + return {}; +} + +Device::~Device() { + Destroy(); + + // Close the handle here instead of in DestroyImpl. The handle is returned from + // ExternalImageDXGI, so it needs to live as long as the Device ref does, even if the device + // state is destroyed. + if (mFenceHandle != nullptr) { + ::CloseHandle(mFenceHandle); + mFenceHandle = nullptr; + } +} + +ID3D11Device* Device::GetD3D11Device() const { + return mD3d11Device.Get(); +} + +ID3D11Device5* Device::GetD3D11Device5() const { + return mD3d11Device5.Get(); +} + +ResultOrError Device::GetPendingCommandContext( + Device::SubmitMode submitMode) { + // Callers of GetPendingCommandList do so to record commands. Only reserve a command + // allocator when it is needed so we don't submit empty command lists + if (!mPendingCommands.IsOpen()) { + DAWN_TRY(mPendingCommands.Open(this)); + } + if (submitMode == Device::SubmitMode::Normal) { + mPendingCommands.SetNeedsSubmit(); + } + return &mPendingCommands; +} + +MaybeError Device::TickImpl() { + // Perform cleanup operations to free unused objects + [[maybe_unused]] ExecutionSerial completedSerial = GetCompletedCommandSerial(); + + if (mPendingCommands.IsOpen() && mPendingCommands.NeedsSubmit()) { + DAWN_TRY(ExecutePendingCommandContext()); + DAWN_TRY(NextSerial()); + } + + DAWN_TRY(CheckDebugLayerAndGenerateErrors()); + + return {}; +} + +MaybeError Device::NextSerial() { + IncrementLastSubmittedCommandSerial(); + + TRACE_EVENT1(GetPlatform(), General, "D3D11Device::SignalFence", "serial", + uint64_t(GetLastSubmittedCommandSerial())); + + CommandRecordingContext* commandContext; + DAWN_TRY_ASSIGN(commandContext, GetPendingCommandContext()); + + DAWN_TRY(CheckHRESULT(commandContext->GetD3D11DeviceContext4()->Signal( + mFence.Get(), uint64_t(GetLastSubmittedCommandSerial())), + "D3D11 command queue signal fence")); + + return {}; +} + +MaybeError Device::WaitForSerial(ExecutionSerial serial) { + DAWN_TRY(CheckPassedSerials()); + if (GetCompletedCommandSerial() < serial) { + DAWN_TRY(CheckHRESULT(mFence->SetEventOnCompletion(uint64_t(serial), mFenceEvent), + "D3D11 set event on completion")); + WaitForSingleObject(mFenceEvent, INFINITE); + DAWN_TRY(CheckPassedSerials()); + } + return {}; +} + +ResultOrError Device::CheckAndUpdateCompletedSerials() { + ExecutionSerial completedSerial = ExecutionSerial(mFence->GetCompletedValue()); + if (DAWN_UNLIKELY(completedSerial == ExecutionSerial(UINT64_MAX))) { + // GetCompletedValue returns UINT64_MAX if the device was removed. + // Try to query the failure reason. + DAWN_TRY(CheckHRESULT(mD3d11Device->GetDeviceRemovedReason(), + "ID3D11Device::GetDeviceRemovedReason")); + // Otherwise, return a generic device lost error. + return DAWN_DEVICE_LOST_ERROR("Device lost"); + } + + if (completedSerial <= GetCompletedCommandSerial()) { + return ExecutionSerial(0); + } + + return completedSerial; +} + +void Device::ReferenceUntilUnused(ComPtr object) { + mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial()); +} + +bool Device::HasPendingCommands() const { + return mPendingCommands.NeedsSubmit(); +} + +void Device::ForceEventualFlushOfCommands() { + if (mPendingCommands.IsOpen()) { + mPendingCommands.SetNeedsSubmit(); + } +} + +MaybeError Device::ExecutePendingCommandContext() { + return {}; +} + +ResultOrError> Device::CreateBindGroupImpl( + const BindGroupDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateBindGroupImpl"); +} + +ResultOrError> Device::CreateBindGroupLayoutImpl( + const BindGroupLayoutDescriptor* descriptor, + PipelineCompatibilityToken pipelineCompatibilityToken) { + return DAWN_UNIMPLEMENTED_ERROR("CreateBindGroupLayoutImpl"); +} + +ResultOrError> Device::CreateBufferImpl(const BufferDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateBufferImpl"); +} + +ResultOrError> Device::CreateCommandBuffer( + CommandEncoder* encoder, + const CommandBufferDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateCommandBuffer"); +} + +Ref Device::CreateUninitializedComputePipelineImpl( + const ComputePipelineDescriptor* descriptor) { + return nullptr; +} + +ResultOrError> Device::CreatePipelineLayoutImpl( + const PipelineLayoutDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreatePipelineLayoutImpl"); +} + +ResultOrError> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateQuerySetImpl"); +} + +Ref Device::CreateUninitializedRenderPipelineImpl( + const RenderPipelineDescriptor* descriptor) { + return nullptr; +} + +ResultOrError> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) { + return Sampler::Create(this, descriptor); +} + +ResultOrError> Device::CreateShaderModuleImpl( + const ShaderModuleDescriptor* descriptor, + ShaderModuleParseResult* parseResult, + OwnedCompilationMessages* compilationMessages) { + return DAWN_UNIMPLEMENTED_ERROR("CreateShaderModuleImpl"); +} + +ResultOrError> Device::CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateSwapChainImpl"); +} + +ResultOrError> Device::CreateSwapChainImpl( + Surface* surface, + NewSwapChainBase* previousSwapChain, + const SwapChainDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateSwapChainImpl"); +} + +ResultOrError> Device::CreateTextureImpl(const TextureDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateTextureImpl"); +} + +ResultOrError> Device::CreateTextureViewImpl( + TextureBase* texture, + const TextureViewDescriptor* descriptor) { + return DAWN_UNIMPLEMENTED_ERROR("CreateTextureViewImpl"); +} + +void Device::InitializeComputePipelineAsyncImpl(Ref computePipeline, + WGPUCreateComputePipelineAsyncCallback callback, + void* userdata) {} + +void Device::InitializeRenderPipelineAsyncImpl(Ref renderPipeline, + WGPUCreateRenderPipelineAsyncCallback callback, + void* userdata) {} + +MaybeError Device::CopyFromStagingToBufferImpl(BufferBase* source, + uint64_t sourceOffset, + BufferBase* destination, + uint64_t destinationOffset, + uint64_t size) { + return DAWN_UNIMPLEMENTED_ERROR("CopyFromStagingToBufferImpl"); +} + +MaybeError Device::CopyFromStagingToTextureImpl(const BufferBase* source, + const TextureDataLayout& src, + const TextureCopy& dst, + const Extent3D& copySizePixels) { + return DAWN_UNIMPLEMENTED_ERROR("CopyFromStagingToTextureImpl"); +} + +const DeviceInfo& Device::GetDeviceInfo() const { + return ToBackend(GetAdapter())->GetDeviceInfo(); +} + +MaybeError Device::WaitForIdleForDestruction() { + // Immediately forget about all pending commands + mPendingCommands.Release(); + + DAWN_TRY(NextSerial()); + // Wait for all in-flight commands to finish executing + DAWN_TRY(WaitForSerial(GetLastSubmittedCommandSerial())); + + return {}; +} + +MaybeError Device::CheckDebugLayerAndGenerateErrors() { + if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled()) { + return {}; + } + + ComPtr infoQueue; + DAWN_TRY(CheckHRESULT(mD3d11Device.As(&infoQueue), + "D3D11 QueryInterface ID3D11Device to ID3D11InfoQueue")); + uint64_t totalErrors = infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter(); + + // Check if any errors have occurred otherwise we would be creating an empty error. Note + // that we use GetNumStoredMessagesAllowedByRetrievalFilter instead of GetNumStoredMessages + // because we only convert WARNINGS or higher messages to dawn errors. + if (totalErrors == 0) { + return {}; + } + + auto error = DAWN_INTERNAL_ERROR("The D3D11 debug layer reported uncaught errors."); + + AppendDebugLayerMessagesToError(infoQueue.Get(), totalErrors, error.get()); + + return error; +} + +void Device::AppendDebugLayerMessages(ErrorData* error) { + if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled()) { + return; + } + + ComPtr infoQueue; + if (FAILED(mD3d11Device.As(&infoQueue))) { + return; + } + uint64_t totalErrors = infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter(); + + if (totalErrors == 0) { + return; + } + + AppendDebugLayerMessagesToError(infoQueue.Get(), totalErrors, error); +} + +void Device::DestroyImpl() { + ASSERT(GetState() == State::Disconnected); + + if (mFenceEvent != nullptr) { + ::CloseHandle(mFenceEvent); + mFenceEvent = nullptr; + } +} + +uint32_t Device::GetOptimalBytesPerRowAlignment() const { + return 256; +} + +uint64_t Device::GetOptimalBufferToTextureCopyOffsetAlignment() const { + return 1; +} + +float Device::GetTimestampPeriodInNS() const { + return 1.0f; +} + +bool Device::ShouldDuplicateNumWorkgroupsForDispatchIndirect( + ComputePipelineBase* computePipeline) const { + return false; +} + +void Device::SetLabelImpl() {} + +bool Device::MayRequireDuplicationOfIndirectParameters() const { + return true; +} + +bool Device::ShouldDuplicateParametersForDrawIndirect( + const RenderPipelineBase* renderPipelineBase) const { + // return ToBackend(renderPipelineBase)->UsesVertexOrInstanceIndex(); + return false; +} + +uint64_t Device::GetBufferCopyOffsetAlignmentForDepthStencil() const { + return DeviceBase::GetBufferCopyOffsetAlignmentForDepthStencil(); +} + +HANDLE Device::GetFenceHandle() const { + return mFenceHandle; +} + +} // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/DeviceD3D11.h b/src/dawn/native/d3d11/DeviceD3D11.h new file mode 100644 index 0000000000..e97a9ab211 --- /dev/null +++ b/src/dawn/native/d3d11/DeviceD3D11.h @@ -0,0 +1,144 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_D3D11_DEVICED3D11_H_ +#define SRC_DAWN_NATIVE_D3D11_DEVICED3D11_H_ + +#include +#include + +#include "dawn/common/SerialQueue.h" +#include "dawn/native/d3d/DeviceD3D.h" +#include "dawn/native/d3d11/CommandRecordingContextD3D11.h" +#include "dawn/native/d3d11/DeviceInfoD3D11.h" +#include "dawn/native/d3d11/Forward.h" + +namespace dawn::native::d3d11 { + +class Fence; + +// Definition of backend types +class Device final : public d3d::Device { + public: + static ResultOrError> Create(Adapter* adapter, + const DeviceDescriptor* descriptor, + const TogglesState& deviceToggles); + ~Device() override; + + MaybeError Initialize(const DeviceDescriptor* descriptor); + + ID3D11Device* GetD3D11Device() const; + ID3D11Device5* GetD3D11Device5() const; + + ResultOrError GetPendingCommandContext( + Device::SubmitMode submitMode = Device::SubmitMode::Normal); + + const DeviceInfo& GetDeviceInfo() const; + + MaybeError NextSerial(); + MaybeError WaitForSerial(ExecutionSerial serial); + + void ReferenceUntilUnused(ComPtr object); + MaybeError ExecutePendingCommandContext(); + HANDLE GetFenceHandle() const; + Ref CreateD3D11ExternalTexture(const TextureDescriptor* descriptor, + ComPtr d3d11Texture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized); + + ResultOrError> CreateCommandBuffer( + CommandEncoder* encoder, + const CommandBufferDescriptor* descriptor) override; + MaybeError TickImpl() override; + void ForceEventualFlushOfCommands() override; + MaybeError CopyFromStagingToBufferImpl(BufferBase* source, + uint64_t sourceOffset, + BufferBase* destination, + uint64_t destinationOffset, + uint64_t size) override; + MaybeError CopyFromStagingToTextureImpl(const BufferBase* source, + const TextureDataLayout& src, + const TextureCopy& dst, + const Extent3D& copySizePixels) override; + uint32_t GetOptimalBytesPerRowAlignment() const override; + uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override; + float GetTimestampPeriodInNS() const override; + bool ShouldDuplicateNumWorkgroupsForDispatchIndirect( + ComputePipelineBase* computePipeline) const override; + bool MayRequireDuplicationOfIndirectParameters() const override; + bool ShouldDuplicateParametersForDrawIndirect( + const RenderPipelineBase* renderPipelineBase) const override; + uint64_t GetBufferCopyOffsetAlignmentForDepthStencil() const override; + void SetLabelImpl() override; + + private: + using Base = d3d::Device; + using Base::Base; + + ResultOrError> CreateBindGroupImpl( + const BindGroupDescriptor* descriptor) override; + ResultOrError> CreateBindGroupLayoutImpl( + const BindGroupLayoutDescriptor* descriptor, + PipelineCompatibilityToken pipelineCompatibilityToken) override; + ResultOrError> CreateBufferImpl(const BufferDescriptor* descriptor) override; + ResultOrError> CreatePipelineLayoutImpl( + const PipelineLayoutDescriptor* descriptor) override; + ResultOrError> CreateQuerySetImpl( + const QuerySetDescriptor* descriptor) override; + ResultOrError> CreateSamplerImpl(const SamplerDescriptor* descriptor) override; + ResultOrError> CreateShaderModuleImpl( + const ShaderModuleDescriptor* descriptor, + ShaderModuleParseResult* parseResult, + OwnedCompilationMessages* compilationMessages) override; + ResultOrError> CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) override; + ResultOrError> CreateSwapChainImpl( + Surface* surface, + NewSwapChainBase* previousSwapChain, + const SwapChainDescriptor* descriptor) override; + ResultOrError> CreateTextureImpl(const TextureDescriptor* descriptor) override; + ResultOrError> CreateTextureViewImpl( + TextureBase* texture, + const TextureViewDescriptor* descriptor) override; + Ref CreateUninitializedComputePipelineImpl( + const ComputePipelineDescriptor* descriptor) override; + Ref CreateUninitializedRenderPipelineImpl( + const RenderPipelineDescriptor* descriptor) override; + void InitializeComputePipelineAsyncImpl(Ref computePipeline, + WGPUCreateComputePipelineAsyncCallback callback, + void* userdata) override; + void InitializeRenderPipelineAsyncImpl(Ref renderPipeline, + WGPUCreateRenderPipelineAsyncCallback callback, + void* userdata) override; + void DestroyImpl() override; + MaybeError WaitForIdleForDestruction() override; + bool HasPendingCommands() const override; + MaybeError CheckDebugLayerAndGenerateErrors(); + void AppendDebugLayerMessages(ErrorData* error) override; + ResultOrError CheckAndUpdateCompletedSerials() override; + + ComPtr mFence; + HANDLE mFenceHandle = nullptr; + HANDLE mFenceEvent = nullptr; + + ComPtr mD3d11Device; + ComPtr mD3d11Device5; + CommandRecordingContext mPendingCommands; + SerialQueue> mUsedComObjectRefs; +}; + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_DEVICED3D11_H_ diff --git a/src/dawn/native/d3d11/DeviceInfoD3D11.cpp b/src/dawn/native/d3d11/DeviceInfoD3D11.cpp index d15b7bb212..02c6c3c325 100644 --- a/src/dawn/native/d3d11/DeviceInfoD3D11.cpp +++ b/src/dawn/native/d3d11/DeviceInfoD3D11.cpp @@ -17,18 +17,17 @@ #include #include "dawn/native/d3d/D3DError.h" -#include "dawn/native/d3d11/AdapterD3D11.h" #include "dawn/native/d3d11/PlatformFunctionsD3D11.h" namespace dawn::native::d3d11 { -ResultOrError GatherDeviceInfo(const Adapter& adapter) { +ResultOrError GatherDeviceInfo(const ComPtr& device) { DeviceInfo info = {}; D3D11_FEATURE_DATA_D3D11_OPTIONS2 options2; - DAWN_TRY(CheckHRESULT(adapter.GetD3D11Device()->CheckFeatureSupport( - D3D11_FEATURE_D3D11_OPTIONS2, &options2, sizeof(options2)), - "D3D11_FEATURE_D3D11_OPTIONS2")); + DAWN_TRY(CheckHRESULT( + device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &options2, sizeof(options2)), + "D3D11_FEATURE_D3D11_OPTIONS2")); info.isUMA = options2.UnifiedMemoryArchitecture; diff --git a/src/dawn/native/d3d11/DeviceInfoD3D11.h b/src/dawn/native/d3d11/DeviceInfoD3D11.h index 66ffd7b9a1..0f5992571c 100644 --- a/src/dawn/native/d3d11/DeviceInfoD3D11.h +++ b/src/dawn/native/d3d11/DeviceInfoD3D11.h @@ -32,7 +32,7 @@ struct DeviceInfo { PerStage shaderProfiles; }; -ResultOrError GatherDeviceInfo(const Adapter& adapter); +ResultOrError GatherDeviceInfo(const ComPtr& device); } // namespace dawn::native::d3d11 #endif // SRC_DAWN_NATIVE_D3D11_DEVICEINFOD3D11_H_ diff --git a/src/dawn/native/d3d11/Forward.h b/src/dawn/native/d3d11/Forward.h new file mode 100644 index 0000000000..398bdd2b05 --- /dev/null +++ b/src/dawn/native/d3d11/Forward.h @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_D3D11_FORWARD_H_ +#define SRC_DAWN_NATIVE_D3D11_FORWARD_H_ + +#include "dawn/native/ToBackend.h" + +namespace dawn::native::d3d11 { + +class Adapter; +class BindGroup; +class BindGroupLayout; +class Buffer; +class CommandBuffer; +class ComputePipeline; +class Device; +class Heap; +class PipelineCache; +class PipelineLayout; +class QuerySet; +class Queue; +class RenderPipeline; +class Sampler; +class ShaderModule; +class SwapChain; +class Texture; +class TextureView; + +struct D3D11BackendTraits { + using AdapterType = Adapter; + using BindGroupType = BindGroup; + using BindGroupLayoutType = BindGroupLayout; + using BufferType = Buffer; + using CommandBufferType = CommandBuffer; + using ComputePipelineType = ComputePipeline; + using DeviceType = Device; + using PipelineCacheType = PipelineCache; + using PipelineLayoutType = PipelineLayout; + using QuerySetType = QuerySet; + using QueueType = Queue; + using RenderPipelineType = RenderPipeline; + using ResourceHeapType = Heap; + using SamplerType = Sampler; + using ShaderModuleType = ShaderModule; + using SwapChainType = SwapChain; + using TextureType = Texture; + using TextureViewType = TextureView; +}; + +template +auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { + return ToBackendBase(common); +} + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_FORWARD_H_ diff --git a/src/dawn/native/d3d11/QueueD3D11.cpp b/src/dawn/native/d3d11/QueueD3D11.cpp new file mode 100644 index 0000000000..1071960cb8 --- /dev/null +++ b/src/dawn/native/d3d11/QueueD3D11.cpp @@ -0,0 +1,44 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/native/d3d11/QueueD3D11.h" + +#include "dawn/native/d3d11/DeviceD3D11.h" +#include "dawn/platform/DawnPlatform.h" + +namespace dawn::native::d3d11 { + +Ref Queue::Create(Device* device, const QueueDescriptor* descriptor) { + return AcquireRef(new Queue(device, descriptor)); +} + +MaybeError Queue::SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) { + return DAWN_UNIMPLEMENTED_ERROR("Submit is not implemented for D3D11"); +} + +MaybeError Queue::WriteBufferImpl(BufferBase* buffer, + uint64_t bufferOffset, + const void* data, + size_t size) { + return DAWN_UNIMPLEMENTED_ERROR("WriteBuffer is not implemented for D3D11"); +} + +MaybeError Queue::WriteTextureImpl(const ImageCopyTexture& destination, + const void* data, + const TextureDataLayout& dataLayout, + const Extent3D& writeSizePixel) { + return DAWN_UNIMPLEMENTED_ERROR("WriteTexture is not implemented for D3D11"); +} + +} // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/QueueD3D11.h b/src/dawn/native/d3d11/QueueD3D11.h new file mode 100644 index 0000000000..e134deef62 --- /dev/null +++ b/src/dawn/native/d3d11/QueueD3D11.h @@ -0,0 +1,46 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_D3D11_QUEUED3D11_H_ +#define SRC_DAWN_NATIVE_D3D11_QUEUED3D11_H_ + +#include "dawn/native/Queue.h" + +namespace dawn::native::d3d11 { + +class Device; + +class Queue final : public QueueBase { + public: + static Ref Create(Device* device, const QueueDescriptor* descriptor); + + private: + using QueueBase::QueueBase; + + ~Queue() override = default; + + MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; + MaybeError WriteBufferImpl(BufferBase* buffer, + uint64_t bufferOffset, + const void* data, + size_t size) override; + MaybeError WriteTextureImpl(const ImageCopyTexture& destination, + const void* data, + const TextureDataLayout& dataLayout, + const Extent3D& writeSizePixel) override; +}; + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_QUEUED3D11_H_ diff --git a/src/dawn/native/d3d11/SamplerD3D11.cpp b/src/dawn/native/d3d11/SamplerD3D11.cpp new file mode 100644 index 0000000000..15ecfa0701 --- /dev/null +++ b/src/dawn/native/d3d11/SamplerD3D11.cpp @@ -0,0 +1,102 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/native/d3d11/SamplerD3D11.h" + +#include + +#include "dawn/native/d3d/D3DError.h" +#include "dawn/native/d3d11/DeviceD3D11.h" +#include "dawn/native/d3d11/UtilsD3D11.h" + +namespace dawn::native::d3d11 { + +namespace { + +D3D11_TEXTURE_ADDRESS_MODE D3D11TextureAddressMode(wgpu::AddressMode mode) { + switch (mode) { + case wgpu::AddressMode::Repeat: + return D3D11_TEXTURE_ADDRESS_WRAP; + case wgpu::AddressMode::MirrorRepeat: + return D3D11_TEXTURE_ADDRESS_MIRROR; + case wgpu::AddressMode::ClampToEdge: + return D3D11_TEXTURE_ADDRESS_CLAMP; + } +} + +D3D11_FILTER_TYPE D3D11FilterType(wgpu::FilterMode mode) { + switch (mode) { + case wgpu::FilterMode::Nearest: + return D3D11_FILTER_TYPE_POINT; + case wgpu::FilterMode::Linear: + return D3D11_FILTER_TYPE_LINEAR; + } +} + +} // namespace + +// static +ResultOrError> Sampler::Create(Device* device, const SamplerDescriptor* descriptor) { + auto sampler = AcquireRef(new Sampler(device, descriptor)); + DAWN_TRY(sampler->Initialize(descriptor)); + return sampler; +} + +MaybeError Sampler::Initialize(const SamplerDescriptor* descriptor) { + D3D11_SAMPLER_DESC samplerDesc = {}; + D3D11_FILTER_TYPE minFilter = D3D11FilterType(descriptor->minFilter); + D3D11_FILTER_TYPE magFilter = D3D11FilterType(descriptor->magFilter); + D3D11_FILTER_TYPE mipmapFilter = D3D11FilterType(descriptor->mipmapFilter); + + D3D11_FILTER_REDUCTION_TYPE reduction = descriptor->compare == wgpu::CompareFunction::Undefined + ? D3D11_FILTER_REDUCTION_TYPE_STANDARD + : D3D11_FILTER_REDUCTION_TYPE_COMPARISON; + + // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11_sampler_desc + samplerDesc.MaxAnisotropy = std::min(GetMaxAnisotropy(), 16u); + + if (samplerDesc.MaxAnisotropy > 1) { + samplerDesc.Filter = D3D11_ENCODE_ANISOTROPIC_FILTER(reduction); + } else { + samplerDesc.Filter = + D3D11_ENCODE_BASIC_FILTER(minFilter, magFilter, mipmapFilter, reduction); + } + + samplerDesc.AddressU = D3D11TextureAddressMode(descriptor->addressModeU); + samplerDesc.AddressV = D3D11TextureAddressMode(descriptor->addressModeV); + samplerDesc.AddressW = D3D11TextureAddressMode(descriptor->addressModeW); + samplerDesc.MipLODBias = 0.f; + + if (descriptor->compare != wgpu::CompareFunction::Undefined) { + samplerDesc.ComparisonFunc = ToD3D11ComparisonFunc(descriptor->compare); + } else { + // Still set the function so it's not garbage. + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + } + samplerDesc.MinLOD = descriptor->lodMinClamp; + samplerDesc.MaxLOD = descriptor->lodMaxClamp; + + DAWN_TRY(CheckHRESULT(ToBackend(GetDevice()) + ->GetD3D11Device() + ->CreateSamplerState(&samplerDesc, &mD3d11SamplerState), + "ID3D11Device::CreateSamplerState")); + + return {}; +} + +ID3D11SamplerState* Sampler::GetD3D11SamplerState() const { + return mD3d11SamplerState.Get(); +} + +} // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/SamplerD3D11.h b/src/dawn/native/d3d11/SamplerD3D11.h new file mode 100644 index 0000000000..3626e51bcb --- /dev/null +++ b/src/dawn/native/d3d11/SamplerD3D11.h @@ -0,0 +1,43 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_D3D11_SAMPLERD3D11_H_ +#define SRC_DAWN_NATIVE_D3D11_SAMPLERD3D11_H_ + +#include "dawn/native/Sampler.h" + +#include "dawn/native/d3d/d3d_platform.h" + +namespace dawn::native::d3d11 { + +class Device; + +class Sampler final : public SamplerBase { + public: + static ResultOrError> Create(Device* device, const SamplerDescriptor* descriptor); + + ID3D11SamplerState* GetD3D11SamplerState() const; + + private: + using SamplerBase::SamplerBase; + + ~Sampler() override = default; + MaybeError Initialize(const SamplerDescriptor* descriptor); + + ComPtr mD3d11SamplerState; +}; + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_SAMPLERD3D11_H_ diff --git a/src/dawn/native/d3d11/UtilsD3D11.cpp b/src/dawn/native/d3d11/UtilsD3D11.cpp new file mode 100644 index 0000000000..3858db2931 --- /dev/null +++ b/src/dawn/native/d3d11/UtilsD3D11.cpp @@ -0,0 +1,46 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/native/d3d11/UtilsD3D11.h" + +#include "dawn/common/Assert.h" +#include "dawn/native/Format.h" +#include "dawn/native/d3d/D3DError.h" + +namespace dawn::native::d3d11 { + +D3D11_COMPARISON_FUNC ToD3D11ComparisonFunc(wgpu::CompareFunction func) { + switch (func) { + case wgpu::CompareFunction::Never: + return D3D11_COMPARISON_NEVER; + case wgpu::CompareFunction::Less: + return D3D11_COMPARISON_LESS; + case wgpu::CompareFunction::LessEqual: + return D3D11_COMPARISON_LESS_EQUAL; + case wgpu::CompareFunction::Greater: + return D3D11_COMPARISON_GREATER; + case wgpu::CompareFunction::GreaterEqual: + return D3D11_COMPARISON_GREATER_EQUAL; + case wgpu::CompareFunction::Equal: + return D3D11_COMPARISON_EQUAL; + case wgpu::CompareFunction::NotEqual: + return D3D11_COMPARISON_NOT_EQUAL; + case wgpu::CompareFunction::Always: + return D3D11_COMPARISON_ALWAYS; + case wgpu::CompareFunction::Undefined: + UNREACHABLE(); + } +} + +} // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/UtilsD3D11.h b/src/dawn/native/d3d11/UtilsD3D11.h new file mode 100644 index 0000000000..48692c6078 --- /dev/null +++ b/src/dawn/native/d3d11/UtilsD3D11.h @@ -0,0 +1,28 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_D3D11_UTILSD3D11_H_ +#define SRC_DAWN_NATIVE_D3D11_UTILSD3D11_H_ + +#include "dawn/native/d3d/UtilsD3D.h" +#include "dawn/native/d3d/d3d_platform.h" +#include "dawn/native/dawn_platform.h" + +namespace dawn::native::d3d11 { + +D3D11_COMPARISON_FUNC ToD3D11ComparisonFunc(wgpu::CompareFunction func); + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_UTILSD3D11_H_