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 #include "dawn_native/d3d12/AdapterD3D12.h" 16 17 #include "common/Constants.h" 18 #include "dawn_native/Instance.h" 19 #include "dawn_native/d3d12/BackendD3D12.h" 20 #include "dawn_native/d3d12/D3D12Error.h" 21 #include "dawn_native/d3d12/DeviceD3D12.h" 22 #include "dawn_native/d3d12/PlatformFunctions.h" 23 24 #include <locale> 25 #include <sstream> 26 27 namespace dawn_native { namespace d3d12 { 28 29 // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert 30 template <class Facet> 31 struct DeletableFacet : Facet { 32 template <class... Args> DeletableFacetdawn_native::d3d12::DeletableFacet33 DeletableFacet(Args&&... args) : Facet(std::forward<Args>(args)...) { 34 } 35 ~DeletableFacetdawn_native::d3d12::DeletableFacet36 ~DeletableFacet() { 37 } 38 }; 39 Adapter(Backend * backend,ComPtr<IDXGIAdapter3> hardwareAdapter)40 Adapter::Adapter(Backend* backend, ComPtr<IDXGIAdapter3> hardwareAdapter) 41 : AdapterBase(backend->GetInstance(), wgpu::BackendType::D3D12), 42 mHardwareAdapter(hardwareAdapter), 43 mBackend(backend) { 44 } 45 ~Adapter()46 Adapter::~Adapter() { 47 CleanUpDebugLayerFilters(); 48 } 49 GetDeviceInfo() const50 const D3D12DeviceInfo& Adapter::GetDeviceInfo() const { 51 return mDeviceInfo; 52 } 53 GetHardwareAdapter() const54 IDXGIAdapter3* Adapter::GetHardwareAdapter() const { 55 return mHardwareAdapter.Get(); 56 } 57 GetBackend() const58 Backend* Adapter::GetBackend() const { 59 return mBackend; 60 } 61 GetDevice() const62 ComPtr<ID3D12Device> Adapter::GetDevice() const { 63 return mD3d12Device; 64 } 65 Initialize()66 MaybeError Adapter::Initialize() { 67 // D3D12 cannot check for feature support without a device. 68 // Create the device to populate the adapter properties then reuse it when needed for actual 69 // rendering. 70 const PlatformFunctions* functions = GetBackend()->GetFunctions(); 71 if (FAILED(functions->d3d12CreateDevice(GetHardwareAdapter(), D3D_FEATURE_LEVEL_11_0, 72 _uuidof(ID3D12Device), &mD3d12Device))) { 73 return DAWN_INTERNAL_ERROR("D3D12CreateDevice failed"); 74 } 75 76 DAWN_TRY(InitializeDebugLayerFilters()); 77 78 DXGI_ADAPTER_DESC1 adapterDesc; 79 mHardwareAdapter->GetDesc1(&adapterDesc); 80 81 mPCIInfo.deviceId = adapterDesc.DeviceId; 82 mPCIInfo.vendorId = adapterDesc.VendorId; 83 84 DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this)); 85 86 if (adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) { 87 mAdapterType = wgpu::AdapterType::CPU; 88 } else { 89 mAdapterType = (mDeviceInfo.isUMA) ? wgpu::AdapterType::IntegratedGPU 90 : wgpu::AdapterType::DiscreteGPU; 91 } 92 93 // Get the adapter's name as a UTF8 string. 94 std::wstring_convert<DeletableFacet<std::codecvt<wchar_t, char, std::mbstate_t>>> converter( 95 "Error converting"); 96 mPCIInfo.name = converter.to_bytes(adapterDesc.Description); 97 98 // Convert the adapter's D3D12 driver version to a readable string like "24.21.13.9793". 99 LARGE_INTEGER umdVersion; 100 if (mHardwareAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &umdVersion) != 101 DXGI_ERROR_UNSUPPORTED) { 102 uint64_t encodedVersion = umdVersion.QuadPart; 103 104 std::ostringstream o; 105 o << "D3D12 driver version "; 106 o << ((encodedVersion >> 48) & 0xFFFF) << "."; 107 o << ((encodedVersion >> 32) & 0xFFFF) << "."; 108 o << ((encodedVersion >> 16) & 0xFFFF) << "."; 109 o << (encodedVersion & 0xFFFF); 110 mDriverDescription = o.str(); 111 } 112 113 InitializeSupportedExtensions(); 114 115 return {}; 116 } 117 InitializeSupportedExtensions()118 void Adapter::InitializeSupportedExtensions() { 119 mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC); 120 mSupportedExtensions.EnableExtension(Extension::PipelineStatisticsQuery); 121 mSupportedExtensions.EnableExtension(Extension::TimestampQuery); 122 if (mDeviceInfo.supportsShaderFloat16 && GetBackend()->GetFunctions()->IsDXCAvailable()) { 123 mSupportedExtensions.EnableExtension(Extension::ShaderFloat16); 124 } 125 } 126 InitializeDebugLayerFilters()127 MaybeError Adapter::InitializeDebugLayerFilters() { 128 if (!GetInstance()->IsBackendValidationEnabled()) { 129 return {}; 130 } 131 132 D3D12_MESSAGE_ID denyIds[] = { 133 134 // 135 // Permanent IDs: list of warnings that are not applicable 136 // 137 138 // Resource sub-allocation partially maps pre-allocated heaps. This means the 139 // entire physical addresses space may have no resources or have many resources 140 // assigned the same heap. 141 D3D12_MESSAGE_ID_HEAP_ADDRESS_RANGE_HAS_NO_RESOURCE, 142 D3D12_MESSAGE_ID_HEAP_ADDRESS_RANGE_INTERSECTS_MULTIPLE_BUFFERS, 143 144 // The debug layer validates pipeline objects when they are created. Dawn validates 145 // them when them when they are set. Therefore, since the issue is caught at a later 146 // time, we can silence this warnings. 147 D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_RENDERTARGETVIEW_NOT_SET, 148 149 // Adding a clear color during resource creation would require heuristics or delayed 150 // creation. 151 // https://crbug.com/dawn/418 152 D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE, 153 D3D12_MESSAGE_ID_CLEARDEPTHSTENCILVIEW_MISMATCHINGCLEARVALUE, 154 155 // Dawn enforces proper Unmaps at a later time. 156 // https://crbug.com/dawn/422 157 D3D12_MESSAGE_ID_EXECUTECOMMANDLISTS_GPU_WRITTEN_READBACK_RESOURCE_MAPPED, 158 159 // WebGPU allows empty scissors without empty viewports. 160 D3D12_MESSAGE_ID_DRAW_EMPTY_SCISSOR_RECTANGLE, 161 162 // 163 // Temporary IDs: list of warnings that should be fixed or promoted 164 // 165 166 // Remove after warning have been addressed 167 // https://crbug.com/dawn/421 168 D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_INCOMPATIBLE_RESOURCE_STATE, 169 170 // For small placed resource alignment, we first request the small alignment, which may 171 // get rejected and generate a debug error. Then, we request 0 to get the allowed 172 // allowed alignment. 173 D3D12_MESSAGE_ID_CREATERESOURCE_INVALIDALIGNMENT, 174 }; 175 176 // Create a retrieval filter with a deny list to suppress messages. 177 // Any messages remaining will be converted to Dawn errors. 178 D3D12_INFO_QUEUE_FILTER filter{}; 179 // Filter out info/message and only create errors from warnings or worse. 180 D3D12_MESSAGE_SEVERITY severities[] = { 181 D3D12_MESSAGE_SEVERITY_INFO, 182 D3D12_MESSAGE_SEVERITY_MESSAGE, 183 }; 184 filter.DenyList.NumSeverities = ARRAYSIZE(severities); 185 filter.DenyList.pSeverityList = severities; 186 filter.DenyList.NumIDs = ARRAYSIZE(denyIds); 187 filter.DenyList.pIDList = denyIds; 188 189 ComPtr<ID3D12InfoQueue> infoQueue; 190 ASSERT_SUCCESS(mD3d12Device.As(&infoQueue)); 191 192 // To avoid flooding the console, a storage-filter is also used to 193 // prevent messages from getting logged. 194 DAWN_TRY(CheckHRESULT(infoQueue->PushStorageFilter(&filter), 195 "ID3D12InfoQueue::PushStorageFilter")); 196 197 DAWN_TRY(CheckHRESULT(infoQueue->PushRetrievalFilter(&filter), 198 "ID3D12InfoQueue::PushRetrievalFilter")); 199 200 return {}; 201 } 202 CleanUpDebugLayerFilters()203 void Adapter::CleanUpDebugLayerFilters() { 204 if (!GetInstance()->IsBackendValidationEnabled()) { 205 return; 206 } 207 ComPtr<ID3D12InfoQueue> infoQueue; 208 ASSERT_SUCCESS(mD3d12Device.As(&infoQueue)); 209 infoQueue->PopRetrievalFilter(); 210 infoQueue->PopStorageFilter(); 211 } 212 CreateDeviceImpl(const DeviceDescriptor * descriptor)213 ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { 214 return Device::Create(this, descriptor); 215 } 216 217 }} // namespace dawn_native::d3d12 218