Home | History | Annotate | Download | only in vk
      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