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 "GrVkDescriptorSetManager.h"
      9 
     10 #include "GrVkDescriptorPool.h"
     11 #include "GrVkDescriptorSet.h"
     12 #include "GrVkGpu.h"
     13 #include "GrVkUniformHandler.h"
     14 
     15 GrVkDescriptorSetManager* GrVkDescriptorSetManager::CreateUniformManager(GrVkGpu* gpu) {
     16     SkSTArray<2, uint32_t> visibilities;
     17     // We set the visibility of the first binding to all supported geometry processing shader
     18     // stages (vertex, tesselation, geometry, etc.) and the second binding to the fragment
     19     // shader.
     20     uint32_t geomStages = kVertex_GrShaderFlag;
     21     if (gpu->vkCaps().shaderCaps()->geometryShaderSupport()) {
     22         geomStages |= kGeometry_GrShaderFlag;
     23     }
     24     visibilities.push_back(geomStages);
     25     visibilities.push_back(kFragment_GrShaderFlag);
     26     return new GrVkDescriptorSetManager(gpu, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, visibilities);
     27 }
     28 
     29 GrVkDescriptorSetManager* GrVkDescriptorSetManager::CreateSamplerManager(
     30         GrVkGpu* gpu, VkDescriptorType type, const GrVkUniformHandler& uniformHandler) {
     31     SkSTArray<4, uint32_t> visibilities;
     32     if (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == type) {
     33         for (int i = 0 ; i < uniformHandler.numSamplers(); ++i) {
     34             visibilities.push_back(uniformHandler.samplerVisibility(i));
     35         }
     36     } else {
     37         SkASSERT(type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
     38         for (int i = 0 ; i < uniformHandler.numTexelBuffers(); ++i) {
     39             visibilities.push_back(uniformHandler.texelBufferVisibility(i));
     40         }
     41     }
     42     return CreateSamplerManager(gpu, type, visibilities);
     43 }
     44 
     45 GrVkDescriptorSetManager* GrVkDescriptorSetManager::CreateSamplerManager(
     46         GrVkGpu* gpu, VkDescriptorType type, const SkTArray<uint32_t>& visibilities) {
     47     return new GrVkDescriptorSetManager(gpu, type, visibilities);
     48 }
     49 
     50 GrVkDescriptorSetManager::GrVkDescriptorSetManager(GrVkGpu* gpu,
     51                                                    VkDescriptorType type,
     52                                                    const SkTArray<uint32_t>& visibilities)
     53     : fPoolManager(type, gpu, visibilities) {
     54     for (int i = 0; i < visibilities.count(); ++i) {
     55         fBindingVisibilities.push_back(visibilities[i]);
     56     }
     57 }
     58 
     59 const GrVkDescriptorSet* GrVkDescriptorSetManager::getDescriptorSet(GrVkGpu* gpu,
     60                                                                     const Handle& handle) {
     61     const GrVkDescriptorSet* ds = nullptr;
     62     int count = fFreeSets.count();
     63     if (count > 0) {
     64         ds = fFreeSets[count - 1];
     65         fFreeSets.removeShuffle(count - 1);
     66     } else {
     67         VkDescriptorSet vkDS;
     68         fPoolManager.getNewDescriptorSet(gpu, &vkDS);
     69 
     70         ds = new GrVkDescriptorSet(vkDS, fPoolManager.fPool, handle);
     71     }
     72     SkASSERT(ds);
     73     return ds;
     74 }
     75 
     76 void GrVkDescriptorSetManager::recycleDescriptorSet(const GrVkDescriptorSet* descSet) {
     77     SkASSERT(descSet);
     78     fFreeSets.push_back(descSet);
     79 }
     80 
     81 void GrVkDescriptorSetManager::release(const GrVkGpu* gpu) {
     82     fPoolManager.freeGPUResources(gpu);
     83 
     84     for (int i = 0; i < fFreeSets.count(); ++i) {
     85         fFreeSets[i]->unref(gpu);
     86     }
     87     fFreeSets.reset();
     88 }
     89 
     90 void GrVkDescriptorSetManager::abandon() {
     91     fPoolManager.abandonGPUResources();
     92 
     93     for (int i = 0; i < fFreeSets.count(); ++i) {
     94         fFreeSets[i]->unrefAndAbandon();
     95     }
     96     fFreeSets.reset();
     97 }
     98 
     99 bool GrVkDescriptorSetManager::isCompatible(VkDescriptorType type,
    100                                             const GrVkUniformHandler* uniHandler) const {
    101     SkASSERT(uniHandler);
    102     if (type != fPoolManager.fDescType) {
    103         return false;
    104     }
    105 
    106     if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
    107         if (fBindingVisibilities.count() != uniHandler->numSamplers()) {
    108             return false;
    109         }
    110         for (int i = 0; i < uniHandler->numSamplers(); ++i) {
    111             if (uniHandler->samplerVisibility(i) != fBindingVisibilities[i]) {
    112                 return false;
    113             }
    114         }
    115     } else if (VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == type) {
    116         if (fBindingVisibilities.count() != uniHandler->numTexelBuffers()) {
    117             return false;
    118         }
    119         for (int i = 0; i < uniHandler->numTexelBuffers(); ++i) {
    120             if (uniHandler->texelBufferVisibility(i) != fBindingVisibilities[i]) {
    121                 return false;
    122             }
    123         }
    124     }
    125     return true;
    126 }
    127 
    128 bool GrVkDescriptorSetManager::isCompatible(VkDescriptorType type,
    129                                             const SkTArray<uint32_t>& visibilities) const {
    130     if (type != fPoolManager.fDescType) {
    131         return false;
    132     }
    133 
    134     if (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == type ||
    135         VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == type) {
    136         if (fBindingVisibilities.count() != visibilities.count()) {
    137             return false;
    138         }
    139         for (int i = 0; i < visibilities.count(); ++i) {
    140             if (visibilities[i] != fBindingVisibilities[i]) {
    141                 return false;
    142             }
    143         }
    144     }
    145     return true;
    146 }
    147 
    148 ////////////////////////////////////////////////////////////////////////////////
    149 
    150 VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) {
    151     VkShaderStageFlags flags = 0;
    152 
    153     if (visibility & kVertex_GrShaderFlag) {
    154         flags |= VK_SHADER_STAGE_VERTEX_BIT;
    155     }
    156     if (visibility & kGeometry_GrShaderFlag) {
    157         flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
    158     }
    159     if (visibility & kFragment_GrShaderFlag) {
    160         flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
    161     }
    162     return flags;
    163 }
    164 
    165 GrVkDescriptorSetManager::DescriptorPoolManager::DescriptorPoolManager(
    166         VkDescriptorType type,
    167         GrVkGpu* gpu,
    168         const SkTArray<uint32_t>& visibilities)
    169     : fDescType(type)
    170     , fCurrentDescriptorCount(0)
    171     , fPool(nullptr) {
    172 
    173 
    174     if (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == type ||
    175         VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == type) {
    176         uint32_t numBindings = visibilities.count();
    177         std::unique_ptr<VkDescriptorSetLayoutBinding[]> dsSamplerBindings(
    178                 new VkDescriptorSetLayoutBinding[numBindings]);
    179         for (uint32_t i = 0; i < numBindings; ++i) {
    180             uint32_t visibility = visibilities[i];
    181             dsSamplerBindings[i].binding = i;
    182             dsSamplerBindings[i].descriptorType = type;
    183             dsSamplerBindings[i].descriptorCount = 1;
    184             dsSamplerBindings[i].stageFlags = visibility_to_vk_stage_flags(visibility);
    185             dsSamplerBindings[i].pImmutableSamplers = nullptr;
    186         }
    187 
    188         VkDescriptorSetLayoutCreateInfo dsSamplerLayoutCreateInfo;
    189         memset(&dsSamplerLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
    190         dsSamplerLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    191         dsSamplerLayoutCreateInfo.pNext = nullptr;
    192         dsSamplerLayoutCreateInfo.flags = 0;
    193         dsSamplerLayoutCreateInfo.bindingCount = numBindings;
    194         // Setting to nullptr fixes an error in the param checker validation layer. Even though
    195         // bindingCount is 0 (which is valid), it still tries to validate pBindings unless it is
    196         // null.
    197         dsSamplerLayoutCreateInfo.pBindings = numBindings ? dsSamplerBindings.get() : nullptr;
    198 
    199         GR_VK_CALL_ERRCHECK(gpu->vkInterface(),
    200                             CreateDescriptorSetLayout(gpu->device(),
    201                                                       &dsSamplerLayoutCreateInfo,
    202                                                       nullptr,
    203                                                       &fDescLayout));
    204         fDescCountPerSet = visibilities.count();
    205     } else {
    206         SkASSERT(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type);
    207         GR_STATIC_ASSERT(2 == kUniformDescPerSet);
    208         SkASSERT(kUniformDescPerSet == visibilities.count());
    209         // Create Uniform Buffer Descriptor
    210         static const uint32_t bindings[kUniformDescPerSet] =
    211                 { GrVkUniformHandler::kGeometryBinding, GrVkUniformHandler::kFragBinding };
    212         VkDescriptorSetLayoutBinding dsUniBindings[kUniformDescPerSet];
    213         memset(&dsUniBindings, 0, kUniformDescPerSet * sizeof(VkDescriptorSetLayoutBinding));
    214         for (int i = 0; i < kUniformDescPerSet; ++i) {
    215             dsUniBindings[i].binding = bindings[i];
    216             dsUniBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    217             dsUniBindings[i].descriptorCount = 1;
    218             dsUniBindings[i].stageFlags = visibility_to_vk_stage_flags(visibilities[i]);
    219             dsUniBindings[i].pImmutableSamplers = nullptr;
    220         }
    221 
    222         VkDescriptorSetLayoutCreateInfo uniformLayoutCreateInfo;
    223         memset(&uniformLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
    224         uniformLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    225         uniformLayoutCreateInfo.pNext = nullptr;
    226         uniformLayoutCreateInfo.flags = 0;
    227         uniformLayoutCreateInfo.bindingCount = 2;
    228         uniformLayoutCreateInfo.pBindings = dsUniBindings;
    229 
    230         GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateDescriptorSetLayout(gpu->device(),
    231                                                                           &uniformLayoutCreateInfo,
    232                                                                           nullptr,
    233                                                                           &fDescLayout));
    234         fDescCountPerSet = kUniformDescPerSet;
    235     }
    236 
    237     SkASSERT(fDescCountPerSet < kStartNumDescriptors);
    238     fMaxDescriptors = kStartNumDescriptors;
    239     SkASSERT(fMaxDescriptors > 0);
    240     this->getNewPool(gpu);
    241 }
    242 
    243 void GrVkDescriptorSetManager::DescriptorPoolManager::getNewPool(GrVkGpu* gpu) {
    244     if (fPool) {
    245         fPool->unref(gpu);
    246         uint32_t newPoolSize = fMaxDescriptors + ((fMaxDescriptors + 1) >> 1);
    247         if (newPoolSize < kMaxDescriptors) {
    248             fMaxDescriptors = newPoolSize;
    249         } else {
    250             fMaxDescriptors = kMaxDescriptors;
    251         }
    252 
    253     }
    254     fPool = gpu->resourceProvider().findOrCreateCompatibleDescriptorPool(fDescType,
    255                                                                          fMaxDescriptors);
    256     SkASSERT(fPool);
    257 }
    258 
    259 void GrVkDescriptorSetManager::DescriptorPoolManager::getNewDescriptorSet(GrVkGpu* gpu,
    260                                                                           VkDescriptorSet* ds) {
    261     if (!fMaxDescriptors) {
    262         return;
    263     }
    264     fCurrentDescriptorCount += fDescCountPerSet;
    265     if (fCurrentDescriptorCount > fMaxDescriptors) {
    266         this->getNewPool(gpu);
    267         fCurrentDescriptorCount = fDescCountPerSet;
    268     }
    269 
    270     VkDescriptorSetAllocateInfo dsAllocateInfo;
    271     memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo));
    272     dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    273     dsAllocateInfo.pNext = nullptr;
    274     dsAllocateInfo.descriptorPool = fPool->descPool();
    275     dsAllocateInfo.descriptorSetCount = 1;
    276     dsAllocateInfo.pSetLayouts = &fDescLayout;
    277     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), AllocateDescriptorSets(gpu->device(),
    278                                                                    &dsAllocateInfo,
    279                                                                    ds));
    280 }
    281 
    282 void GrVkDescriptorSetManager::DescriptorPoolManager::freeGPUResources(const GrVkGpu* gpu) {
    283     if (fDescLayout) {
    284         GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDescLayout,
    285                                                                   nullptr));
    286         fDescLayout = VK_NULL_HANDLE;
    287     }
    288 
    289     if (fPool) {
    290         fPool->unref(gpu);
    291         fPool = nullptr;
    292     }
    293 }
    294 
    295 void GrVkDescriptorSetManager::DescriptorPoolManager::abandonGPUResources() {
    296     fDescLayout = VK_NULL_HANDLE;
    297     if (fPool) {
    298         fPool->unrefAndAbandon();
    299         fPool = nullptr;
    300     }
    301 }
    302