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