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/RenderPassBuilderD3D12.h" 16 17 #include "dawn_native/Format.h" 18 #include "dawn_native/d3d12/CommandBufferD3D12.h" 19 #include "dawn_native/d3d12/Forward.h" 20 #include "dawn_native/d3d12/TextureD3D12.h" 21 22 #include "dawn_native/dawn_platform.h" 23 24 namespace dawn_native { namespace d3d12 { 25 26 namespace { D3D12BeginningAccessType(wgpu::LoadOp loadOp)27 D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE D3D12BeginningAccessType(wgpu::LoadOp loadOp) { 28 switch (loadOp) { 29 case wgpu::LoadOp::Clear: 30 return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR; 31 case wgpu::LoadOp::Load: 32 return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE; 33 } 34 } 35 D3D12EndingAccessType(wgpu::StoreOp storeOp)36 D3D12_RENDER_PASS_ENDING_ACCESS_TYPE D3D12EndingAccessType(wgpu::StoreOp storeOp) { 37 switch (storeOp) { 38 case wgpu::StoreOp::Discard: 39 return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD; 40 case wgpu::StoreOp::Store: 41 return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; 42 } 43 } 44 D3D12EndingAccessResolveParameters(wgpu::StoreOp storeOp,TextureView * resolveSource,TextureView * resolveDestination)45 D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS D3D12EndingAccessResolveParameters( 46 wgpu::StoreOp storeOp, 47 TextureView* resolveSource, 48 TextureView* resolveDestination) { 49 D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS resolveParameters; 50 51 resolveParameters.Format = resolveDestination->GetD3D12Format(); 52 resolveParameters.pSrcResource = 53 ToBackend(resolveSource->GetTexture())->GetD3D12Resource(); 54 resolveParameters.pDstResource = 55 ToBackend(resolveDestination->GetTexture())->GetD3D12Resource(); 56 57 // Clear or preserve the resolve source. 58 if (storeOp == wgpu::StoreOp::Discard) { 59 resolveParameters.PreserveResolveSource = false; 60 } else if (storeOp == wgpu::StoreOp::Store) { 61 resolveParameters.PreserveResolveSource = true; 62 } 63 64 // RESOLVE_MODE_AVERAGE is only valid for non-integer formats. 65 // TODO: Investigate and determine how integer format resolves should work in WebGPU. 66 switch (resolveDestination->GetFormat().GetAspectInfo(Aspect::Color).baseType) { 67 case wgpu::TextureComponentType::Sint: 68 case wgpu::TextureComponentType::Uint: 69 resolveParameters.ResolveMode = D3D12_RESOLVE_MODE_MAX; 70 break; 71 case wgpu::TextureComponentType::Float: 72 resolveParameters.ResolveMode = D3D12_RESOLVE_MODE_AVERAGE; 73 break; 74 75 case wgpu::TextureComponentType::DepthComparison: 76 UNREACHABLE(); 77 } 78 79 resolveParameters.SubresourceCount = 1; 80 81 return resolveParameters; 82 } 83 84 D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS D3D12EndingAccessResolveSubresourceParameters(TextureView * resolveDestination)85 D3D12EndingAccessResolveSubresourceParameters(TextureView* resolveDestination) { 86 D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS subresourceParameters; 87 Texture* resolveDestinationTexture = ToBackend(resolveDestination->GetTexture()); 88 ASSERT(resolveDestinationTexture->GetFormat().aspects == Aspect::Color); 89 90 subresourceParameters.DstX = 0; 91 subresourceParameters.DstY = 0; 92 subresourceParameters.SrcSubresource = 0; 93 subresourceParameters.DstSubresource = resolveDestinationTexture->GetSubresourceIndex( 94 resolveDestination->GetBaseMipLevel(), resolveDestination->GetBaseArrayLayer(), 95 Aspect::Color); 96 // Resolving a specified sub-rect is only valid on hardware that supports sample 97 // positions. This means even {0, 0, width, height} would be invalid if unsupported. To 98 // avoid this, we assume sub-rect resolves never work by setting them to all zeros or 99 // "empty" to resolve the entire region. 100 subresourceParameters.SrcRect = {0, 0, 0, 0}; 101 102 return subresourceParameters; 103 } 104 } // anonymous namespace 105 RenderPassBuilder(bool hasUAV)106 RenderPassBuilder::RenderPassBuilder(bool hasUAV) { 107 if (hasUAV) { 108 mRenderPassFlags = D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES; 109 } 110 } 111 SetRenderTargetView(ColorAttachmentIndex attachmentIndex,D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor)112 void RenderPassBuilder::SetRenderTargetView(ColorAttachmentIndex attachmentIndex, 113 D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor) { 114 ASSERT(mColorAttachmentCount < kMaxColorAttachmentsTyped); 115 mRenderTargetViews[attachmentIndex] = baseDescriptor; 116 mRenderPassRenderTargetDescriptors[attachmentIndex].cpuDescriptor = baseDescriptor; 117 mColorAttachmentCount++; 118 } 119 SetDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor)120 void RenderPassBuilder::SetDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor) { 121 mRenderPassDepthStencilDesc.cpuDescriptor = baseDescriptor; 122 } 123 GetColorAttachmentCount() const124 ColorAttachmentIndex RenderPassBuilder::GetColorAttachmentCount() const { 125 return mColorAttachmentCount; 126 } 127 HasDepth() const128 bool RenderPassBuilder::HasDepth() const { 129 return mHasDepth; 130 } 131 132 ityp::span<ColorAttachmentIndex, const D3D12_RENDER_PASS_RENDER_TARGET_DESC> GetRenderPassRenderTargetDescriptors() const133 RenderPassBuilder::GetRenderPassRenderTargetDescriptors() const { 134 return {mRenderPassRenderTargetDescriptors.data(), mColorAttachmentCount}; 135 } 136 137 const D3D12_RENDER_PASS_DEPTH_STENCIL_DESC* GetRenderPassDepthStencilDescriptor() const138 RenderPassBuilder::GetRenderPassDepthStencilDescriptor() const { 139 return &mRenderPassDepthStencilDesc; 140 } 141 GetRenderPassFlags() const142 D3D12_RENDER_PASS_FLAGS RenderPassBuilder::GetRenderPassFlags() const { 143 return mRenderPassFlags; 144 } 145 GetRenderTargetViews() const146 const D3D12_CPU_DESCRIPTOR_HANDLE* RenderPassBuilder::GetRenderTargetViews() const { 147 return mRenderTargetViews.data(); 148 } 149 SetRenderTargetBeginningAccess(ColorAttachmentIndex attachment,wgpu::LoadOp loadOp,dawn_native::Color clearColor,DXGI_FORMAT format)150 void RenderPassBuilder::SetRenderTargetBeginningAccess(ColorAttachmentIndex attachment, 151 wgpu::LoadOp loadOp, 152 dawn_native::Color clearColor, 153 DXGI_FORMAT format) { 154 mRenderPassRenderTargetDescriptors[attachment].BeginningAccess.Type = 155 D3D12BeginningAccessType(loadOp); 156 if (loadOp == wgpu::LoadOp::Clear) { 157 mRenderPassRenderTargetDescriptors[attachment] 158 .BeginningAccess.Clear.ClearValue.Color[0] = clearColor.r; 159 mRenderPassRenderTargetDescriptors[attachment] 160 .BeginningAccess.Clear.ClearValue.Color[1] = clearColor.g; 161 mRenderPassRenderTargetDescriptors[attachment] 162 .BeginningAccess.Clear.ClearValue.Color[2] = clearColor.b; 163 mRenderPassRenderTargetDescriptors[attachment] 164 .BeginningAccess.Clear.ClearValue.Color[3] = clearColor.a; 165 mRenderPassRenderTargetDescriptors[attachment].BeginningAccess.Clear.ClearValue.Format = 166 format; 167 } 168 } 169 SetRenderTargetEndingAccess(ColorAttachmentIndex attachment,wgpu::StoreOp storeOp)170 void RenderPassBuilder::SetRenderTargetEndingAccess(ColorAttachmentIndex attachment, 171 wgpu::StoreOp storeOp) { 172 mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Type = 173 D3D12EndingAccessType(storeOp); 174 } 175 SetRenderTargetEndingAccessResolve(ColorAttachmentIndex attachment,wgpu::StoreOp storeOp,TextureView * resolveSource,TextureView * resolveDestination)176 void RenderPassBuilder::SetRenderTargetEndingAccessResolve(ColorAttachmentIndex attachment, 177 wgpu::StoreOp storeOp, 178 TextureView* resolveSource, 179 TextureView* resolveDestination) { 180 mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Type = 181 D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE; 182 mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Resolve = 183 D3D12EndingAccessResolveParameters(storeOp, resolveSource, resolveDestination); 184 185 mSubresourceParams[attachment] = 186 D3D12EndingAccessResolveSubresourceParameters(resolveDestination); 187 188 mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Resolve.pSubresourceParameters = 189 &mSubresourceParams[attachment]; 190 } 191 SetDepthAccess(wgpu::LoadOp loadOp,wgpu::StoreOp storeOp,float clearDepth,DXGI_FORMAT format)192 void RenderPassBuilder::SetDepthAccess(wgpu::LoadOp loadOp, 193 wgpu::StoreOp storeOp, 194 float clearDepth, 195 DXGI_FORMAT format) { 196 mHasDepth = true; 197 mRenderPassDepthStencilDesc.DepthBeginningAccess.Type = D3D12BeginningAccessType(loadOp); 198 if (loadOp == wgpu::LoadOp::Clear) { 199 mRenderPassDepthStencilDesc.DepthBeginningAccess.Clear.ClearValue.DepthStencil.Depth = 200 clearDepth; 201 mRenderPassDepthStencilDesc.DepthBeginningAccess.Clear.ClearValue.Format = format; 202 } 203 mRenderPassDepthStencilDesc.DepthEndingAccess.Type = D3D12EndingAccessType(storeOp); 204 } 205 SetStencilAccess(wgpu::LoadOp loadOp,wgpu::StoreOp storeOp,uint8_t clearStencil,DXGI_FORMAT format)206 void RenderPassBuilder::SetStencilAccess(wgpu::LoadOp loadOp, 207 wgpu::StoreOp storeOp, 208 uint8_t clearStencil, 209 DXGI_FORMAT format) { 210 mRenderPassDepthStencilDesc.StencilBeginningAccess.Type = D3D12BeginningAccessType(loadOp); 211 if (loadOp == wgpu::LoadOp::Clear) { 212 mRenderPassDepthStencilDesc.StencilBeginningAccess.Clear.ClearValue.DepthStencil 213 .Stencil = clearStencil; 214 mRenderPassDepthStencilDesc.StencilBeginningAccess.Clear.ClearValue.Format = format; 215 } 216 mRenderPassDepthStencilDesc.StencilEndingAccess.Type = D3D12EndingAccessType(storeOp); 217 } 218 SetDepthNoAccess()219 void RenderPassBuilder::SetDepthNoAccess() { 220 mRenderPassDepthStencilDesc.DepthBeginningAccess.Type = 221 D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS; 222 mRenderPassDepthStencilDesc.DepthEndingAccess.Type = 223 D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS; 224 } 225 SetDepthStencilNoAccess()226 void RenderPassBuilder::SetDepthStencilNoAccess() { 227 SetDepthNoAccess(); 228 SetStencilNoAccess(); 229 } 230 SetStencilNoAccess()231 void RenderPassBuilder::SetStencilNoAccess() { 232 mRenderPassDepthStencilDesc.StencilBeginningAccess.Type = 233 D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS; 234 mRenderPassDepthStencilDesc.StencilEndingAccess.Type = 235 D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS; 236 } 237 238 }} // namespace dawn_native::d3d12 239