// Copyright 2019 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. // D3D12Backend.cpp: contains the definition of symbols exported by D3D12Backend.h so that they // can be compiled twice: once export (shared library), once not exported (static library) #include "dawn_native/D3D12Backend.h" #include "common/Log.h" #include "common/Math.h" #include "common/SwapChainUtils.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/NativeSwapChainImplD3D12.h" #include "dawn_native/d3d12/ResidencyManagerD3D12.h" #include "dawn_native/d3d12/TextureD3D12.h" namespace dawn_native { namespace d3d12 { ComPtr GetD3D12Device(WGPUDevice device) { Device* backendDevice = reinterpret_cast(device); return backendDevice->GetD3D12Device(); } DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device, HWND window) { Device* backendDevice = reinterpret_cast(device); DawnSwapChainImplementation impl; impl = CreateSwapChainImplementation(new NativeSwapChainImpl(backendDevice, window)); impl.textureUsage = WGPUTextureUsage_Present; return impl; } WGPUTextureFormat GetNativeSwapChainPreferredFormat( const DawnSwapChainImplementation* swapChain) { NativeSwapChainImpl* impl = reinterpret_cast(swapChain->userData); return static_cast(impl->GetPreferredFormat()); } ExternalImageDescriptorDXGISharedHandle::ExternalImageDescriptorDXGISharedHandle() : ExternalImageDescriptor(ExternalImageType::DXGISharedHandle) { } ExternalImageDXGI::ExternalImageDXGI(ComPtr d3d12Resource, const WGPUTextureDescriptor* descriptor) : mD3D12Resource(std::move(d3d12Resource)), mUsage(descriptor->usage), mDimension(descriptor->dimension), mSize(descriptor->size), mFormat(descriptor->format), mMipLevelCount(descriptor->mipLevelCount), mSampleCount(descriptor->sampleCount) { ASSERT(descriptor->nextInChain == nullptr); } WGPUTexture ExternalImageDXGI::ProduceTexture( WGPUDevice device, const ExternalImageAccessDescriptorDXGIKeyedMutex* descriptor) { Device* backendDevice = reinterpret_cast(device); // Ensure the texture usage is allowed if (!IsSubset(descriptor->usage, mUsage)) { dawn::ErrorLog() << "Texture usage is not valid for external image"; return nullptr; } TextureDescriptor textureDescriptor = {}; textureDescriptor.usage = static_cast(descriptor->usage); textureDescriptor.dimension = static_cast(mDimension); textureDescriptor.size = {mSize.width, mSize.height, mSize.depthOrArrayLayers}; textureDescriptor.format = static_cast(mFormat); textureDescriptor.mipLevelCount = mMipLevelCount; textureDescriptor.sampleCount = mSampleCount; Ref texture = backendDevice->CreateExternalTexture( &textureDescriptor, mD3D12Resource, ExternalMutexSerial(descriptor->acquireMutexKey), descriptor->isSwapChainTexture, descriptor->isInitialized); return reinterpret_cast(texture.Detach()); } // static std::unique_ptr ExternalImageDXGI::Create( WGPUDevice device, const ExternalImageDescriptorDXGISharedHandle* descriptor) { Device* backendDevice = reinterpret_cast(device); Microsoft::WRL::ComPtr d3d12Resource; if (FAILED(backendDevice->GetD3D12Device()->OpenSharedHandle( descriptor->sharedHandle, IID_PPV_ARGS(&d3d12Resource)))) { return nullptr; } const TextureDescriptor* textureDescriptor = reinterpret_cast(descriptor->cTextureDescriptor); if (backendDevice->ConsumedError( ValidateTextureDescriptor(backendDevice, textureDescriptor))) { return nullptr; } if (backendDevice->ConsumedError( ValidateTextureDescriptorCanBeWrapped(textureDescriptor))) { return nullptr; } if (backendDevice->ConsumedError( ValidateD3D12TextureCanBeWrapped(d3d12Resource.Get(), textureDescriptor))) { return nullptr; } // Shared handle is assumed to support resource sharing capability. The resource // shared capability tier must agree to share resources between D3D devices. const Format* format = backendDevice->GetInternalFormat(textureDescriptor->format).AcquireSuccess(); if (format->IsMultiPlanar()) { if (backendDevice->ConsumedError(ValidateD3D12VideoTextureCanBeShared( backendDevice, D3D12TextureFormat(textureDescriptor->format)))) { return nullptr; } } std::unique_ptr result( new ExternalImageDXGI(std::move(d3d12Resource), descriptor->cTextureDescriptor)); return result; } uint64_t SetExternalMemoryReservation(WGPUDevice device, uint64_t requestedReservationSize, MemorySegment memorySegment) { Device* backendDevice = reinterpret_cast(device); return backendDevice->GetResidencyManager()->SetExternalMemoryReservation( memorySegment, requestedReservationSize); } WGPUTexture WrapSharedHandle(WGPUDevice device, const ExternalImageDescriptorDXGISharedHandle* descriptor) { std::unique_ptr externalImage = ExternalImageDXGI::Create(device, descriptor); if (externalImage == nullptr) { return nullptr; } ExternalImageAccessDescriptorDXGIKeyedMutex externalAccessDesc = {}; externalAccessDesc.isInitialized = descriptor->isInitialized; externalAccessDesc.isSwapChainTexture = descriptor->isSwapChainTexture; externalAccessDesc.acquireMutexKey = descriptor->acquireMutexKey; externalAccessDesc.usage = descriptor->cTextureDescriptor->usage; return externalImage->ProduceTexture(device, &externalAccessDesc); } AdapterDiscoveryOptions::AdapterDiscoveryOptions(ComPtr adapter) : AdapterDiscoveryOptionsBase(WGPUBackendType_D3D12), dxgiAdapter(std::move(adapter)) { } }} // namespace dawn_native::d3d12