xash3d-fwgs/ref/vk/vk_descriptor.c
Ivan Avdeev 01de5957d8
vk: respect TF_NEAREST/CLAMP/BORDER flags (#471)
Use these flags to pick the right sampler. Fixes issues with blurry and leaking fonts, lines in main menu tiles, etc.

fixes #439, fixes #79
2023-03-08 14:16:21 -08:00

223 lines
7.0 KiB
C

#include "vk_descriptor.h"
#include "eiface.h" // ARRAYSIZE
descriptor_pool_t vk_desc;
qboolean VK_DescriptorInit( void )
{
int max_desc_sets = 0;
VkDescriptorPoolSize dps[] = {
{
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = MAX_TEXTURES,
}, {
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
.descriptorCount = ARRAYSIZE(vk_desc.ubo_sets),
/*
}, {
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
*/
},
};
VkDescriptorPoolCreateInfo dpci = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.pPoolSizes = dps,
.poolSizeCount = ARRAYSIZE(dps),
};
for (int i = 0; i < ARRAYSIZE(dps); ++i)
max_desc_sets += dps[i].descriptorCount;
dpci.maxSets = max_desc_sets;
XVK_CHECK(vkCreateDescriptorPool(vk_core.device, &dpci, NULL, &vk_desc.pool));
{
const int num_sets = MAX_TEXTURES;
// ... TODO find better place for this; this should be per-pipeline/shader
const VkDescriptorSetLayoutBinding bindings[] = { {
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = NULL,
}};
const VkDescriptorSetLayoutCreateInfo dslci = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = ARRAYSIZE(bindings),
.pBindings = bindings,
};
VkDescriptorSetLayout* tmp_layouts = Mem_Malloc(vk_core.pool, sizeof(VkDescriptorSetLayout) * num_sets);
const VkDescriptorSetAllocateInfo dsai = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = vk_desc.pool,
.descriptorSetCount = num_sets,
.pSetLayouts = tmp_layouts,
};
XVK_CHECK(vkCreateDescriptorSetLayout(vk_core.device, &dslci, NULL, &vk_desc.one_texture_layout));
for (int i = 0; i < num_sets; ++i)
tmp_layouts[i] = vk_desc.one_texture_layout;
XVK_CHECK(vkAllocateDescriptorSets(vk_core.device, &dsai, vk_desc.sets));
Mem_Free(tmp_layouts);
}
{
const int num_sets = ARRAYSIZE(vk_desc.ubo_sets);
// ... TODO find better place for this; this should be per-pipeline/shader
VkDescriptorSetLayoutBinding bindings[] = { {
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
.descriptorCount = 1,
// TODO we use these sets for both vertex-only and fragment-only bindings; improve
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
}};
VkDescriptorSetLayoutCreateInfo dslci = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = ARRAYSIZE(bindings),
.pBindings = bindings,
};
VkDescriptorSetLayout* tmp_layouts = Mem_Malloc(vk_core.pool, sizeof(VkDescriptorSetLayout) * num_sets);
VkDescriptorSetAllocateInfo dsai = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = vk_desc.pool,
.descriptorSetCount = num_sets,
.pSetLayouts = tmp_layouts,
};
XVK_CHECK(vkCreateDescriptorSetLayout(vk_core.device, &dslci, NULL, &vk_desc.one_uniform_buffer_layout));
for (int i = 0; i < num_sets; ++i)
tmp_layouts[i] = vk_desc.one_uniform_buffer_layout;
XVK_CHECK(vkAllocateDescriptorSets(vk_core.device, &dsai, vk_desc.ubo_sets));
Mem_Free(tmp_layouts);
}
return true;
}
void VK_DescriptorShutdown( void )
{
vkDestroyDescriptorPool(vk_core.device, vk_desc.pool, NULL);
vkDestroyDescriptorSetLayout(vk_core.device, vk_desc.one_texture_layout, NULL);
vkDestroyDescriptorSetLayout(vk_core.device, vk_desc.one_uniform_buffer_layout, NULL);
}
void VK_DescriptorsCreate(vk_descriptors_t *desc)
{
{
VkDescriptorSetLayoutCreateInfo dslci = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = desc->num_bindings,
.pBindings = desc->bindings,
};
XVK_CHECK(vkCreateDescriptorSetLayout(vk_core.device, &dslci, NULL, &desc->desc_layout));
}
{
VkPipelineLayoutCreateInfo plci = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 1,
.pSetLayouts = &desc->desc_layout,
.pushConstantRangeCount = desc->push_constants.size > 0 ? 1 : 0,
.pPushConstantRanges = &desc->push_constants,
};
XVK_CHECK(vkCreatePipelineLayout(vk_core.device, &plci, NULL, &desc->pipeline_layout));
}
{
VkDescriptorPoolSize pools[8] = {0};
VkDescriptorPoolCreateInfo dpci = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.maxSets = desc->num_sets,
.poolSizeCount = 0,
.pPoolSizes = pools,
};
for (int i = 0; i < desc->num_bindings; ++i) {
const VkDescriptorSetLayoutBinding *bind = desc->bindings + i;
int j;
for (j = 0; j < dpci.poolSizeCount; ++j) {
if (pools[j].type == bind->descriptorType) {
pools[j].descriptorCount += bind->descriptorCount * desc->num_sets;
break;
}
}
if (j == dpci.poolSizeCount) {
ASSERT(dpci.poolSizeCount < ARRAYSIZE(pools));
pools[j].descriptorCount = bind->descriptorCount * desc->num_sets;
pools[j].type = bind->descriptorType;
++dpci.poolSizeCount;
}
}
XVK_CHECK(vkCreateDescriptorPool(vk_core.device, &dpci, NULL, &desc->desc_pool));
}
for (int i = 0; i < desc->num_sets; ++i)
{
VkDescriptorSetAllocateInfo dsai = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = desc->desc_pool,
.descriptorSetCount = 1,
.pSetLayouts = &desc->desc_layout,
};
XVK_CHECK(vkAllocateDescriptorSets(vk_core.device, &dsai, desc->desc_sets + i));
}
}
void VK_DescriptorsWrite(const vk_descriptors_t *desc, int set_slot)
{
VkWriteDescriptorSet wds[16];
ASSERT(ARRAYSIZE(wds) >= desc->num_bindings);
for (int i = 0; i < desc->num_bindings; ++i){
const VkDescriptorSetLayoutBinding *binding = desc->bindings + i;
wds[i] = (VkWriteDescriptorSet) {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.descriptorCount = binding->descriptorCount,
.descriptorType = binding->descriptorType,
.dstSet = desc->desc_sets[set_slot],
.dstBinding = binding->binding,
.dstArrayElement = 0,
};
switch (binding->descriptorType) {
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
// TODO
ASSERT(wds[i].descriptorCount == 1);
wds[i].pBufferInfo = &desc->values[i].buffer;
break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
if (wds[i].descriptorCount > 1)
wds[i].pImageInfo = desc->values[i].image_array;
else
wds[i].pImageInfo = &desc->values[i].image;
break;
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
// TODO
ASSERT(wds[i].descriptorCount == 1);
wds[i].pNext = &desc->values[i].accel;
break;
default:
gEngine.Con_Printf(S_ERROR "Unexpected descriptor type %d\n", binding->descriptorType);
ASSERT("Unexpected descriptor type");
}
}
vkUpdateDescriptorSets(vk_core.device, desc->num_bindings, wds, 0, NULL);
}
void VK_DescriptorsDestroy(const vk_descriptors_t *desc)
{
vkDestroyDescriptorPool(vk_core.device, desc->desc_pool, NULL);
vkDestroyPipelineLayout(vk_core.device, desc->pipeline_layout, NULL);
vkDestroyDescriptorSetLayout(vk_core.device, desc->desc_layout, NULL);
}