1 /*
2  * Copyright 2020 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrD3DCommandList_DEFINED
9 #define GrD3DCommandList_DEFINED
10 
11 #include "include/gpu/GrTypes.h"
12 #include "include/gpu/d3d/GrD3DTypes.h"
13 #include "include/private/SkColorData.h"
14 #include "src/gpu/GrManagedResource.h"
15 #include "src/gpu/GrRingBuffer.h"
16 #include "src/gpu/d3d/GrD3DRootSignature.h"
17 
18 #include <memory>
19 
20 class GrD3DGpu;
21 class GrD3DBuffer;
22 class GrD3DCommandSignature;
23 class GrD3DConstantRingBuffer;
24 class GrD3DPipelineState;
25 class GrD3DRenderTarget;
26 class GrD3DRootSignature;
27 class GrD3DAttachment;
28 class GrD3DTexture;
29 class GrD3DTextureResource;
30 
31 class GrScissorState;
32 
33 class GrD3DCommandList {
34 public:
~GrD3DCommandList()35     virtual ~GrD3DCommandList() {
36         this->releaseResources();
37     }
38 
39     enum class SubmitResult {
40         kNoWork,
41         kSuccess,
42         kFailure,
43     };
44     SubmitResult submit(ID3D12CommandQueue* queue);
45 
46     bool close();
47     void reset();
48 
49     ////////////////////////////////////////////////////////////////////////////
50     // GraphicsCommandList commands
51     ////////////////////////////////////////////////////////////////////////////
52 
53     // For the moment we only support Transition barriers
54     // All barriers should reference subresources of managedResource
55     void resourceBarrier(sk_sp<GrManagedResource> managedResource,
56                          int numBarriers,
57                          const D3D12_RESOURCE_TRANSITION_BARRIER* barriers);
58 
59     // Helper method that calls copyTextureRegion multiple times, once for each subresource
60     // The srcBuffer comes from a staging buffer so we don't need to take any refs to it. Instead,
61     // we ref the whole buffer during sumbit.
62     void copyBufferToTexture(ID3D12Resource* srcBuffer,
63                              const GrD3DTextureResource* dstTexture,
64                              uint32_t subresourceCount,
65                              D3D12_PLACED_SUBRESOURCE_FOOTPRINT* bufferFootprints,
66                              int left, int top);
67 
68     void copyTextureRegionToTexture(sk_sp<GrManagedResource> dst,
69                                     const D3D12_TEXTURE_COPY_LOCATION* dstLocation,
70                                     UINT dstX, UINT dstY,
71                                     sk_sp<GrManagedResource> src,
72                                     const D3D12_TEXTURE_COPY_LOCATION* srcLocation,
73                                     const D3D12_BOX* srcBox);
74 
75      void copyTextureRegionToBuffer(sk_sp<const GrBuffer> dst,
76                                     const D3D12_TEXTURE_COPY_LOCATION* dstLocation,
77                                     UINT dstX,
78                                     UINT dstY,
79                                     sk_sp<GrManagedResource> src,
80                                     const D3D12_TEXTURE_COPY_LOCATION* srcLocation,
81                                     const D3D12_BOX* srcBox);
82 
83     // We don't take a ref to the src buffer because we assume the src buffer is coming from a
84     // staging buffer which will get ref'd during submit.
85     void copyBufferToBuffer(sk_sp<GrD3DBuffer> dstBuffer, uint64_t dstOffset,
86                             ID3D12Resource* srcBuffer, uint64_t srcOffset,
87                             uint64_t numBytes);
88 
addGrBuffer(sk_sp<const GrBuffer> buffer)89     void addGrBuffer(sk_sp<const GrBuffer> buffer) {
90         fTrackedGpuBuffers.push_back(std::move(buffer));
91     }
92 
93     void releaseResources();
94 
hasWork()95     bool hasWork() const { return fHasWork; }
96 
97     void addFinishedCallback(sk_sp<GrRefCntedCallback> callback);
98 
99 private:
100     static const int kInitialTrackedResourcesCount = 32;
101 
102 protected:
103     GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,
104                      gr_cp<ID3D12GraphicsCommandList> commandList);
105 
106     // Add ref-counted resource that will be tracked and released when this command buffer finishes
107     // execution
addResource(sk_sp<GrManagedResource> resource)108     void addResource(sk_sp<GrManagedResource> resource) {
109         SkASSERT(resource);
110         resource->notifyQueuedForWorkOnGpu();
111         fTrackedResources.push_back(std::move(resource));
112     }
113 
114     // Add ref-counted resource that will be tracked and released when this command buffer finishes
115     // execution. When it is released, it will signal that the resource can be recycled for reuse.
addRecycledResource(sk_sp<GrRecycledResource> resource)116     void addRecycledResource(sk_sp<GrRecycledResource> resource) {
117         resource->notifyQueuedForWorkOnGpu();
118         fTrackedRecycledResources.push_back(std::move(resource));
119     }
120 
121     void addingWork();
onReset()122     virtual void onReset() {}
123 
124     void submitResourceBarriers();
125 
126     gr_cp<ID3D12GraphicsCommandList> fCommandList;
127 
128     SkSTArray<kInitialTrackedResourcesCount, sk_sp<GrManagedResource>> fTrackedResources;
129     SkSTArray<kInitialTrackedResourcesCount, sk_sp<GrRecycledResource>> fTrackedRecycledResources;
130     SkSTArray<kInitialTrackedResourcesCount, sk_sp<const GrBuffer>> fTrackedGpuBuffers;
131 
132 
133     // When we create a command list it starts in an active recording state
134     SkDEBUGCODE(bool fIsActive = true;)
135     bool fHasWork = false;
136 
137 private:
callFinishedCallbacks()138     void callFinishedCallbacks() { fFinishedCallbacks.reset(); }
139 
140     gr_cp<ID3D12CommandAllocator> fAllocator;
141 
142     SkSTArray<4, D3D12_RESOURCE_BARRIER> fResourceBarriers;
143 
144     SkTArray<sk_sp<GrRefCntedCallback>> fFinishedCallbacks;
145 };
146 
147 class GrD3DDirectCommandList : public GrD3DCommandList {
148 public:
149     static std::unique_ptr<GrD3DDirectCommandList> Make(ID3D12Device* device);
150 
151     ~GrD3DDirectCommandList() override = default;
152 
153     void setPipelineState(sk_sp<GrD3DPipelineState> pipelineState);
154 
155     void setStencilRef(unsigned int stencilRef);
156     void setBlendFactor(const float blendFactor[4]);
157     void setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology);
158     void setScissorRects(unsigned int numRects, const D3D12_RECT* rects);
159     void setViewports(unsigned int numViewports, const D3D12_VIEWPORT* viewports);
160     void setCenteredSamplePositions(unsigned int numSamples);
161     void setDefaultSamplePositions();
162     void setGraphicsRootSignature(const sk_sp<GrD3DRootSignature>& rootSignature);
163     void setVertexBuffers(unsigned int startSlot,
164                           sk_sp<const GrBuffer> vertexBuffer, size_t vertexStride,
165                           sk_sp<const GrBuffer> instanceBuffer, size_t instanceStride);
166     void setIndexBuffer(sk_sp<const GrBuffer> indexBuffer);
167     void drawInstanced(unsigned int vertexCount, unsigned int instanceCount,
168                        unsigned int startVertex, unsigned int startInstance);
169     void drawIndexedInstanced(unsigned int indexCount, unsigned int instanceCount,
170                               unsigned int startIndex, unsigned int baseVertex,
171                               unsigned int startInstance);
172     void executeIndirect(const sk_sp<GrD3DCommandSignature> commandSig, unsigned int maxCommandCnt,
173                          const GrD3DBuffer* argumentBuffer, size_t argumentBufferOffset);
174 
175     void clearRenderTargetView(const GrD3DRenderTarget* renderTarget, const SkPMColor4f& color,
176                                const D3D12_RECT* rect);
177     void clearDepthStencilView(const GrD3DAttachment*,
178                                uint8_t stencilClearValue,
179                                const D3D12_RECT* rect);
180     void setRenderTarget(const GrD3DRenderTarget* renderTarget);
181     void resolveSubresourceRegion(const GrD3DTextureResource* dstTexture,
182                                   unsigned int dstX, unsigned int dstY,
183                                   const GrD3DTextureResource* srcTexture,
184                                   D3D12_RECT* srcRect);
185 
186     void setGraphicsRootConstantBufferView(unsigned int rootParameterIndex,
187                                            D3D12_GPU_VIRTUAL_ADDRESS bufferLocation);
188     void setGraphicsRootDescriptorTable(unsigned int rootParameterIndex,
189                                         D3D12_GPU_DESCRIPTOR_HANDLE bufferLocation);
190     void setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource,
191                             ID3D12DescriptorHeap* srvDescriptorHeap,
192                             sk_sp<GrRecycledResource> samplerHeapResource,
193                             ID3D12DescriptorHeap* samplerDescriptorHeap);
194 
195     void addSampledTextureRef(GrD3DTexture*);
196 
197 private:
198     GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,
199                            gr_cp<ID3D12GraphicsCommandList> commandList);
200 
201     void onReset() override;
202 
203     const GrD3DPipelineState* fCurrentPipelineState;
204     const GrD3DRootSignature* fCurrentRootSignature;
205     const GrBuffer* fCurrentVertexBuffer;
206     size_t fCurrentVertexStride;
207     const GrBuffer* fCurrentInstanceBuffer;
208     size_t fCurrentInstanceStride;
209     const GrBuffer* fCurrentIndexBuffer;
210     bool fUsingCenteredSamples;
211 
212     D3D12_GPU_VIRTUAL_ADDRESS fCurrentConstantBufferAddress;
213     D3D12_GPU_DESCRIPTOR_HANDLE fCurrentRootDescriptorTable[GrD3DRootSignature::kParamIndexCount];
214     const ID3D12DescriptorHeap* fCurrentSRVCRVDescriptorHeap;
215     const ID3D12DescriptorHeap* fCurrentSamplerDescriptorHeap;
216 };
217 
218 class GrD3DCopyCommandList : public GrD3DCommandList {
219 public:
220     static std::unique_ptr<GrD3DCopyCommandList> Make(ID3D12Device* device);
221 
222 private:
223     GrD3DCopyCommandList(gr_cp<ID3D12CommandAllocator> allocator,
224                          gr_cp<ID3D12GraphicsCommandList> commandList);
225 };
226 #endif
227