Vulkan: descriptor cache.

Doesn't help running out right now, as the DMA-BUFs from a new app
frame get imported as different Vulkan textures. Not sure how to
ensure continuity across several sightings of the original swapchain
images yet.
This commit is contained in:
Pierre-Loup A. Griffais 2019-12-11 03:17:33 +00:00
parent 0915d864c0
commit 9d49e1a682
2 changed files with 136 additions and 68 deletions

View file

@ -50,6 +50,14 @@ Composite_t *g_pCompositeBuffer;
std::unordered_map<VulkanTexture_t, CVulkanTexture *> g_mapVulkanTextures;
std::atomic<VulkanTexture_t> g_nMaxVulkanTexHandle;
struct VulkanDescriptorCacheEntry_t
{
VulkanPipeline_t key;
VulkanDescriptor_t *pDesc;
};
std::vector< VulkanDescriptorCacheEntry_t > g_vecVulkanDescriptorCache;
#define MAX_DEVICE_COUNT 8
#define MAX_QUEUE_COUNT 8
@ -741,16 +749,37 @@ void vulkan_free_texture( VulkanTexture_t vulkanTex )
// actually free something at some point
}
bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *pPipeline )
bool operator==(const struct VulkanPipeline_t& lhs, const struct VulkanPipeline_t& rhs)
{
*g_pCompositeBuffer = *pComposite;
// XXX maybe flush something?
for ( int i = 0; i < k_nMaxLayers; i++ )
{
if ( lhs.layerBindings[ i ].tex != rhs.layerBindings[ i ].tex )
return false;
if ( lhs.layerBindings[ i ].bFilter != rhs.layerBindings[ i ].bFilter )
return false;
if ( lhs.layerBindings[ i ].bBlackBorder != rhs.layerBindings[ i ].bBlackBorder )
return false;
}
return true;
}
VulkanDescriptor_t *vulkan_make_descriptor( struct VulkanPipeline_t *pPipeline )
{
VulkanDescriptor_t *ret = new VulkanDescriptor_t;
if ( ret == nullptr )
return nullptr;
*ret = {};
CVulkanTexture *pTex[ k_nMaxLayers ] = {};
uint32_t texLayerIDs[ k_nMaxLayers ] = {};
uint32_t nTexCount = 0;
for ( uint32_t i = 0; i < k_nMaxLayers; i ++ )
{
if ( pPipeline->layerBindings[ i ].tex != 0 )
@ -759,7 +788,7 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
assert( pTex[ nTexCount ] );
texLayerIDs[ nTexCount ] = i;
nTexCount++;
}
}
@ -772,27 +801,27 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
};
vecLayoutBindings.push_back( descriptorSetLayoutBindings ); // first binding is target storage image
descriptorSetLayoutBindings.binding = 1;
descriptorSetLayoutBindings.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
vecLayoutBindings.push_back( descriptorSetLayoutBindings ); // second binding is composite description buffer
for ( uint32_t i = 0; i < nTexCount; i++ )
{
descriptorSetLayoutBindings.binding = 2 + ( i * 2 );
descriptorSetLayoutBindings.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
vecLayoutBindings.push_back( descriptorSetLayoutBindings );
descriptorSetLayoutBindings.binding = 2 + ( i * 2 ) + 1;
descriptorSetLayoutBindings.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
vecLayoutBindings.push_back( descriptorSetLayoutBindings );
}
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo =
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
@ -801,33 +830,31 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
.bindingCount = 2 + ( nTexCount * 2 ),
vecLayoutBindings.data()
};
VkDescriptorSetLayout descriptorSetLayout;
VkResult res = vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, 0, &descriptorSetLayout);
VkResult res = vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, 0, &ret->descriptorSetLayout);
if ( res != VK_SUCCESS )
{
return false;
return nullptr;
}
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
0,
0,
1,
&descriptorSetLayout,
&ret->descriptorSetLayout,
0,
0
};
VkPipelineLayout pipelineLayout;
res = vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, 0, &pipelineLayout);
res = vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, 0, &ret->pipelineLayout);
if ( res != VK_SUCCESS )
{
return false;
return nullptr;
}
VkComputePipelineCreateInfo computePipelineCreateInfo = {
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
0,
@ -841,51 +868,49 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
"main",
0
},
pipelineLayout,
ret->pipelineLayout,
0,
0
};
VkPipeline pipeline;
res = vkCreateComputePipelines(device, 0, 1, &computePipelineCreateInfo, 0, &pipeline);
res = vkCreateComputePipelines(device, 0, 1, &computePipelineCreateInfo, 0, &ret->pipeline);
if ( res != VK_SUCCESS )
{
return false;
return nullptr;
}
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
nullptr,
descriptorPool,
1,
&descriptorSetLayout
&ret->descriptorSetLayout
};
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
res = vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet);
if ( res != VK_SUCCESS || descriptorSet == VK_NULL_HANDLE )
res = vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &ret->descriptorSet);
if ( res != VK_SUCCESS || ret->descriptorSet == VK_NULL_HANDLE )
{
return false;
return nullptr;
}
{
VkDescriptorImageInfo imageInfo = {
.imageView = BIsNested() ? swapChainImageViews[ g_nSwapChainImageIndex ] : outputImage[ g_nOutImage ].m_vkImageView,
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
};
VkDescriptorBufferInfo bufferInfo = {
.buffer = constantBuffer,
.offset = 0,
.range = VK_WHOLE_SIZE
};
VkWriteDescriptorSet writeDescriptorSet = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
.dstSet = descriptorSet,
.dstSet = ret->descriptorSet,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -894,21 +919,19 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
.pBufferInfo = nullptr,
.pTexelBufferView = nullptr,
};
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
writeDescriptorSet.dstBinding = 1;
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
writeDescriptorSet.pImageInfo = nullptr;
writeDescriptorSet.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
}
for ( uint32_t i = 0; i < nTexCount; i++ )
{
VkSampler sampler = VK_NULL_HANDLE;
VkSamplerCreateInfo samplerCreateInfo = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.pNext = nullptr,
@ -919,25 +942,25 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
.borderColor = pPipeline->layerBindings[ texLayerIDs[ i ] ].bBlackBorder ? VK_BORDER_COLOR_INT_OPAQUE_BLACK : VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,
.unnormalizedCoordinates = VK_TRUE,
};
res = vkCreateSampler( device, &samplerCreateInfo, nullptr, &sampler );
res = vkCreateSampler( device, &samplerCreateInfo, nullptr, &ret->samplers[ i ] );
if ( res != VK_SUCCESS )
{
return false;
return nullptr;
}
{
VkDescriptorImageInfo imageInfo = {
.imageView = pTex[ i ]->m_vkImageView,
// TODO figure out what it is exactly for the wayland surfaces
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
};
VkWriteDescriptorSet writeDescriptorSet = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
.dstSet = descriptorSet,
.dstSet = ret->descriptorSet,
.dstBinding = 2 + (i * 2),
.dstArrayElement = 0,
.descriptorCount = 1,
@ -946,19 +969,19 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
.pBufferInfo = nullptr,
.pTexelBufferView = nullptr,
};
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
}
{
VkDescriptorImageInfo imageInfo = {
.sampler = sampler,
.sampler = ret->samplers[ i ],
};
VkWriteDescriptorSet writeDescriptorSet = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
.dstSet = descriptorSet,
.dstSet = ret->descriptorSet,
.dstBinding = 2 + (i * 2) + 1,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -967,11 +990,44 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
.pBufferInfo = nullptr,
.pTexelBufferView = nullptr,
};
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
}
}
return ret;
}
bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *pPipeline )
{
*g_pCompositeBuffer = *pComposite;
// XXX maybe flush something?
VulkanDescriptor_t *pDescriptor = nullptr;
// First try to look up the descriptor in the cache.
for ( uint32_t i = 0; i < g_vecVulkanDescriptorCache.size(); i++ )
{
if ( g_vecVulkanDescriptorCache[ i ].key == *pPipeline )
{
pDescriptor = g_vecVulkanDescriptorCache[ i ].pDesc;
break;
}
}
if ( pDescriptor == nullptr )
{
pDescriptor = vulkan_make_descriptor( pPipeline );
if ( pDescriptor == nullptr )
{
return false;
}
VulkanDescriptorCacheEntry_t entry = { *pPipeline, pDescriptor };
g_vecVulkanDescriptorCache.push_back( entry );
}
VkCommandBufferAllocateInfo commandBufferAllocateInfo = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
0,
@ -981,7 +1037,7 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
};
VkCommandBuffer commandBuffer;
res = vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer);
VkResult res = vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer);
if ( res != VK_SUCCESS )
{
@ -1002,10 +1058,10 @@ bool vulkan_composite( struct Composite_t *pComposite, struct VulkanPipeline_t *
return false;
}
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pDescriptor->pipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
pipelineLayout, 0, 1, &descriptorSet, 0, 0);
pDescriptor->pipelineLayout, 0, 1, &pDescriptor->descriptorSet, 0, 0);
vkCmdDispatch(commandBuffer, g_nOutputWidth / 16, g_nOutputHeight / 16, 1);

View file

@ -5,6 +5,10 @@
#include "drm.hpp"
#ifndef C_SIDE
#include <unordered_map>
#include <vector>
extern "C" {
#endif
@ -14,9 +18,6 @@ extern "C" {
#ifndef C_SIDE
#include <unordered_map>
#include <vector>
class CVulkanTexture
{
public:
@ -43,6 +44,17 @@ typedef uint32_t VulkanTexture_t;
#define k_nMaxLayers 4
struct VulkanDescriptor_t
{
VkDescriptorSetLayout descriptorSetLayout;
VkPipelineLayout pipelineLayout;
VkDescriptorSet descriptorSet;
VkSampler samplers[ k_nMaxLayers ];
VkPipeline pipeline;
};
struct VulkanPipeline_t
{
struct