1 // Copyright 2019 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // D3D12Backend.cpp: contains the definition of symbols exported by D3D12Backend.h so that they 16 // can be compiled twice: once export (shared library), once not exported (static library) 17 18 #include "dawn_native/D3D12Backend.h" 19 20 #include "common/Log.h" 21 #include "common/Math.h" 22 #include "common/SwapChainUtils.h" 23 #include "dawn_native/d3d12/D3D11on12Util.h" 24 #include "dawn_native/d3d12/DeviceD3D12.h" 25 #include "dawn_native/d3d12/NativeSwapChainImplD3D12.h" 26 #include "dawn_native/d3d12/ResidencyManagerD3D12.h" 27 #include "dawn_native/d3d12/TextureD3D12.h" 28 29 namespace dawn_native { namespace d3d12 { 30 GetD3D12Device(WGPUDevice device)31 ComPtr<ID3D12Device> GetD3D12Device(WGPUDevice device) { 32 return ToBackend(FromAPI(device))->GetD3D12Device(); 33 } 34 CreateNativeSwapChainImpl(WGPUDevice device,HWND window)35 DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device, HWND window) { 36 Device* backendDevice = ToBackend(FromAPI(device)); 37 38 DawnSwapChainImplementation impl; 39 impl = CreateSwapChainImplementation(new NativeSwapChainImpl(backendDevice, window)); 40 impl.textureUsage = WGPUTextureUsage_Present; 41 42 return impl; 43 } 44 GetNativeSwapChainPreferredFormat(const DawnSwapChainImplementation * swapChain)45 WGPUTextureFormat GetNativeSwapChainPreferredFormat( 46 const DawnSwapChainImplementation* swapChain) { 47 NativeSwapChainImpl* impl = reinterpret_cast<NativeSwapChainImpl*>(swapChain->userData); 48 return static_cast<WGPUTextureFormat>(impl->GetPreferredFormat()); 49 } 50 ExternalImageDescriptorDXGISharedHandle()51 ExternalImageDescriptorDXGISharedHandle::ExternalImageDescriptorDXGISharedHandle() 52 : ExternalImageDescriptor(ExternalImageType::DXGISharedHandle) { 53 } 54 ExternalImageDXGI(ComPtr<ID3D12Resource> d3d12Resource,const WGPUTextureDescriptor * descriptor)55 ExternalImageDXGI::ExternalImageDXGI(ComPtr<ID3D12Resource> d3d12Resource, 56 const WGPUTextureDescriptor* descriptor) 57 : mD3D12Resource(std::move(d3d12Resource)), 58 mUsage(descriptor->usage), 59 mDimension(descriptor->dimension), 60 mSize(descriptor->size), 61 mFormat(descriptor->format), 62 mMipLevelCount(descriptor->mipLevelCount), 63 mSampleCount(descriptor->sampleCount) { 64 ASSERT(!descriptor->nextInChain || 65 descriptor->nextInChain->sType == WGPUSType_DawnTextureInternalUsageDescriptor); 66 if (descriptor->nextInChain) { 67 mUsageInternal = reinterpret_cast<const WGPUDawnTextureInternalUsageDescriptor*>( 68 descriptor->nextInChain) 69 ->internalUsage; 70 } 71 mD3D11on12ResourceCache = std::make_unique<D3D11on12ResourceCache>(); 72 } 73 74 ExternalImageDXGI::~ExternalImageDXGI() = default; 75 ProduceTexture(WGPUDevice device,const ExternalImageAccessDescriptorDXGIKeyedMutex * descriptor)76 WGPUTexture ExternalImageDXGI::ProduceTexture( 77 WGPUDevice device, 78 const ExternalImageAccessDescriptorDXGIKeyedMutex* descriptor) { 79 Device* backendDevice = ToBackend(FromAPI(device)); 80 81 // Ensure the texture usage is allowed 82 if (!IsSubset(descriptor->usage, mUsage)) { 83 dawn::ErrorLog() << "Texture usage is not valid for external image"; 84 return nullptr; 85 } 86 87 TextureDescriptor textureDescriptor = {}; 88 textureDescriptor.usage = static_cast<wgpu::TextureUsage>(descriptor->usage); 89 textureDescriptor.dimension = static_cast<wgpu::TextureDimension>(mDimension); 90 textureDescriptor.size = {mSize.width, mSize.height, mSize.depthOrArrayLayers}; 91 textureDescriptor.format = static_cast<wgpu::TextureFormat>(mFormat); 92 textureDescriptor.mipLevelCount = mMipLevelCount; 93 textureDescriptor.sampleCount = mSampleCount; 94 95 DawnTextureInternalUsageDescriptor internalDesc = {}; 96 if (mUsageInternal) { 97 textureDescriptor.nextInChain = &internalDesc; 98 internalDesc.internalUsage = static_cast<wgpu::TextureUsage>(mUsageInternal); 99 internalDesc.sType = wgpu::SType::DawnTextureInternalUsageDescriptor; 100 } 101 102 Ref<D3D11on12ResourceCacheEntry> d3d11on12Resource = 103 mD3D11on12ResourceCache->GetOrCreateD3D11on12Resource(device, mD3D12Resource.Get()); 104 if (d3d11on12Resource == nullptr) { 105 dawn::ErrorLog() << "Unable to create 11on12 resource for external image"; 106 return nullptr; 107 } 108 109 Ref<TextureBase> texture = backendDevice->CreateExternalTexture( 110 &textureDescriptor, mD3D12Resource, std::move(d3d11on12Resource), 111 ExternalMutexSerial(descriptor->acquireMutexKey), 112 ExternalMutexSerial(descriptor->releaseMutexKey), descriptor->isSwapChainTexture, 113 descriptor->isInitialized); 114 115 return ToAPI(texture.Detach()); 116 } 117 118 // static Create(WGPUDevice device,const ExternalImageDescriptorDXGISharedHandle * descriptor)119 std::unique_ptr<ExternalImageDXGI> ExternalImageDXGI::Create( 120 WGPUDevice device, 121 const ExternalImageDescriptorDXGISharedHandle* descriptor) { 122 Device* backendDevice = ToBackend(FromAPI(device)); 123 124 Microsoft::WRL::ComPtr<ID3D12Resource> d3d12Resource; 125 if (FAILED(backendDevice->GetD3D12Device()->OpenSharedHandle( 126 descriptor->sharedHandle, IID_PPV_ARGS(&d3d12Resource)))) { 127 return nullptr; 128 } 129 130 const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor); 131 132 if (backendDevice->ConsumedError( 133 ValidateTextureDescriptor(backendDevice, textureDescriptor))) { 134 return nullptr; 135 } 136 137 if (backendDevice->ConsumedError( 138 ValidateTextureDescriptorCanBeWrapped(textureDescriptor), 139 "validating that a D3D12 external image can be wrapped with %s", 140 textureDescriptor)) { 141 return nullptr; 142 } 143 144 if (backendDevice->ConsumedError( 145 ValidateD3D12TextureCanBeWrapped(d3d12Resource.Get(), textureDescriptor))) { 146 return nullptr; 147 } 148 149 // Shared handle is assumed to support resource sharing capability. The resource 150 // shared capability tier must agree to share resources between D3D devices. 151 const Format* format = 152 backendDevice->GetInternalFormat(textureDescriptor->format).AcquireSuccess(); 153 if (format->IsMultiPlanar()) { 154 if (backendDevice->ConsumedError(ValidateD3D12VideoTextureCanBeShared( 155 backendDevice, D3D12TextureFormat(textureDescriptor->format)))) { 156 return nullptr; 157 } 158 } 159 160 std::unique_ptr<ExternalImageDXGI> result( 161 new ExternalImageDXGI(std::move(d3d12Resource), descriptor->cTextureDescriptor)); 162 return result; 163 } 164 SetExternalMemoryReservation(WGPUDevice device,uint64_t requestedReservationSize,MemorySegment memorySegment)165 uint64_t SetExternalMemoryReservation(WGPUDevice device, 166 uint64_t requestedReservationSize, 167 MemorySegment memorySegment) { 168 Device* backendDevice = ToBackend(FromAPI(device)); 169 170 return backendDevice->GetResidencyManager()->SetExternalMemoryReservation( 171 memorySegment, requestedReservationSize); 172 } 173 AdapterDiscoveryOptions()174 AdapterDiscoveryOptions::AdapterDiscoveryOptions() 175 : AdapterDiscoveryOptionsBase(WGPUBackendType_D3D12), dxgiAdapter(nullptr) { 176 } 177 AdapterDiscoveryOptions(ComPtr<IDXGIAdapter> adapter)178 AdapterDiscoveryOptions::AdapterDiscoveryOptions(ComPtr<IDXGIAdapter> adapter) 179 : AdapterDiscoveryOptionsBase(WGPUBackendType_D3D12), dxgiAdapter(std::move(adapter)) { 180 } 181 }} // namespace dawn_native::d3d12 182