Files
evk/evk/evkDescriptor.c
T
2026-05-01 20:32:57 +03:00

187 lines
6.0 KiB
C

#include "evkDescriptor.h"
#include "evkBuffer.h"
#include "evkCommand.h"
EV_FORCEINLINE uint32_t aligned_size(uint32_t value, uint32_t alignment)
{
return (value + alignment - 1) & ~(alignment - 1);
}
VkBufferUsageFlags evkGetDescriptorSetBufferUsageFlags(evkDescriptorSetLayout* layout)
{
VkBufferUsageFlags flags = 0;
for(int i = 0; i < vec_len(&layout->vkBindings); i++)
{
VkDescriptorType type = layout->vkBindings[i].descriptorType;
if(type == VK_DESCRIPTOR_TYPE_SAMPLER)
{
flags |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
}
else
{
flags |= VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;
if(type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
{
flags |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
break;
}
}
}
return flags;
}
evkDescriptorSet evkCreateDescriptorSet(evkDescriptorSetCreateInfo* createInfo)
{
evkDescriptorSet res;
res.device = createInfo->device;
res.layout = (evkDescriptorSetLayout){
.names = ev_vec_dup(&createInfo->layout->names),
.vkBindings = ev_vec_dup(&createInfo->layout->vkBindings),
.vk = createInfo->layout->vk,
.size = createInfo->layout->size,
.offset = createInfo->layout->offset,
};
res.buffer = evkCreateBuffer(createInfo->device, (evkBufferCreateInfo) {
.allocationCreateInfo = (evkGPUAllocationCreateInfo) {
.allocator = *createInfo->allocator,
.allocationFlags = EVK_GPU_ALLOCATION_CREATE_MAPPED_BIT | EVK_GPU_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
},
.sizeInBytes = res.layout.size,
.usage = evkGetDescriptorSetBufferUsageFlags(&res.layout) | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.exclusive = true,
});
return res;
}
void evkDestroyDescriptorSet(evkDevice* device, evkDescriptorSet* set)
{
evkDestroyBuffer(set->buffer);
set->layout.vk = VK_NULL_HANDLE; // Not owned, so don't destroy
evkDestroyDescriptorSetLayout(device, &set->layout);
}
evkDescriptorSetLayout evkCreateDescriptorSetLayoutFromBindings(evkDevice* device, vec(evkDescriptorBinding) bindings)
{
evkDescriptorSetLayout layout;
layout.names = ev_vec_init(evstring);
layout.vkBindings = ev_vec_init(VkDescriptorSetLayoutBinding);
for(int i = 0; i < ev_vec_len(&bindings); i++)
{
VkDescriptorSetLayoutBinding b = {
.binding = bindings[i].binding,
.descriptorCount = bindings[i].descriptorCount,
.descriptorType = bindings[i].descriptorType,
.pImmutableSamplers = bindings[i].pImmutableSamplers,
.stageFlags = bindings[i].stageFlags,
};
ev_vec_push(&layout.names, &bindings[i].name);
ev_vec_push(&layout.vkBindings, &b);
}
vkCreateDescriptorSetLayout(device->vk, &(VkDescriptorSetLayoutCreateInfo){
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = vec_len(&layout.vkBindings),
.pBindings = layout.vkBindings,
.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT,
}, NULL, &layout.vk);
vkGetDescriptorSetLayoutSizeEXT(device->vk, layout.vk, &layout.size);
layout.size = aligned_size(layout.size, device->props.desc_buf.descriptorBufferOffsetAlignment);
vkGetDescriptorSetLayoutBindingOffsetEXT(device->vk, layout.vk, 0u, &layout.offset);
return layout;
}
void evkDescriptorBindingDedup(vec(evkDescriptorBinding) bindings)
{
}
evkDescriptorSetLayout evkCreateDescriptorSetLayoutFromShaders(evkDevice* device, vec(evkShader) shaders)
{
vec(evkDescriptorBinding) bindings = vec_init(evkDescriptorBinding);
for(int i = 0; i < vec_len(&shaders); i++)
{
vec_append(&bindings, (void**)&shaders[i].reflect.bindings, vec_len(&shaders[i].reflect.bindings));
}
evkDescriptorBindingDedup(bindings);
return evkCreateDescriptorSetLayoutFromBindings(device, bindings);
}
void evkDestroyDescriptorSetLayout(evkDevice* device, evkDescriptorSetLayout* layout)
{
if(layout->vk != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(device->vk, layout->vk, NULL);
ev_vec_fini(&layout->names);
ev_vec_fini(&layout->vkBindings);
layout->offset = 0;
layout->size = 0;
}
void evkSetDescriptor(evkDescriptorSet* set, evstring name, evkBuffer* buf)
{
i32 layoutBindingIdx = ev_vec_find(&set->layout.names, &name);
if(layoutBindingIdx == -1) return;
i32 bindingIdx = set->layout.vkBindings[layoutBindingIdx].binding;
u64 bindingOffset = 0;
vkGetDescriptorSetLayoutBindingOffsetEXT(set->device->vk, set->layout.vk, bindingIdx, &bindingOffset);
VkDescriptorAddressInfoEXT addressInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
.address = buf->address,
.range = buf->sizeInBytes,
.format = VK_FORMAT_UNDEFINED,
};
VkDescriptorGetInfoEXT getInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
.type = set->layout.vkBindings[layoutBindingIdx].descriptorType,
.data = {
.pUniformBuffer = &addressInfo
}
};
vkGetDescriptorEXT(set->device->vk, &getInfo, set->device->props.desc_buf.uniformBufferDescriptorSize, set->buffer.allocData.allocationInfo.vma.pMappedData);
}
void evkCmdBindDescriptorSets(evkCommandBuffer* cmdbuf, evkPipeline* pipeline, vec(evkDescriptorSet) sets, vec(u32) setIndices)
{
VkDescriptorBufferBindingInfoEXT bindingInfos[MAX_DESCRIPTOR_SETS];
VkDeviceSize setOffsets[MAX_DESCRIPTOR_SETS];
u32 actualSetIndices[MAX_DESCRIPTOR_SETS];
for(int i = 0; i < MAX_DESCRIPTOR_SETS; i++)
actualSetIndices[i] = i;
int bindingCount = min(MAX_DESCRIPTOR_SETS, vec_len(&sets));
int offset = 0;
for(int i = 0; i < bindingCount; i++)
{
bindingInfos[i] = (VkDescriptorBufferBindingInfoEXT) {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
.address = sets[setIndices[i]].buffer.address,
.usage = sets[setIndices[i]].buffer.usage,
};
setOffsets[i] = offset;
offset += sets[setIndices[i]].layout.size;
}
vkCmdBindDescriptorBuffersEXT(cmdbuf->vk, bindingCount, bindingInfos);
vkCmdSetDescriptorBufferOffsetsEXT(cmdbuf->vk,
(VkPipelineBindPoint)pipeline->type,
pipeline->layout.vk,
0, bindingCount,
actualSetIndices,
setOffsets);
}