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/d3d/GrD3DPipelineState.h"
9
10 #include "include/private/SkTemplates.h"
11 #include "src/gpu/GrProgramInfo.h"
12 #include "src/gpu/GrStencilSettings.h"
13 #include "src/gpu/d3d/GrD3DBuffer.h"
14 #include "src/gpu/d3d/GrD3DGpu.h"
15 #include "src/gpu/d3d/GrD3DRootSignature.h"
16 #include "src/gpu/d3d/GrD3DTexture.h"
17 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
18 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
19 #include "src/gpu/glsl/GrGLSLXferProcessor.h"
20
GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState,sk_sp<GrD3DRootSignature> rootSignature,const GrGLSLBuiltinUniformHandles & builtinUniformHandles,const UniformInfoArray & uniforms,uint32_t uniformSize,uint32_t numSamplers,std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,std::unique_ptr<GrGLSLXferProcessor> xferProcessor,std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,size_t vertexStride,size_t instanceStride)21 GrD3DPipelineState::GrD3DPipelineState(
22 gr_cp<ID3D12PipelineState> pipelineState,
23 sk_sp<GrD3DRootSignature> rootSignature,
24 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
25 const UniformInfoArray& uniforms, uint32_t uniformSize,
26 uint32_t numSamplers,
27 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
28 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
29 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
30 size_t vertexStride,
31 size_t instanceStride)
32 : fPipelineState(std::move(pipelineState))
33 , fRootSignature(std::move(rootSignature))
34 , fBuiltinUniformHandles(builtinUniformHandles)
35 , fGeometryProcessor(std::move(geometryProcessor))
36 , fXferProcessor(std::move(xferProcessor))
37 , fFragmentProcessors(std::move(fragmentProcessors))
38 , fDataManager(uniforms, uniformSize)
39 , fNumSamplers(numSamplers)
40 , fVertexStride(vertexStride)
41 , fInstanceStride(instanceStride) {}
42
setAndBindConstants(GrD3DGpu * gpu,const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo)43 void GrD3DPipelineState::setAndBindConstants(GrD3DGpu* gpu,
44 const GrRenderTarget* renderTarget,
45 const GrProgramInfo& programInfo) {
46 this->setRenderTargetState(renderTarget, programInfo.origin());
47
48 fGeometryProcessor->setData(fDataManager, programInfo.primProc());
49 for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
50 auto& pipelineFP = programInfo.pipeline().getFragmentProcessor(i);
51 auto& baseGLSLFP = *fFragmentProcessors[i];
52 for (auto [fp, glslFP] : GrGLSLFragmentProcessor::ParallelRange(pipelineFP, baseGLSLFP)) {
53 glslFP.setData(fDataManager, fp);
54 }
55 }
56
57 {
58 SkIPoint offset;
59 GrTexture* dstTexture = programInfo.pipeline().peekDstTexture(&offset);
60
61 fXferProcessor->setData(fDataManager, programInfo.pipeline().getXferProcessor(),
62 dstTexture, offset);
63 }
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 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
73 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
74 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
75 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
76 }
77
78 // set RT adjustment
79 SkISize dimensions = rt->dimensions();
80 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
81 if (fRenderTargetState.fRenderTargetOrigin != origin ||
82 fRenderTargetState.fRenderTargetSize != dimensions) {
83 fRenderTargetState.fRenderTargetSize = dimensions;
84 fRenderTargetState.fRenderTargetOrigin = origin;
85
86 float rtAdjustmentVec[4];
87 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
88 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
89 }
90 }
91
setAndBindTextures(GrD3DGpu * gpu,const GrPrimitiveProcessor & primProc,const GrSurfaceProxy * const primProcTextures[],const GrPipeline & pipeline)92 void GrD3DPipelineState::setAndBindTextures(GrD3DGpu* gpu, const GrPrimitiveProcessor& primProc,
93 const GrSurfaceProxy* const primProcTextures[],
94 const GrPipeline& pipeline) {
95 SkASSERT(primProcTextures || !primProc.numTextureSamplers());
96
97 std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> shaderResourceViews(fNumSamplers);
98 std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> samplers(fNumSamplers);
99 unsigned int currTextureBinding = 0;
100
101 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
102 SkASSERT(primProcTextures[i]->asTextureProxy());
103 const auto& sampler = primProc.textureSampler(i);
104 auto texture = static_cast<GrD3DTexture*>(primProcTextures[i]->peekTexture());
105 shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
106 samplers[currTextureBinding++] =
107 gpu->resourceProvider().findOrCreateCompatibleSampler(sampler.samplerState());
108 gpu->currentCommandList()->addSampledTextureRef(texture);
109 }
110
111 pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
112 GrSamplerState samplerState = te.samplerState();
113 auto* texture = static_cast<GrD3DTexture*>(te.texture());
114 shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
115 samplers[currTextureBinding++] =
116 gpu->resourceProvider().findOrCreateCompatibleSampler(samplerState);
117 gpu->currentCommandList()->addSampledTextureRef(texture);
118 });
119
120 if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
121 auto texture = static_cast<GrD3DTexture*>(dstTexture);
122 shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
123 samplers[currTextureBinding++] = gpu->resourceProvider().findOrCreateCompatibleSampler(
124 GrSamplerState::Filter::kNearest);
125 gpu->currentCommandList()->addSampledTextureRef(texture);
126 }
127
128 SkASSERT(fNumSamplers == currTextureBinding);
129
130 // fill in descriptor tables and bind to root signature
131 if (fNumSamplers > 0) {
132 // set up and bind shader resource view table
133 sk_sp<GrD3DDescriptorTable> srvTable =
134 gpu->resourceProvider().findOrCreateShaderResourceTable(shaderResourceViews);
135 gpu->currentCommandList()->setGraphicsRootDescriptorTable(
136 static_cast<unsigned int>(GrD3DRootSignature::ParamIndex::kTextureDescriptorTable),
137 srvTable->baseGpuDescriptor());
138
139 // set up and bind sampler table
140 sk_sp<GrD3DDescriptorTable> samplerTable =
141 gpu->resourceProvider().findOrCreateSamplerTable(samplers);
142 gpu->currentCommandList()->setGraphicsRootDescriptorTable(
143 static_cast<unsigned int>(GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable),
144 samplerTable->baseGpuDescriptor());
145 }
146 }
147
bindBuffers(GrD3DGpu * gpu,sk_sp<const GrBuffer> indexBuffer,sk_sp<const GrBuffer> instanceBuffer,sk_sp<const GrBuffer> vertexBuffer,GrD3DDirectCommandList * commandList)148 void GrD3DPipelineState::bindBuffers(GrD3DGpu* gpu, sk_sp<const GrBuffer> indexBuffer,
149 sk_sp<const GrBuffer> instanceBuffer,
150 sk_sp<const GrBuffer> vertexBuffer,
151 GrD3DDirectCommandList* commandList) {
152 // Here our vertex and instance inputs need to match the same 0-based bindings they were
153 // assigned in the PipelineState. That is, vertex first (if any) followed by instance.
154 if (vertexBuffer) {
155 auto* d3dVertexBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer.get());
156 SkASSERT(!d3dVertexBuffer->isCpuBuffer());
157 SkASSERT(!d3dVertexBuffer->isMapped());
158 const_cast<GrD3DBuffer*>(d3dVertexBuffer)->setResourceState(
159 gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
160 }
161 if (instanceBuffer) {
162 auto* d3dInstanceBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer.get());
163 SkASSERT(!d3dInstanceBuffer->isCpuBuffer());
164 SkASSERT(!d3dInstanceBuffer->isMapped());
165 const_cast<GrD3DBuffer*>(d3dInstanceBuffer)->setResourceState(
166 gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
167 }
168 commandList->setVertexBuffers(0, std::move(vertexBuffer), fVertexStride,
169 std::move(instanceBuffer), fInstanceStride);
170
171 if (auto* d3dIndexBuffer = static_cast<const GrD3DBuffer*>(indexBuffer.get())) {
172 SkASSERT(!d3dIndexBuffer->isCpuBuffer());
173 SkASSERT(!d3dIndexBuffer->isMapped());
174 const_cast<GrD3DBuffer*>(d3dIndexBuffer)->setResourceState(
175 gpu, D3D12_RESOURCE_STATE_INDEX_BUFFER);
176 commandList->setIndexBuffer(std::move(indexBuffer));
177 }
178 }
179