187 lines
6.0 KiB
C
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);
|
|
}
|