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 GrD3DPipelineState_DEFINED
9 #define GrD3DPipelineState_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/gpu/GrTypes.h"
13 #include "include/gpu/d3d/GrD3DTypes.h"
14 #include "src/gpu/GrManagedResource.h"
15 #include "src/gpu/d3d/GrD3DPipelineStateDataManager.h"
16 #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
17 
18 class GrD3DDirectCommandList;
19 class GrD3DGpu;
20 class GrD3DRootSignature;
21 class GrProgramInfo;
22 
23 class GrD3DPipelineState : public GrManagedResource {
24 public:
25     using UniformInfoArray = GrD3DPipelineStateDataManager::UniformInfoArray;
26 
27     GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState,
28                        sk_sp<GrD3DRootSignature> rootSignature,
29                        const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
30                        const UniformInfoArray& uniforms,
31                        uint32_t uniformSize,
32                        uint32_t numSamplers,
33                        std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
34                        std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
35                        std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragProcessors,
36                        size_t vertexStride,
37                        size_t instanceStride);
38 
39 #ifdef SK_TRACE_MANAGED_RESOURCES
40     /** Output a human-readable dump of this resource's information
41     */
dumpInfo()42     void dumpInfo() const override {
43         SkDebugf("GrD3DPipelineState: %p (%d refs)\n", fPipelineState.get(), this->getRefCnt());
44     }
45 #endif
46 
47     // This will be called right before this class is destroyed and there is no reason to explicitly
48     // release the fPipelineState cause the gr_cp will handle that in the dtor.
freeGPUData()49     void freeGPUData() const override {}
50 
pipelineState()51     ID3D12PipelineState* pipelineState() const { return fPipelineState.get(); }
rootSignature()52     const sk_sp<GrD3DRootSignature>& rootSignature() const { return fRootSignature; }
53 
54     void setAndBindConstants(GrD3DGpu*, const GrRenderTarget*, const GrProgramInfo&);
55 
56     void setAndBindTextures(GrD3DGpu*, const GrPrimitiveProcessor& primProc,
57                             const GrSurfaceProxy* const primProcTextures[],
58                             const GrPipeline& pipeline);
59 
60     void bindBuffers(GrD3DGpu*, sk_sp<const GrBuffer> indexBuffer,
61                      sk_sp<const GrBuffer> instanceBuffer, sk_sp<const GrBuffer> vertexBuffer,
62                      GrD3DDirectCommandList* commandList);
63 
64     // We can only cache non dirty uniform values until we submit a command list. After that, the
65     // next frame will get a completely different uniform buffer and/or offset into the buffer. Thus
66     // we need a way to mark them all as dirty during submit.
markUniformsDirty()67     void markUniformsDirty() { fDataManager.markDirty(); }
68 
69 private:
70     /**
71      * We use the RT's size and origin to adjust from Skia device space to d3d normalized device
72      * space and to make device space positions have the correct origin for processors that require
73      * them.
74      */
75     struct RenderTargetState {
76         SkISize         fRenderTargetSize;
77         GrSurfaceOrigin fRenderTargetOrigin;
78 
RenderTargetStateRenderTargetState79         RenderTargetState() { this->invalidate(); }
invalidateRenderTargetState80         void invalidate() {
81             fRenderTargetSize.fWidth = -1;
82             fRenderTargetSize.fHeight = -1;
83             fRenderTargetOrigin = (GrSurfaceOrigin)-1;
84         }
85 
86         /**
87         * Gets a float4 that adjusts the position from Skia device coords to D3D's normalized device
88         * coords. Assuming the transformed position, pos, is a homogeneous float3, the vec, v, is
89         * applied as such:
90         * pos.x = dot(v.xy, pos.xz)
91         * pos.y = dot(v.zw, pos.yz)
92         */
getRTAdjustmentVecRenderTargetState93         void getRTAdjustmentVec(float* destVec) {
94             destVec[0] = 2.f / fRenderTargetSize.fWidth;
95             destVec[1] = -1.f;
96             // D3D's NDC space is flipped from Vulkan and Metal
97             if (kTopLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
98                 destVec[2] = -2.f / fRenderTargetSize.fHeight;
99                 destVec[3] = 1.f;
100             } else {
101                 destVec[2] = 2.f / fRenderTargetSize.fHeight;
102                 destVec[3] = -1.f;
103             }
104         }
105     };
106 
107     // Helper for setData() that sets the view matrix and loads the render target height uniform
108     void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin);
109 
110     gr_cp<ID3D12PipelineState> fPipelineState;
111     sk_sp<GrD3DRootSignature> fRootSignature;
112 
113     // Tracks the current render target uniforms stored in the vertex buffer.
114     RenderTargetState fRenderTargetState;
115     GrGLSLBuiltinUniformHandles fBuiltinUniformHandles;
116 
117     // Processors in the GrD3DPipelineState
118     std::unique_ptr<GrGLSLPrimitiveProcessor> fGeometryProcessor;
119     std::unique_ptr<GrGLSLXferProcessor> fXferProcessor;
120     std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fFragmentProcessors;
121 
122     GrD3DPipelineStateDataManager fDataManager;
123 
124     unsigned int fNumSamplers;
125     size_t fVertexStride;
126     size_t fInstanceStride;
127 };
128 
129 #endif
130