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 "GrVkProgram.h" 9 10 #include "GrPipeline.h" 11 #include "GrVkCommandBuffer.h" 12 #include "GrVkDescriptorPool.h" 13 #include "GrVkGpu.h" 14 #include "GrVkImageView.h" 15 #include "GrVkMemory.h" 16 #include "GrVkPipeline.h" 17 #include "GrVkSampler.h" 18 #include "GrVkTexture.h" 19 #include "GrVkUniformBuffer.h" 20 #include "glsl/GrGLSLFragmentProcessor.h" 21 #include "glsl/GrGLSLGeometryProcessor.h" 22 #include "glsl/GrGLSLXferProcessor.h" 23 24 GrVkProgram::GrVkProgram(GrVkGpu* gpu, 25 GrVkPipeline* pipeline, 26 VkPipelineLayout layout, 27 VkDescriptorSetLayout dsLayout[2], 28 GrVkDescriptorPool* descriptorPool, 29 VkDescriptorSet descriptorSets[2], 30 const BuiltinUniformHandles& builtinUniformHandles, 31 const UniformInfoArray& uniforms, 32 uint32_t vertexUniformSize, 33 uint32_t fragmentUniformSize, 34 uint32_t numSamplers, 35 GrGLSLPrimitiveProcessor* geometryProcessor, 36 GrGLSLXferProcessor* xferProcessor, 37 const GrGLSLFragProcs& fragmentProcessors) 38 : fDescriptorPool(descriptorPool) 39 , fPipeline(pipeline) 40 , fPipelineLayout(layout) 41 , fBuiltinUniformHandles(builtinUniformHandles) 42 , fGeometryProcessor(geometryProcessor) 43 , fXferProcessor(xferProcessor) 44 , fFragmentProcessors(fragmentProcessors) 45 , fProgramDataManager(uniforms, vertexUniformSize, fragmentUniformSize) { 46 fSamplers.setReserve(numSamplers); 47 fTextureViews.setReserve(numSamplers); 48 fTextures.setReserve(numSamplers); 49 50 memcpy(fDSLayout, dsLayout, 2 * sizeof(VkDescriptorSetLayout)); 51 memcpy(fDescriptorSets, descriptorSets, 2 * sizeof(VkDescriptorSetLayout)); 52 53 fVertexUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, vertexUniformSize, true)); 54 fFragmentUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, fragmentUniformSize, true)); 55 56 #ifdef SK_DEBUG 57 fNumSamplers = numSamplers; 58 #endif 59 } 60 61 GrVkProgram::~GrVkProgram() { 62 // Must of freed all GPU resources before this is destroyed 63 SkASSERT(!fPipeline); 64 SkASSERT(!fDescriptorPool); 65 SkASSERT(!fPipelineLayout); 66 SkASSERT(!fDSLayout[0]); 67 SkASSERT(!fDSLayout[1]); 68 SkASSERT(!fSamplers.count()); 69 SkASSERT(!fTextureViews.count()); 70 SkASSERT(!fTextures.count()); 71 } 72 73 void GrVkProgram::freeTempResources(const GrVkGpu* gpu) { 74 for (int i = 0; i < fSamplers.count(); ++i) { 75 fSamplers[i]->unref(gpu); 76 } 77 fSamplers.rewind(); 78 79 for (int i = 0; i < fTextureViews.count(); ++i) { 80 fTextureViews[i]->unref(gpu); 81 } 82 fTextureViews.rewind(); 83 84 for (int i = 0; i < fTextures.count(); ++i) { 85 fTextures[i]->unref(gpu); 86 } 87 fTextures.rewind(); 88 } 89 90 void GrVkProgram::freeGPUResources(const GrVkGpu* gpu) { 91 if (fPipeline) { 92 fPipeline->unref(gpu); 93 fPipeline = nullptr; 94 } 95 if (fDescriptorPool) { 96 fDescriptorPool->unref(gpu); 97 fDescriptorPool = nullptr; 98 } 99 if (fPipelineLayout) { 100 GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), 101 fPipelineLayout, 102 nullptr)); 103 fPipelineLayout = nullptr; 104 } 105 106 if (fDSLayout[0]) { 107 GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDSLayout[0], 108 nullptr)); 109 fDSLayout[0] = nullptr; 110 } 111 if (fDSLayout[1]) { 112 GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDSLayout[1], 113 nullptr)); 114 fDSLayout[1] = nullptr; 115 } 116 117 if (fVertexUniformBuffer) { 118 fVertexUniformBuffer->release(gpu); 119 } 120 121 if (fFragmentUniformBuffer) { 122 fFragmentUniformBuffer->release(gpu); 123 } 124 this->freeTempResources(gpu); 125 } 126 127 void GrVkProgram::abandonGPUResources() { 128 fPipeline->unrefAndAbandon(); 129 fPipeline = nullptr; 130 fDescriptorPool->unrefAndAbandon(); 131 fDescriptorPool = nullptr; 132 fPipelineLayout = nullptr; 133 fDSLayout[0] = nullptr; 134 fDSLayout[1] = nullptr; 135 136 fVertexUniformBuffer->abandon(); 137 fFragmentUniformBuffer->abandon(); 138 139 for (int i = 0; i < fSamplers.count(); ++i) { 140 fSamplers[i]->unrefAndAbandon(); 141 } 142 fSamplers.rewind(); 143 144 for (int i = 0; i < fTextureViews.count(); ++i) { 145 fTextureViews[i]->unrefAndAbandon(); 146 } 147 fTextureViews.rewind(); 148 149 for (int i = 0; i < fTextures.count(); ++i) { 150 fTextures[i]->unrefAndAbandon(); 151 } 152 fTextures.rewind(); 153 } 154 155 static void append_texture_bindings(const GrProcessor& processor, 156 SkTArray<const GrTextureAccess*>* textureBindings) { 157 if (int numTextures = processor.numTextures()) { 158 const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures); 159 int i = 0; 160 do { 161 bindings[i] = &processor.textureAccess(i); 162 } while (++i < numTextures); 163 } 164 } 165 166 void GrVkProgram::setData(const GrVkGpu* gpu, 167 const GrPrimitiveProcessor& primProc, 168 const GrPipeline& pipeline) { 169 // This is here to protect against someone calling setData multiple times in a row without 170 // freeing the tempData between calls. 171 this->freeTempResources(gpu); 172 173 this->setRenderTargetState(pipeline); 174 175 SkSTArray<8, const GrTextureAccess*> textureBindings; 176 177 fGeometryProcessor->setData(fProgramDataManager, primProc); 178 append_texture_bindings(primProc, &textureBindings); 179 180 for (int i = 0; i < fFragmentProcessors.count(); ++i) { 181 const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i); 182 fFragmentProcessors[i]->setData(fProgramDataManager, processor); 183 fGeometryProcessor->setTransformData(primProc, fProgramDataManager, i, 184 processor.coordTransforms()); 185 append_texture_bindings(processor, &textureBindings); 186 } 187 188 fXferProcessor->setData(fProgramDataManager, pipeline.getXferProcessor()); 189 append_texture_bindings(pipeline.getXferProcessor(), &textureBindings); 190 191 this->writeUniformBuffers(gpu); 192 193 this->writeSamplers(gpu, textureBindings); 194 } 195 196 void GrVkProgram::writeUniformBuffers(const GrVkGpu* gpu) { 197 fProgramDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmentUniformBuffer); 198 199 VkWriteDescriptorSet descriptorWrites[2]; 200 memset(descriptorWrites, 0, 2 * sizeof(VkWriteDescriptorSet)); 201 202 uint32_t firstUniformWrite = 0; 203 uint32_t uniformBindingUpdateCount = 0; 204 205 // Vertex Uniform Buffer 206 if (fVertexUniformBuffer.get()) { 207 ++uniformBindingUpdateCount; 208 VkDescriptorBufferInfo vertBufferInfo; 209 memset(&vertBufferInfo, 0, sizeof(VkDescriptorBufferInfo)); 210 vertBufferInfo.buffer = fVertexUniformBuffer->buffer(); 211 vertBufferInfo.offset = 0; 212 vertBufferInfo.range = fVertexUniformBuffer->size(); 213 214 descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 215 descriptorWrites[0].pNext = nullptr; 216 descriptorWrites[0].dstSet = fDescriptorSets[1]; 217 descriptorWrites[0].dstBinding = GrVkUniformHandler::kVertexBinding; 218 descriptorWrites[0].dstArrayElement = 0; 219 descriptorWrites[0].descriptorCount = 1; 220 descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 221 descriptorWrites[0].pImageInfo = nullptr; 222 descriptorWrites[0].pBufferInfo = &vertBufferInfo; 223 descriptorWrites[0].pTexelBufferView = nullptr; 224 } 225 226 // Fragment Uniform Buffer 227 if (fFragmentUniformBuffer.get()) { 228 if (0 == uniformBindingUpdateCount) { 229 firstUniformWrite = 1; 230 } 231 ++uniformBindingUpdateCount; 232 VkDescriptorBufferInfo fragBufferInfo; 233 memset(&fragBufferInfo, 0, sizeof(VkDescriptorBufferInfo)); 234 fragBufferInfo.buffer = fFragmentUniformBuffer->buffer(); 235 fragBufferInfo.offset = 0; 236 fragBufferInfo.range = fFragmentUniformBuffer->size(); 237 238 descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 239 descriptorWrites[1].pNext = nullptr; 240 descriptorWrites[1].dstSet = fDescriptorSets[1]; 241 descriptorWrites[1].dstBinding = GrVkUniformHandler::kFragBinding;; 242 descriptorWrites[1].dstArrayElement = 0; 243 descriptorWrites[1].descriptorCount = 1; 244 descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 245 descriptorWrites[1].pImageInfo = nullptr; 246 descriptorWrites[1].pBufferInfo = &fragBufferInfo; 247 descriptorWrites[1].pTexelBufferView = nullptr; 248 } 249 250 if (uniformBindingUpdateCount) { 251 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), 252 uniformBindingUpdateCount, 253 &descriptorWrites[firstUniformWrite], 254 0, nullptr)); 255 } 256 } 257 258 void GrVkProgram::writeSamplers(const GrVkGpu* gpu, 259 const SkTArray<const GrTextureAccess*>& textureBindings) { 260 SkASSERT(fNumSamplers == textureBindings.count()); 261 262 for (int i = 0; i < textureBindings.count(); ++i) { 263 fSamplers.push(GrVkSampler::Create(gpu, *textureBindings[i])); 264 265 GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->getTexture()); 266 267 const GrVkImage::Resource* textureResource = texture->resource(); 268 textureResource->ref(); 269 fTextures.push(textureResource); 270 271 const GrVkImageView* textureView = texture->textureView(); 272 textureView->ref(); 273 fTextureViews.push(textureView); 274 275 // Change texture layout so it can be read in shader 276 VkImageLayout layout = texture->currentLayout(); 277 VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout); 278 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; 279 VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout); 280 VkAccessFlags dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 281 texture->setImageLayout(gpu, 282 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 283 srcAccessMask, 284 dstAccessMask, 285 srcStageMask, 286 dstStageMask, 287 false); 288 289 VkDescriptorImageInfo imageInfo; 290 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo)); 291 imageInfo.sampler = fSamplers[i]->sampler(); 292 imageInfo.imageView = texture->textureView()->imageView(); 293 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 294 295 VkWriteDescriptorSet writeInfo; 296 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet)); 297 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 298 writeInfo.pNext = nullptr; 299 writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet]; 300 writeInfo.dstBinding = i; 301 writeInfo.dstArrayElement = 0; 302 writeInfo.descriptorCount = 1; 303 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 304 writeInfo.pImageInfo = &imageInfo; 305 writeInfo.pBufferInfo = nullptr; 306 writeInfo.pTexelBufferView = nullptr; 307 308 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), 309 1, 310 &writeInfo, 311 0, 312 nullptr)); 313 } 314 } 315 316 void GrVkProgram::setRenderTargetState(const GrPipeline& pipeline) { 317 // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 318 if (fBuiltinUniformHandles.fRTHeightUni.isValid() && 319 fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget()->height()) { 320 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, 321 SkIntToScalar(pipeline.getRenderTarget()->height())); 322 } 323 324 // set RT adjustment 325 const GrRenderTarget* rt = pipeline.getRenderTarget(); 326 SkISize size; 327 size.set(rt->width(), rt->height()); 328 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); 329 if (fRenderTargetState.fRenderTargetOrigin != rt->origin() || 330 fRenderTargetState.fRenderTargetSize != size) { 331 fRenderTargetState.fRenderTargetSize = size; 332 fRenderTargetState.fRenderTargetOrigin = rt->origin(); 333 334 float rtAdjustmentVec[4]; 335 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec); 336 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); 337 } 338 } 339 340 void GrVkProgram::bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) { 341 commandBuffer->bindPipeline(gpu, fPipeline); 342 commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, 0, 2, fDescriptorSets, 0, 343 nullptr); 344 } 345 346 void GrVkProgram::addUniformResources(GrVkCommandBuffer& commandBuffer) { 347 #if 1 348 commandBuffer.addResource(fDescriptorPool); 349 if (fVertexUniformBuffer.get()) { 350 commandBuffer.addResource(fVertexUniformBuffer->resource()); 351 } 352 if (fFragmentUniformBuffer.get()) { 353 commandBuffer.addResource(fFragmentUniformBuffer->resource()); 354 } 355 for (int i = 0; i < fSamplers.count(); ++i) { 356 commandBuffer.addResource(fSamplers[i]); 357 } 358 359 for (int i = 0; i < fTextureViews.count(); ++i) { 360 commandBuffer.addResource(fTextureViews[i]); 361 } 362 363 for (int i = 0; i < fTextures.count(); ++i) { 364 commandBuffer.addResource(fTextures[i]); 365 } 366 #endif 367 } 368