xref: /aosp_15_r20/external/skia/src/gpu/ganesh/d3d/GrD3DPipelineState.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 #include "src/gpu/ganesh/d3d/GrD3DPipelineState.h"
9 
10 #include "include/private/base/SkTemplates.h"
11 #include "src/gpu/ganesh/GrFragmentProcessor.h"
12 #include "src/gpu/ganesh/GrGeometryProcessor.h"
13 #include "src/gpu/ganesh/GrProgramInfo.h"
14 #include "src/gpu/ganesh/GrStencilSettings.h"
15 #include "src/gpu/ganesh/GrXferProcessor.h"
16 #include "src/gpu/ganesh/d3d/GrD3DBuffer.h"
17 #include "src/gpu/ganesh/d3d/GrD3DGpu.h"
18 #include "src/gpu/ganesh/d3d/GrD3DPipeline.h"
19 #include "src/gpu/ganesh/d3d/GrD3DRootSignature.h"
20 #include "src/gpu/ganesh/d3d/GrD3DTexture.h"
21 #include "src/gpu/ganesh/effects/GrTextureEffect.h"
22 #include "src/sksl/SkSLCompiler.h"
23 
GrD3DPipelineState(sk_sp<GrD3DPipeline> pipeline,sk_sp<GrD3DRootSignature> rootSignature,const GrGLSLBuiltinUniformHandles & builtinUniformHandles,const UniformInfoArray & uniforms,uint32_t uniformSize,uint32_t numSamplers,std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,size_t vertexStride,size_t instanceStride)24 GrD3DPipelineState::GrD3DPipelineState(
25         sk_sp<GrD3DPipeline> pipeline,
26         sk_sp<GrD3DRootSignature> rootSignature,
27         const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
28         const UniformInfoArray& uniforms,
29         uint32_t uniformSize,
30         uint32_t numSamplers,
31         std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
32         std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
33         std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
34         size_t vertexStride,
35         size_t instanceStride)
36         : fPipeline(std::move(pipeline))
37         , fRootSignature(std::move(rootSignature))
38         , fBuiltinUniformHandles(builtinUniformHandles)
39         , fGPImpl(std::move(gpImpl))
40         , fXPImpl(std::move(xpImpl))
41         , fFPImpls(std::move(fpImpls))
42         , fDataManager(uniforms, uniformSize)
43         , fNumSamplers(numSamplers)
44         , fVertexStride(vertexStride)
45         , fInstanceStride(instanceStride) {}
46 
setAndBindConstants(GrD3DGpu * gpu,const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo)47 void GrD3DPipelineState::setAndBindConstants(GrD3DGpu* gpu,
48                                              const GrRenderTarget* renderTarget,
49                                              const GrProgramInfo& programInfo) {
50     this->setRenderTargetState(renderTarget, programInfo.origin());
51 
52     fGPImpl->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc());
53 
54     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
55         const auto& fp = programInfo.pipeline().getFragmentProcessor(i);
56         fp.visitWithImpls([&](const GrFragmentProcessor& fp,
57                               GrFragmentProcessor::ProgramImpl& impl) {
58             impl.setData(fDataManager, fp);
59         }, *fFPImpls[i]);
60     }
61 
62     programInfo.pipeline().setDstTextureUniforms(fDataManager, &fBuiltinUniformHandles);
63     fXPImpl->setData(fDataManager, programInfo.pipeline().getXferProcessor());
64 
65     D3D12_GPU_VIRTUAL_ADDRESS constantsAddress = fDataManager.uploadConstants(gpu);
66     gpu->currentCommandList()->setGraphicsRootConstantBufferView(
67         (unsigned int)(GrD3DRootSignature::ParamIndex::kConstantBufferView),
68         constantsAddress);
69 }
70 
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin)71 void GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
72     // Set RT adjustment and RT flip
73     SkISize dimensions = rt->dimensions();
74     SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
75     if (fRenderTargetState.fRenderTargetOrigin != origin ||
76         fRenderTargetState.fRenderTargetSize != dimensions) {
77         fRenderTargetState.fRenderTargetSize = dimensions;
78         fRenderTargetState.fRenderTargetOrigin = origin;
79 
80         // The client will mark a swap buffer as kTopLeft when making a SkSurface because
81         // D3D's framebuffer space has (0, 0) at the top left. This agrees with Skia's device
82         // coords. However, in NDC (-1, -1) is the bottom left. So we flip when origin is kTopLeft.
83         bool flip = (origin == kTopLeft_GrSurfaceOrigin);
84         std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip);
85         fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data());
86         if (fBuiltinUniformHandles.fRTFlipUni.isValid()) {
87             // Note above that framebuffer space has origin top left. So we need !flip here.
88             std::array<float, 2> d = SkSL::Compiler::GetRTFlipVector(rt->height(), !flip);
89             fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data());
90         }
91     }
92 }
93 
setAndBindTextures(GrD3DGpu * gpu,const GrGeometryProcessor & geomProc,const GrSurfaceProxy * const geomProcTextures[],const GrPipeline & pipeline)94 void GrD3DPipelineState::setAndBindTextures(GrD3DGpu* gpu,
95                                             const GrGeometryProcessor& geomProc,
96                                             const GrSurfaceProxy* const geomProcTextures[],
97                                             const GrPipeline& pipeline) {
98     SkASSERT(geomProcTextures || !geomProc.numTextureSamplers());
99 
100     std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> shaderResourceViews(fNumSamplers);
101     std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> samplers(fNumSamplers);
102     unsigned int currTextureBinding = 0;
103 
104     for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
105         SkASSERT(geomProcTextures[i]->asTextureProxy());
106         const auto& sampler = geomProc.textureSampler(i);
107         auto texture = static_cast<GrD3DTexture*>(geomProcTextures[i]->peekTexture());
108         shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
109         samplers[currTextureBinding++] =
110                 gpu->resourceProvider().findOrCreateCompatibleSampler(sampler.samplerState());
111         gpu->currentCommandList()->addSampledTextureRef(texture);
112     }
113 
114     if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
115         auto texture = static_cast<GrD3DTexture*>(dstTexture);
116         shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
117         samplers[currTextureBinding++] = gpu->resourceProvider().findOrCreateCompatibleSampler(
118                                                GrSamplerState::Filter::kNearest);
119         gpu->currentCommandList()->addSampledTextureRef(texture);
120     }
121 
122     pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
123         GrSamplerState samplerState = te.samplerState();
124         auto* texture = static_cast<GrD3DTexture*>(te.texture());
125         shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
126         samplers[currTextureBinding++] =
127                 gpu->resourceProvider().findOrCreateCompatibleSampler(samplerState);
128         gpu->currentCommandList()->addSampledTextureRef(texture);
129     });
130 
131     SkASSERT(fNumSamplers == currTextureBinding);
132 
133     // fill in descriptor tables and bind to root signature
134     if (fNumSamplers > 0) {
135         // set up descriptor tables and bind heaps
136         sk_sp<GrD3DDescriptorTable> srvTable =
137                 gpu->resourceProvider().findOrCreateShaderViewTable(shaderResourceViews);
138         sk_sp<GrD3DDescriptorTable> samplerTable =
139             gpu->resourceProvider().findOrCreateSamplerTable(samplers);
140         gpu->currentCommandList()->setDescriptorHeaps(srvTable->heap(), samplerTable->heap());
141 
142         // bind shader resource view table
143         gpu->currentCommandList()->setGraphicsRootDescriptorTable(
144                 (unsigned int)GrD3DRootSignature::ParamIndex::kShaderViewDescriptorTable,
145                 srvTable->baseGpuDescriptor());
146 
147         // bind sampler table
148         gpu->currentCommandList()->setGraphicsRootDescriptorTable(
149                 (unsigned int)GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable,
150                 samplerTable->baseGpuDescriptor());
151     }
152 }
153 
bindBuffers(GrD3DGpu * gpu,sk_sp<const GrBuffer> indexBuffer,sk_sp<const GrBuffer> instanceBuffer,sk_sp<const GrBuffer> vertexBuffer,GrD3DDirectCommandList * commandList)154 void GrD3DPipelineState::bindBuffers(GrD3DGpu* gpu, sk_sp<const GrBuffer> indexBuffer,
155                                      sk_sp<const GrBuffer> instanceBuffer,
156                                      sk_sp<const GrBuffer> vertexBuffer,
157                                      GrD3DDirectCommandList* commandList) {
158     // Here our vertex and instance inputs need to match the same 0-based bindings they were
159     // assigned in the PipelineState. That is, vertex first (if any) followed by instance.
160     if (vertexBuffer) {
161         auto* d3dVertexBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer.get());
162         SkASSERT(!d3dVertexBuffer->isCpuBuffer());
163         SkASSERT(!d3dVertexBuffer->isMapped());
164         const_cast<GrD3DBuffer*>(d3dVertexBuffer)->setResourceState(
165                 gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
166     }
167     if (instanceBuffer) {
168         auto* d3dInstanceBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer.get());
169         SkASSERT(!d3dInstanceBuffer->isCpuBuffer());
170         SkASSERT(!d3dInstanceBuffer->isMapped());
171         const_cast<GrD3DBuffer*>(d3dInstanceBuffer)->setResourceState(
172                 gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
173     }
174     commandList->setVertexBuffers(0, std::move(vertexBuffer), fVertexStride,
175                                   std::move(instanceBuffer), fInstanceStride);
176 
177     if (auto* d3dIndexBuffer = static_cast<const GrD3DBuffer*>(indexBuffer.get())) {
178         SkASSERT(!d3dIndexBuffer->isCpuBuffer());
179         SkASSERT(!d3dIndexBuffer->isMapped());
180         const_cast<GrD3DBuffer*>(d3dIndexBuffer)->setResourceState(
181                 gpu, D3D12_RESOURCE_STATE_INDEX_BUFFER);
182         commandList->setIndexBuffer(std::move(indexBuffer));
183     }
184 }
185