1 /*
2 * Copyright 2016 Google Inc.
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 "include/gpu/GrContext.h"
9 #include "src/core/SkMipMap.h"
10 #include "src/gpu/GrContextPriv.h"
11 #include "src/gpu/GrPipeline.h"
12 #include "src/gpu/GrRenderTarget.h"
13 #include "src/gpu/GrTexturePriv.h"
14 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
15 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
16 #include "src/gpu/glsl/GrGLSLXferProcessor.h"
17 #include "src/gpu/vk/GrVkCommandBuffer.h"
18 #include "src/gpu/vk/GrVkDescriptorPool.h"
19 #include "src/gpu/vk/GrVkDescriptorSet.h"
20 #include "src/gpu/vk/GrVkGpu.h"
21 #include "src/gpu/vk/GrVkImageView.h"
22 #include "src/gpu/vk/GrVkMemory.h"
23 #include "src/gpu/vk/GrVkPipeline.h"
24 #include "src/gpu/vk/GrVkPipelineState.h"
25 #include "src/gpu/vk/GrVkSampler.h"
26 #include "src/gpu/vk/GrVkTexture.h"
27 #include "src/gpu/vk/GrVkUniformBuffer.h"
28
GrVkPipelineState(GrVkGpu * gpu,GrVkPipeline * pipeline,const GrVkDescriptorSetManager::Handle & samplerDSHandle,const GrGLSLBuiltinUniformHandles & builtinUniformHandles,const UniformInfoArray & uniforms,uint32_t uniformSize,const UniformInfoArray & samplers,std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,std::unique_ptr<GrGLSLXferProcessor> xferProcessor,std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,int fragmentProcessorCnt)29 GrVkPipelineState::GrVkPipelineState(
30 GrVkGpu* gpu,
31 GrVkPipeline* pipeline,
32 const GrVkDescriptorSetManager::Handle& samplerDSHandle,
33 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
34 const UniformInfoArray& uniforms,
35 uint32_t uniformSize,
36 const UniformInfoArray& samplers,
37 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
38 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
39 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
40 int fragmentProcessorCnt)
41 : fPipeline(pipeline)
42 , fSamplerDSHandle(samplerDSHandle)
43 , fBuiltinUniformHandles(builtinUniformHandles)
44 , fGeometryProcessor(std::move(geometryProcessor))
45 , fXferProcessor(std::move(xferProcessor))
46 , fFragmentProcessors(std::move(fragmentProcessors))
47 , fFragmentProcessorCnt(fragmentProcessorCnt)
48 , fDataManager(uniforms, uniformSize) {
49 fUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, uniformSize));
50
51 fNumSamplers = samplers.count();
52 for (const auto& sampler : samplers.items()) {
53 // We store the immutable samplers here and take ownership of the ref from the
54 // GrVkUnformHandler.
55 fImmutableSamplers.push_back(sampler.fImmutableSampler);
56 }
57 }
58
~GrVkPipelineState()59 GrVkPipelineState::~GrVkPipelineState() {
60 // Must have freed all GPU resources before this is destroyed
61 SkASSERT(!fPipeline);
62 }
63
freeGPUResources()64 void GrVkPipelineState::freeGPUResources() {
65 if (fPipeline) {
66 fPipeline->unref();
67 fPipeline = nullptr;
68 }
69
70 if (fUniformBuffer) {
71 fUniformBuffer->release();
72 fUniformBuffer.reset();
73 }
74 }
75
setAndBindUniforms(GrVkGpu * gpu,const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,GrVkCommandBuffer * commandBuffer)76 bool GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu,
77 const GrRenderTarget* renderTarget,
78 const GrProgramInfo& programInfo,
79 GrVkCommandBuffer* commandBuffer) {
80 this->setRenderTargetState(renderTarget, programInfo.origin());
81
82 GrFragmentProcessor::PipelineCoordTransformRange transformRange(programInfo.pipeline());
83 fGeometryProcessor->setData(fDataManager, programInfo.primProc(), transformRange);
84 GrFragmentProcessor::CIter fpIter(programInfo.pipeline());
85 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
86 for (; fpIter && glslIter; ++fpIter, ++glslIter) {
87 glslIter->setData(fDataManager, *fpIter);
88 }
89 SkASSERT(!fpIter && !glslIter);
90
91 {
92 SkIPoint offset;
93 GrTexture* dstTexture = programInfo.pipeline().peekDstTexture(&offset);
94
95 fXferProcessor->setData(fDataManager, programInfo.pipeline().getXferProcessor(),
96 dstTexture, offset);
97 }
98
99 // Get new descriptor set
100 if (fUniformBuffer) {
101 fDataManager.uploadUniformBuffers(gpu, fUniformBuffer.get());
102 static const int kUniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet;
103 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), kUniformDSIdx, 1,
104 fUniformBuffer->descriptorSet(), 0, nullptr);
105 commandBuffer->addRecycledResource(fUniformBuffer->resource());
106 }
107 return true;
108 }
109
setAndBindTextures(GrVkGpu * gpu,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrSurfaceProxy * const primProcTextures[],GrVkCommandBuffer * commandBuffer)110 bool GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu,
111 const GrPrimitiveProcessor& primProc,
112 const GrPipeline& pipeline,
113 const GrSurfaceProxy* const primProcTextures[],
114 GrVkCommandBuffer* commandBuffer) {
115 SkASSERT(primProcTextures || !primProc.numTextureSamplers());
116
117 struct SamplerBindings {
118 GrSamplerState fState;
119 GrVkTexture* fTexture;
120 };
121 SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers);
122 int currTextureBinding = 0;
123
124 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
125 SkASSERT(primProcTextures[i]->asTextureProxy());
126 const auto& sampler = primProc.textureSampler(i);
127 auto texture = static_cast<GrVkTexture*>(primProcTextures[i]->peekTexture());
128 samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture};
129 }
130
131 GrFragmentProcessor::CIter fpIter(pipeline);
132 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
133 for (; fpIter && glslIter; ++fpIter, ++glslIter) {
134 for (int i = 0; i < fpIter->numTextureSamplers(); ++i) {
135 const auto& sampler = fpIter->textureSampler(i);
136 samplerBindings[currTextureBinding++] =
137 {sampler.samplerState(), static_cast<GrVkTexture*>(sampler.peekTexture())};
138 }
139 }
140 SkASSERT(!fpIter && !glslIter);
141
142 if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
143 samplerBindings[currTextureBinding++] = {
144 GrSamplerState::Filter::kNearest, static_cast<GrVkTexture*>(dstTexture)};
145 }
146
147 // Get new descriptor set
148 SkASSERT(fNumSamplers == currTextureBinding);
149 if (fNumSamplers) {
150 static const int kSamplerDSIdx = GrVkUniformHandler::kSamplerDescSet;
151
152 if (fNumSamplers == 1) {
153 auto texture = samplerBindings[0].fTexture;
154 const auto& samplerState = samplerBindings[0].fState;
155 const GrVkDescriptorSet* descriptorSet = texture->cachedSingleDescSet(samplerState);
156 if (descriptorSet) {
157 commandBuffer->addResource(texture->textureView());
158 commandBuffer->addResource(texture->resource());
159 commandBuffer->addRecycledResource(descriptorSet);
160 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), kSamplerDSIdx, 1,
161 descriptorSet->descriptorSet(), 0, nullptr);
162 return true;
163 }
164 }
165
166 const GrVkDescriptorSet* descriptorSet =
167 gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
168 if (!descriptorSet) {
169 return false;
170 }
171
172 for (int i = 0; i < fNumSamplers; ++i) {
173 GrSamplerState state = samplerBindings[i].fState;
174 GrVkTexture* texture = samplerBindings[i].fTexture;
175
176 const GrVkImageView* textureView = texture->textureView();
177 const GrVkSampler* sampler = nullptr;
178 if (fImmutableSamplers[i]) {
179 sampler = fImmutableSamplers[i];
180 } else {
181 sampler = gpu->resourceProvider().findOrCreateCompatibleSampler(
182 state, texture->ycbcrConversionInfo());
183 }
184 SkASSERT(sampler);
185
186 VkDescriptorImageInfo imageInfo;
187 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
188 imageInfo.sampler = sampler->sampler();
189 imageInfo.imageView = textureView->imageView();
190 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
191
192 VkWriteDescriptorSet writeInfo;
193 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
194 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
195 writeInfo.pNext = nullptr;
196 writeInfo.dstSet = *descriptorSet->descriptorSet();
197 writeInfo.dstBinding = i;
198 writeInfo.dstArrayElement = 0;
199 writeInfo.descriptorCount = 1;
200 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
201 writeInfo.pImageInfo = &imageInfo;
202 writeInfo.pBufferInfo = nullptr;
203 writeInfo.pTexelBufferView = nullptr;
204
205 GR_VK_CALL(gpu->vkInterface(),
206 UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
207 commandBuffer->addResource(sampler);
208 if (!fImmutableSamplers[i]) {
209 sampler->unref();
210 }
211 commandBuffer->addResource(samplerBindings[i].fTexture->textureView());
212 commandBuffer->addResource(samplerBindings[i].fTexture->resource());
213 }
214 if (fNumSamplers == 1) {
215 GrSamplerState state = samplerBindings[0].fState;
216 GrVkTexture* texture = samplerBindings[0].fTexture;
217 texture->addDescriptorSetToCache(descriptorSet, state);
218 }
219
220 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), kSamplerDSIdx, 1,
221 descriptorSet->descriptorSet(), 0, nullptr);
222 commandBuffer->addRecycledResource(descriptorSet);
223 descriptorSet->recycle();
224 }
225 return true;
226 }
227
set_uniform_descriptor_writes(VkWriteDescriptorSet * descriptorWrite,VkDescriptorBufferInfo * bufferInfo,const GrVkUniformBuffer * buffer,VkDescriptorSet descriptorSet)228 void set_uniform_descriptor_writes(VkWriteDescriptorSet* descriptorWrite,
229 VkDescriptorBufferInfo* bufferInfo,
230 const GrVkUniformBuffer* buffer,
231 VkDescriptorSet descriptorSet) {
232
233 memset(bufferInfo, 0, sizeof(VkDescriptorBufferInfo));
234 bufferInfo->buffer = buffer->buffer();
235 bufferInfo->offset = buffer->offset();
236 bufferInfo->range = buffer->size();
237
238 memset(descriptorWrite, 0, sizeof(VkWriteDescriptorSet));
239 descriptorWrite->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
240 descriptorWrite->pNext = nullptr;
241 descriptorWrite->dstSet = descriptorSet;
242 descriptorWrite->dstBinding = GrVkUniformHandler::kUniformBinding;
243 descriptorWrite->dstArrayElement = 0;
244 descriptorWrite->descriptorCount = 1;
245 descriptorWrite->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
246 descriptorWrite->pImageInfo = nullptr;
247 descriptorWrite->pBufferInfo = bufferInfo;
248 descriptorWrite->pTexelBufferView = nullptr;
249 }
250
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin)251 void GrVkPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
252
253 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
254 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
255 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
256 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
257 }
258
259 // set RT adjustment
260 SkISize dimensions = rt->dimensions();
261 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
262 if (fRenderTargetState.fRenderTargetOrigin != origin ||
263 fRenderTargetState.fRenderTargetSize != dimensions) {
264 fRenderTargetState.fRenderTargetSize = dimensions;
265 fRenderTargetState.fRenderTargetOrigin = origin;
266
267 float rtAdjustmentVec[4];
268 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
269 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
270 }
271 }
272
bindPipeline(const GrVkGpu * gpu,GrVkCommandBuffer * commandBuffer)273 void GrVkPipelineState::bindPipeline(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
274 commandBuffer->bindPipeline(gpu, fPipeline);
275 }
276