• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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