From dd0d232c9771356bb4932c1d587a028f40ad0139 Mon Sep 17 00:00:00 2001 From: Robear Selwans Date: Wed, 2 Jul 2025 12:26:20 +0300 Subject: [PATCH] Major changes Signed-off-by: Robear Selwans --- .vscode/launch.json | 17 ++ .vscode/tasks.json | 20 ++ evk/evk.h | 4 + evk/evkBuffer.c | 11 +- evk/evkBuffer.h | 2 +- evk/evkCommand.c | 41 +++- evk/evkCommand.h | 8 +- evk/evkCommon.h | 1 + evk/evkConstants.h | 3 + evk/evkDescriptor.c | 207 +++++++++++++++--- evk/evkDescriptor.h | 14 ++ evk/evkDevice.c | 90 ++++++-- evk/evkInstance.h | 4 +- evk/evkMemory.c | 19 +- evk/evkPipeline.c | 112 ++++++++-- evk/evkPipeline.h | 2 + evk/evkShader.c | 5 +- evk/evkTypes.h | 165 ++++++++++++-- evk/evkVertexLayout.c | 1 + evk/evkVertexLayout.h | 47 ++++ main.c | 144 +++++++++--- meson-native-clang | 5 +- meson.build | 13 +- shaders/tri.vert | 14 +- subprojects/glfw.wrap | 18 +- subprojects/packagefiles/glfw/meson.build | 145 ++++++++++++ .../packagefiles/libshaderc/meson.build | 34 ++- .../packagefiles/libshaderc_old/meson.build | 13 ++ .../packagefiles/shaderc_cmake/meson.build | 1 + subprojects/packagefiles/vma/vk_mem_alloc.cpp | 3 + subprojects/shaderc_cmake.wrap | 10 + .../{shaderc.wrap => shaderc_old.wrap} | 6 +- 32 files changed, 997 insertions(+), 182 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 evk/evkConstants.h create mode 100644 evk/evkVertexLayout.c create mode 100644 evk/evkVertexLayout.h create mode 100644 subprojects/packagefiles/glfw/meson.build create mode 100644 subprojects/packagefiles/libshaderc_old/meson.build create mode 100644 subprojects/packagefiles/shaderc_cmake/meson.build create mode 100644 subprojects/shaderc_cmake.wrap rename subprojects/{shaderc.wrap => shaderc_old.wrap} (79%) diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5e36b6b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "c", + "stdio": [ + "input.txt", + null + ], + "preLaunchTask": "Compile", + "expressions": "native", + "program": "${workspaceFolder}/build/evk.exe" + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..ff8db12 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Compile", + "type": "shell", + "command": "meson compile -C build" + }, + { + "label": "Run", + "type": "shell", + "command": "build/evk.exe" + }, + { + "label": "Test", + "type": "shell", + "command": "echo \"Hi Bye\"" + } + ] +} diff --git a/evk/evk.h b/evk/evk.h index d8c7a2d..7561332 100644 --- a/evk/evk.h +++ b/evk/evk.h @@ -13,4 +13,8 @@ #include "evkSwapChain.h" #include "evkCommand.h" #include "evkPipeline.h" +#include "evkMemory.h" #include "evkImage.h" +#include "evkBuffer.h" +#include "evkDescriptor.h" +#include "evkVertexLayout.h" diff --git a/evk/evkBuffer.c b/evk/evkBuffer.c index 5c84c05..f61c834 100644 --- a/evk/evkBuffer.c +++ b/evk/evkBuffer.c @@ -1,7 +1,7 @@ -#include "evkImage.h" +#include "evkBuffer.h" #include "evk/evkMemory.h" -evkBuffer evkCreateBuffer(evkBufferCreateInfo createInfo) +evkBuffer evkCreateBuffer(evkDevice* device, evkBufferCreateInfo createInfo) { VkBufferCreateInfo bufferCreateInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -9,8 +9,9 @@ evkBuffer evkCreateBuffer(evkBufferCreateInfo createInfo) .flags = createInfo.flags, .usage = createInfo.usage, .sharingMode = createInfo.exclusive?VK_SHARING_MODE_EXCLUSIVE:VK_SHARING_MODE_CONCURRENT, - .queueFamilyIndexCount = vec_len(&createInfo.queueFamilyIndices), + .queueFamilyIndexCount = createInfo.exclusive?0:vec_len(&createInfo.queueFamilyIndices), .pQueueFamilyIndices = createInfo.queueFamilyIndices, + .size = createInfo.sizeInBytes, }; evkBuffer buffer = evkGPUCreateBuffer(createInfo.allocationCreateInfo, &bufferCreateInfo); @@ -18,6 +19,10 @@ evkBuffer evkCreateBuffer(evkBufferCreateInfo createInfo) if(buffer.vk != VK_NULL_HANDLE) { buffer.sizeInBytes = createInfo.sizeInBytes; + buffer.address = vkGetBufferDeviceAddressKHR(device->vk, &(VkBufferDeviceAddressInfo){ + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .buffer = buffer.vk + }); } return buffer; diff --git a/evk/evkBuffer.h b/evk/evkBuffer.h index e8b8607..0adbfc4 100644 --- a/evk/evkBuffer.h +++ b/evk/evkBuffer.h @@ -2,5 +2,5 @@ #include "evkCommon.h" -evkBuffer evkCreateBuffer(evkBufferCreateInfo createInfo); +evkBuffer evkCreateBuffer(evkDevice* device, evkBufferCreateInfo createInfo); void evkDestroyBuffer(evkBuffer buf); diff --git a/evk/evkCommand.c b/evk/evkCommand.c index eaacff5..316140a 100644 --- a/evk/evkCommand.c +++ b/evk/evkCommand.c @@ -20,10 +20,9 @@ void evkDestroyCommandPool(evkDevice device, evkCommandPool commandPool) vkDestroyCommandPool(device.vk, commandPool.vk, NULL); } -vec(VkCommandBuffer) evkAllocateCommandBuffers(evkDevice device, evkCommandPool commandPool, u32 count, bool primary) +vec(evkCommandBuffer) evkAllocateCommandBuffers(evkDevice device, evkCommandPool commandPool, u32 count, bool primary) { - vec(VkCommandBuffer) buffers = vec_init(VkCommandBuffer); - vec_setlen(&buffers, count); + VkCommandBuffer vkBuffers[count]; VkCommandBufferAllocateInfo allocateInfo = (VkCommandBufferAllocateInfo) { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, @@ -32,20 +31,46 @@ vec(VkCommandBuffer) evkAllocateCommandBuffers(evkDevice device, evkCommandPool .level = primary?VK_COMMAND_BUFFER_LEVEL_PRIMARY:VK_COMMAND_BUFFER_LEVEL_SECONDARY, }; - vkAllocateCommandBuffers(device.vk, &allocateInfo, buffers); + vkAllocateCommandBuffers(device.vk, &allocateInfo, vkBuffers); + + vec(evkCommandBuffer) buffers = vec_init(evkCommandBuffer); + vec_setlen(&buffers, count); + for(int i = 0; i < count; i++) + { + buffers[i] = (evkCommandBuffer) { + .vk = vkBuffers[i], + .recording = false, + .boundPipeline = NULL, + }; + } return buffers; } -void evkBeginPrimaryCommandBuffer(VkCommandBuffer cmdBuf) +void evkFreeCommandBuffers(evkDevice device, evkCommandPool pool, vec(evkCommandBuffer) commandBuffers) +{ + vec(VkCommandBuffer) cmdbufs = vec_init(VkCommandBuffer); + + for(u32 i = 0; i < vec_len(&commandBuffers); i++) + { + vec_push(&cmdbufs, &commandBuffers[i].vk); + } + + vkFreeCommandBuffers(device.vk, pool.vk, vec_len(&cmdbufs), cmdbufs); +} + +void evkBeginPrimaryCommandBuffer(evkCommandBuffer* cmdBuf) { VkCommandBufferBeginInfo beginInfo = (VkCommandBufferBeginInfo) { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, }; - vkBeginCommandBuffer(cmdBuf, &beginInfo); + vkBeginCommandBuffer(cmdBuf->vk, &beginInfo); + cmdBuf->recording = true; } -void evkEndCommandBuffer(VkCommandBuffer cmdBuf) +void evkEndCommandBuffer(evkCommandBuffer* cmdBuf) { - vkEndCommandBuffer(cmdBuf); + vkEndCommandBuffer(cmdBuf->vk); + cmdBuf->recording = false; + cmdBuf->boundPipeline = NULL; } diff --git a/evk/evkCommand.h b/evk/evkCommand.h index 0ec0618..e077d0e 100644 --- a/evk/evkCommand.h +++ b/evk/evkCommand.h @@ -9,7 +9,9 @@ evkCommandPool evkCreateCommandPool(evkCommandPoolCreateInfo createInfo); void evkDestroyCommandPool(evkDevice device, evkCommandPool commandPool); [[nodiscard("Leaking allocated CommandBuffers")]] -vec(VkCommandBuffer) evkAllocateCommandBuffers(evkDevice device, evkCommandPool commandPool, u32 count, bool primary); +vec(evkCommandBuffer) evkAllocateCommandBuffers(evkDevice device, evkCommandPool commandPool, u32 count, bool primary); -void evkBeginPrimaryCommandBuffer(VkCommandBuffer cmdBuf); -void evkEndCommandBuffer(VkCommandBuffer cmdBuf); +void evkFreeCommandBuffers(evkDevice device, evkCommandPool pool, vec(evkCommandBuffer) commandBuffers); + +void evkBeginPrimaryCommandBuffer(evkCommandBuffer* cmdBuf); +void evkEndCommandBuffer(evkCommandBuffer* cmdBuf); diff --git a/evk/evkCommon.h b/evk/evkCommon.h index 929b7f9..9ae23a8 100644 --- a/evk/evkCommon.h +++ b/evk/evkCommon.h @@ -10,4 +10,5 @@ #define EV_VEC_SHORTNAMES #include +#include "evkConstants.h" #include "evkTypes.h" diff --git a/evk/evkConstants.h b/evk/evkConstants.h new file mode 100644 index 0000000..54dc4b4 --- /dev/null +++ b/evk/evkConstants.h @@ -0,0 +1,3 @@ +#pragma once + +#define MAX_DESCRIPTOR_SETS 4 diff --git a/evk/evkDescriptor.c b/evk/evkDescriptor.c index e05d7a2..7ea4499 100644 --- a/evk/evkDescriptor.c +++ b/evk/evkDescriptor.c @@ -1,43 +1,186 @@ -#pragma once - #include "evkDescriptor.h" +#include "evkBuffer.h" +#include "evkCommand.h" -typedef struct { - VkDescriptorSetLayout descriptorSetLayouts[4]; -} evkSetLayout; - -evkSetLayout evkCreateDescriptorSetLayouts(vec(evkShader) shaders) +EV_FORCEINLINE uint32_t aligned_size(uint32_t value, uint32_t alignment) { - VkDescriptorSetLayoutCreateInfo createInfos[4]; - for(int i = 0; i < 4; i++) - { - createInfos[i] = EV_DEFAULT( - VkDescriptorSetLayoutCreateInfo, - pBindings = vec_init(VkDescriptorSetLayoutBinding) - ); - } + return (value + alignment - 1) & ~(alignment - 1); +} - for(int i = 0; i < vec_len(&shaders); i++) +VkBufferUsageFlags evkGetDescriptorSetBufferUsageFlags(evkDescriptorSetLayout* layout) +{ + VkBufferUsageFlags flags = 0; + for(int i = 0; i < vec_len(&layout->vkBindings); i++) { - vec(evkDescriptorBinding) bindings = shaders[i].reflect.bindings; - for(int bi = 0; bi < vec_len(&bindings); bi++) + VkDescriptorType type = layout->vkBindings[i].descriptorType; + if(type == VK_DESCRIPTOR_TYPE_SAMPLER) { - evkDescriptorBinding b = bindings[bi]; - if(b.binding >= vec_len(&createInfos[b.set].pBindings)) + 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) { - u32 old_len = vec_len(&createInfos[b.set].pBindings); - vec_setlen(&createInfos[b.set].pBindings, b.binding+1); - for(int cs = old_len; cs < b.binding+1; cs++) - { - /* createInfos[b.set].pBindings[cs].binding */ - } + flags |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT; + break; } - } } - - for(int i = 0; i < 4; i++) - { - createInfos[i].bindingCount = vec_len(&createInfos[i].pBindings); - } + 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, &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); } diff --git a/evk/evkDescriptor.h b/evk/evkDescriptor.h index 3c3dadc..cf89705 100644 --- a/evk/evkDescriptor.h +++ b/evk/evkDescriptor.h @@ -3,3 +3,17 @@ #include "evkCommon.h" // void evkFillSetLayoutCreateInfos(vec(evkShader) shaders, VkDescriptorSetLayoutCreateInfo layoutCreateInfos[4]); + +evkDescriptorSetLayout evkCreateDescriptorSetLayoutFromBindings(evkDevice* device, vec(evkDescriptorBinding) bindings); +evkDescriptorSetLayout evkCreateDescriptorSetLayoutFromShaders(evkDevice* device, vec(evkShader) shaders); +void evkDestroyDescriptorSetLayout(evkDevice* device, evkDescriptorSetLayout* layout); + +evkDescriptorSet evkCreateDescriptorSet(evkDescriptorSetCreateInfo* createInfo); +void evkDestroyDescriptorSet(evkDevice* device, evkDescriptorSet* set); + +void evkSetDescriptor(evkDescriptorSet* set, evstring name, evkBuffer* buf); +void evkCmdBindDescriptorSets(evkCommandBuffer* cmdbuf, evkPipeline* pipeline, vec(evkDescriptorSet) sets, vec(u32) setIndices); + + +// evkDescriptorSet evkCreateDescriptorSet(evkDevice* device, evkGPUAllocator* allocator, vec(evkDescriptorBinding) bindings); +// void evkCmdBindDescriptorBuffers(VkCommandBuffer cmdbuf, vec(evkDescriptorSet) sets); diff --git a/evk/evkDevice.c b/evk/evkDevice.c index 13ea134..9d41360 100644 --- a/evk/evkDevice.c +++ b/evk/evkDevice.c @@ -2,18 +2,41 @@ #include "evkTypes.h" #include "evkAllocator.h" -evstring VkDynamicRenderingExtName = evstr("VK_KHR_dynamic_rendering"); -evstring VkSync2ExtName = evstr("VK_KHR_synchronization2"); +#define SUPPORTED_EXTENSION_FEATURE_PAIRS \ + (VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , features12.descriptorIndexing ), \ + (VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, features12.bufferDeviceAddress), \ + (VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME , features13.dynamicRendering ), \ + (VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME , features13.synchronization2 ) -VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeature = (VkPhysicalDeviceDynamicRenderingFeaturesKHR) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR, - .dynamicRendering = VK_TRUE, +#define EVK_ENABLE_EXTENSION_FEATURES(enabledExtensions,featuresStruct) \ + EV_FOREACH_UDATA(EVK_ENABLE_EXTENSION_FEATURE, (enabledExtensions, featuresStruct), SUPPORTED_EXTENSION_FEATURE_PAIRS) + +#define EVK_ENABLE_EXTENSION_FEATURE(ef_pair, name_flag_pair) \ + { \ + evstring name = evstr(EV_HEAD name_flag_pair); \ + if(ev_vec_find(&EV_HEAD ef_pair, &name) != -1) \ + EV_TAIL ef_pair.EV_TAIL name_flag_pair = true; \ + } + +VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptorBufFeature = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT, + .descriptorBuffer = VK_TRUE, + + EV_DEBUG( + .descriptorBufferCaptureReplay = VK_TRUE, + ) }; -VkPhysicalDeviceSynchronization2Features sync2Features = (VkPhysicalDeviceSynchronization2Features) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, - .synchronization2 = VK_TRUE, +typedef struct { + evstring name; + void* data; + void* ppNext; +} evkDeviceExtension; + +const evkDeviceExtension evkSupportedExtensions[] = { + { evstr(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME) , &descriptorBufFeature , &descriptorBufFeature.pNext }, }; +const u32 evkSupportedExtensionsCount = EV_ARRSIZE(evkSupportedExtensions); VkPhysicalDevice evkDetectPhysicalDevice(evkInstance instance, VkPhysicalDeviceType deviceType) { @@ -48,9 +71,22 @@ evkDevice evkCreateDevice(evkDeviceCreateInfo createInfo) device._physicalDevice = evkDetectPhysicalDevice(createInfo.instance, createInfo.physicalDeviceType); device._instance = createInfo.instance; - VkPhysicalDeviceProperties physicalDeviceProperties; - vkGetPhysicalDeviceProperties(device._physicalDevice, &physicalDeviceProperties); - device.limits = physicalDeviceProperties.limits; + VkPhysicalDeviceProperties2 physicalDeviceProperties = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + }; + + void** pNextProps = (void**)&physicalDeviceProperties.pNext; + + evstring VkDescriptorBufferExtName = evstr(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); + if(ev_vec_find(&createInfo.deviceExtensions, &VkDescriptorBufferExtName) != -1) + { + device.props.desc_buf = (VkPhysicalDeviceDescriptorBufferPropertiesEXT){ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT }; + *pNextProps = &device.props.desc_buf; + pNextProps = &device.props.desc_buf.pNext; + } + + vkGetPhysicalDeviceProperties2(device._physicalDevice, &physicalDeviceProperties); + device.props.limits = physicalDeviceProperties.properties.limits; for (u32 i = 0; i < MAX_QUEUE_FAMILIES; i++) { device.queueFamilies[i] = (evkDeviceQueueFamily){ @@ -61,22 +97,34 @@ evkDevice evkCreateDevice(evkDeviceCreateInfo createInfo) VkDeviceCreateInfo vkDeviceCreateInfo = __EV_VEC_EMPTY_ARRAY; vkDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - void** pNext = &vkDeviceCreateInfo.pNext; + void** pNext = (void**)&vkDeviceCreateInfo.pNext; - if(ev_vec_find(&createInfo.deviceExtensions, &VkDynamicRenderingExtName) != -1) + for(int i = 0; i < evkSupportedExtensionsCount; i++) { - *pNext = &dynamicRenderingFeature; - pNext = &dynamicRenderingFeature.pNext; + if(ev_vec_find(&createInfo.deviceExtensions, &evkSupportedExtensions[i].name) != -1) + { + *pNext = evkSupportedExtensions[i].data; + pNext = evkSupportedExtensions[i].ppNext; + } } - if(ev_vec_find(&createInfo.deviceExtensions, &VkSync2ExtName) != -1) - { - *pNext = &sync2Features; - pNext = &sync2Features.pNext; - } + EVK_ENABLE_EXTENSION_FEATURES(createInfo.deviceExtensions, createInfo.enabledFeatures); + + VkPhysicalDeviceFeatures2 enabledFeatures = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + .features = createInfo.enabledFeatures.features10, + .pNext = &createInfo.enabledFeatures.features11, + }; + createInfo.enabledFeatures.features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; + createInfo.enabledFeatures.features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + createInfo.enabledFeatures.features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; + createInfo.enabledFeatures.features11.pNext = &createInfo.enabledFeatures.features12; + createInfo.enabledFeatures.features12.pNext = &createInfo.enabledFeatures.features13; + *pNext = &enabledFeatures; + pNext = NULL; vkDeviceCreateInfo.enabledExtensionCount = vec_len(&createInfo.deviceExtensions); - vkDeviceCreateInfo.ppEnabledExtensionNames = createInfo.deviceExtensions; + vkDeviceCreateInfo.ppEnabledExtensionNames = (const char* const*) createInfo.deviceExtensions; // Getting the total number of queues requested from the device u32 totalQueueCount = 0; diff --git a/evk/evkInstance.h b/evk/evkInstance.h index 1e9fae1..4a77f5b 100644 --- a/evk/evkInstance.h +++ b/evk/evkInstance.h @@ -3,5 +3,5 @@ #include "evk.h" [[nodiscard("Leaking VkInstance")]] -evkInstance evkCreateInstance(evkInstanceCreateInfo); -void evkDestroyInstance(evkInstance); +evkInstance evkCreateInstance(evkInstanceCreateInfo instanceCreateInfo); +void evkDestroyInstance(evkInstance instance); diff --git a/evk/evkMemory.c b/evk/evkMemory.c index af41dc5..fa01a21 100644 --- a/evk/evkMemory.c +++ b/evk/evkMemory.c @@ -1,5 +1,3 @@ -#pragma once - #include "evkMemory.h" evkGPUAllocator evkGPUCreateAllocator(evkDevice device) @@ -7,6 +5,7 @@ evkGPUAllocator evkGPUCreateAllocator(evkDevice device) VmaVulkanFunctions vmaFunctions = { .vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties, .vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties, + .vkGetPhysicalDeviceMemoryProperties2KHR = vkGetPhysicalDeviceMemoryProperties2, .vkAllocateMemory = vkAllocateMemory, .vkFreeMemory = vkFreeMemory, .vkMapMemory = vkMapMemory, @@ -14,9 +13,13 @@ evkGPUAllocator evkGPUCreateAllocator(evkDevice device) .vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges, .vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges, .vkBindBufferMemory = vkBindBufferMemory, + .vkBindBufferMemory2KHR = vkBindBufferMemory2KHR, .vkBindImageMemory = vkBindImageMemory, + .vkBindImageMemory2KHR = vkBindImageMemory2KHR, .vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements, + .vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2, .vkGetImageMemoryRequirements = vkGetImageMemoryRequirements, + .vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR, .vkCreateBuffer = vkCreateBuffer, .vkDestroyBuffer = vkDestroyBuffer, .vkCreateImage = vkCreateImage, @@ -30,10 +33,11 @@ evkGPUAllocator evkGPUCreateAllocator(evkDevice device) .instance = device._instance.vk, .vulkanApiVersion = device._instance.apiVersion, .pVulkanFunctions = &vmaFunctions, + .flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT | VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT, }; evkGPUAllocator alloc; - vmaCreateAllocator(&createInfo, &alloc.vma); + assert(vmaCreateAllocator(&createInfo, &alloc.vma) == VK_SUCCESS); return alloc; } @@ -48,7 +52,7 @@ evkImage evkGPUCreateImage(evkGPUAllocationCreateInfo allocationCreateInfo, VkIm evkImage img; VmaAllocationCreateInfo vmaAllocCreateInfo = { - .usage = allocationCreateInfo.memoryUsage, + .usage = VMA_MEMORY_USAGE_AUTO, .flags = allocationCreateInfo.allocationFlags, .pool = allocationCreateInfo.pool.vma, }; @@ -63,17 +67,18 @@ void evkGPUDestroyImage(evkImage img) vmaDestroyImage(img.allocData.allocator.vma, img.vk, img.allocData.allocation.vma); } -evkBuffer evkGPUCreateBuffer(evkGPUAllocationCreateInfo allocationCreateInfo, VkBufferCreateInfo* imageCreateInfo) +evkBuffer evkGPUCreateBuffer(evkGPUAllocationCreateInfo allocationCreateInfo, VkBufferCreateInfo* bufferCreateInfo) { evkBuffer buf; VmaAllocationCreateInfo vmaAllocCreateInfo = { - .usage = allocationCreateInfo.memoryUsage, + .usage = VMA_MEMORY_USAGE_AUTO, .flags = allocationCreateInfo.allocationFlags, .pool = allocationCreateInfo.pool.vma, }; - vmaCreateBuffer(allocationCreateInfo.allocator.vma, imageCreateInfo, &vmaAllocCreateInfo, &buf.vk, &buf.allocData.allocation.vma, &buf.allocData.allocationInfo.vma); + vmaCreateBuffer(allocationCreateInfo.allocator.vma, bufferCreateInfo, &vmaAllocCreateInfo, &buf.vk, &buf.allocData.allocation.vma, &buf.allocData.allocationInfo.vma); + buf.usage = bufferCreateInfo->usage; return buf; } diff --git a/evk/evkPipeline.c b/evk/evkPipeline.c index fa152c5..7ce048e 100644 --- a/evk/evkPipeline.c +++ b/evk/evkPipeline.c @@ -2,6 +2,7 @@ #include "evk/evkTypes.h" #include "evkShader.h" +#include "evk/evkVertexLayout.h" const u32 DESCRIPTOR_SET_LAYOUT_COUNT = 4; @@ -9,8 +10,18 @@ evkPipelineLayout evkCreatePipelineLayout(evkDevice device, evkPipelineLayoutCre { evkPipelineLayout layout; + vec(VkDescriptorSetLayout) setLayouts = vec_init(VkDescriptorSetLayout); + for(int i = 0; i < vec_len(&createInfo.setLayouts); i++) + vec_push(&setLayouts, &createInfo.setLayouts[i].vk); + VkPipelineLayoutCreateInfo vkCreateInfo = (VkPipelineLayoutCreateInfo) { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .setLayoutCount = vec_len(&setLayouts), + .pSetLayouts = setLayouts, + .pushConstantRangeCount = vec_len(&createInfo.pushConstantRanges), + .pPushConstantRanges = createInfo.pushConstantRanges, }; vkCreatePipelineLayout(device.vk, &vkCreateInfo, NULL, &layout.vk); @@ -24,13 +35,19 @@ void evkDestroyPipelineLayout(evkDevice device, evkPipelineLayout layout) } -evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo) +evkPipeline evkCreateComputePipeline(evkDevice device, evkPipelineCreateInfo createInfo) +{ + +} + +evkPipeline evkCreateGraphicsPipeline(evkDevice device, evkPipelineCreateInfo createInfo) { u32 shaderStageCount = vec_len(&createInfo.shaderStages); u32 colorAttachmentCount = vec_len(&createInfo.colorAttachments); u32 dynamicStateCount = vec_len(&createInfo.dynamicStates); evkPipeline res; + res.type = createInfo.type; VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, @@ -65,7 +82,10 @@ evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo .attachmentCount = colorAttachmentCount, .pAttachments = colorAttachmentBlendStates, }; - memcpy(colorBlending.blendConstants, createInfo.blendConstants, sizeof(f32) * 4); + colorBlending.blendConstants[0] = createInfo.blendConstants[0]; + colorBlending.blendConstants[1] = createInfo.blendConstants[1]; + colorBlending.blendConstants[2] = createInfo.blendConstants[2]; + colorBlending.blendConstants[3] = createInfo.blendConstants[3]; u32 viewportCount = createInfo.viewportCountOverride; if(viewportCount == 0 && createInfo.viewports) @@ -100,10 +120,43 @@ evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo for(int i = 0; i < vec_len(&createInfo.shaderStages); i++) shaderStageCreateInfos[i] = evkGetShaderStageCreateInfo(createInfo.shaderStages[i]); + + vec(VkVertexInputBindingDescription) binding_descriptions = vec_init(VkVertexInputBindingDescription); + vec(VkVertexInputAttributeDescription) attribute_descriptions = vec_init(VkVertexInputAttributeDescription); + for(int i = 0; i < vec_len(&createInfo.vertexBufferLayouts); i++) + { + evkVertexBufferLayout buf = createInfo.vertexBufferLayouts[i]; + int vertexStride = 0; + for(int j = 0; j < EVK_VERTEX_ATTRIBUTE_TYPE_COUNT; j++) + { + evkVertexAttribute attr = buf.attributes[j]; + if(attr.fmt == EVK_VERTEX_ATTRIBUTE_INVALID) break; + VkVertexInputAttributeDescription attr_desc = { + .binding = i, + .location = j, + .format = evkVertexAttributeGetVkFormat(attr), + .offset = vertexStride, + }; + vec_push(&attribute_descriptions, &attr_desc); + vertexStride += evkVertexAttributeGetSize(attr); + } + + VkVertexInputBindingDescription vert_desc = // {0, 8, VK_VERTEX_INPUT_RATE_VERTEX}; + { + .inputRate = createInfo.vertexBufferLayouts[i].inputRate, + .binding = i, + .stride = vertexStride, + }; + + vec_push(&binding_descriptions, &vert_desc); + } + VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = 0, - .vertexAttributeDescriptionCount = 0, + .vertexBindingDescriptionCount = vec_len(&binding_descriptions), + .pVertexBindingDescriptions = binding_descriptions, + .vertexAttributeDescriptionCount = vec_len(&attribute_descriptions), + .pVertexAttributeDescriptions = attribute_descriptions, }; /* VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfos[DESCRIPTOR_SET_LAYOUT_COUNT] = {}; */ @@ -117,26 +170,34 @@ evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo /* } */ /* } */ - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfos[4]; + // VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfos[4]; + // + // svec(VkDescriptorSetLayout) descriptorSetLayouts = svec_init_w_len(VkDescriptorSetLayout, 4); + // + // for(int i = 0; i < 4; i++) + // { + // VkDescriptorSetLayoutCreateInfo dsCreateInfo = {}; + // + // // Fill descriptorSetLayoutCreateInfos[i] from shader reflection data + Create descriptorSetLayouts[i] + // } - svec(VkDescriptorSetLayout) descriptorSetLayouts = svec_init_w_len(VkDescriptorSetLayout, 4); - - for(int i = 0; i < 4; i++) + if(createInfo.setLayouts != NULL) { - VkDescriptorSetLayoutCreateInfo dsCreateInfo = {}; - - // Fill descriptorSetLayoutCreateInfos[i] from shader reflection data + Create descriptorSetLayouts[i] + res.layout = evkCreatePipelineLayout(device, + EV_DEFAULT(evkPipelineLayoutCreateInfo, + setLayouts = createInfo.setLayouts, + ) + ); + } + else + { + assert(!"Set Layout construction through shader reflection not implemented yet."); } - - res.layout = evkCreatePipelineLayout(device, - EV_DEFAULT(evkPipelineLayoutCreateInfo, - descriptorSetLayouts = descriptorSetLayouts - ) - ); VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &pipelineRenderingCreateInfo, + .flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT, .stageCount = shaderStageCount, .pStages = shaderStageCreateInfos, .pVertexInputState = &vertexInputStateCreateInfo, @@ -153,11 +214,28 @@ evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo res._device = device; + vec_fini(&attribute_descriptions); + vec_fini(&binding_descriptions); + return res; } +evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo) +{ + if(createInfo.type == EVK_PIPELINE_TYPE_GRAPHICS) + return evkCreateGraphicsPipeline(device, createInfo); + else + return evkCreateComputePipeline(device, createInfo); +} + void evkDestroyPipeline(evkPipeline pipeline) { vkDestroyPipeline(pipeline._device.vk, pipeline.vk, NULL); evkDestroyPipelineLayout(pipeline._device, pipeline.layout); } + +void evkCmdBindPipeline(evkCommandBuffer* cmdbuf, evkPipeline* pipeline) +{ + cmdbuf->boundPipeline = pipeline; + vkCmdBindPipeline(cmdbuf->vk, (VkPipelineBindPoint)pipeline->type, pipeline->vk); +} diff --git a/evk/evkPipeline.h b/evk/evkPipeline.h index a74af80..e3d1d61 100644 --- a/evk/evkPipeline.h +++ b/evk/evkPipeline.h @@ -8,3 +8,5 @@ void evkDestroyPipelineLayout(evkDevice device, evkPipelineLayout layout); evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo); void evkDestroyPipeline(evkPipeline pipeline); + +void evkCmdBindPipeline(evkCommandBuffer* cmdbuf, evkPipeline* pipeline); diff --git a/evk/evkShader.c b/evk/evkShader.c index 2494480..18dcb6c 100644 --- a/evk/evkShader.c +++ b/evk/evkShader.c @@ -1,6 +1,7 @@ #include "evk/evkShader.h" #include "shaderc/shaderc.h" #include "ev_helpers.h" +#include "spirv_reflect.h" evkShader evkInitShaderFromBytes(evkDevice device, const u8* shaderBytes, u32 shaderLen) { @@ -43,11 +44,12 @@ evkShaderReflectionData evkGenerateShaderReflectionData(const u8* shaderBytes, u for(int bindingIdx = 0; bindingIdx < currentSet->binding_count; bindingIdx++) { evkDescriptorBinding binding = { + .name = evstring_new(currentSet->bindings[bindingIdx]->name), .stageFlags = res.stage, .binding = currentSet->bindings[bindingIdx]->binding, .descriptorType = (VkDescriptorType) currentSet->bindings[bindingIdx]->descriptor_type, .descriptorCount = currentSet->bindings[bindingIdx]->count, - .set = currentSet->set, + // .set = currentSet->set, }; vec_push(&res.bindings, &binding); @@ -95,6 +97,7 @@ evkShaderCompiler evkCreateShaderCompiler() compiler.sc = shaderc_compiler_initialize(); compiler.scopt = shaderc_compile_options_initialize(); shaderc_compile_options_set_include_callbacks(compiler.scopt, _shader_include_resolve, _shader_include_release, NULL); + shaderc_compile_options_set_generate_debug_info(compiler.scopt); return compiler; } diff --git a/evk/evkTypes.h b/evk/evkTypes.h index c46cad8..3d17c5a 100644 --- a/evk/evkTypes.h +++ b/evk/evkTypes.h @@ -2,7 +2,6 @@ #include "evkCommon.h" #include "shaderc/shaderc.h" -#include "spirv_reflect.h" TYPEDATA_GEN(VkInstance, INVALID(VK_NULL_HANDLE)); TYPEDATA_GEN(VkDevice, INVALID(VK_NULL_HANDLE)); @@ -15,14 +14,14 @@ TYPEDATA_GEN(VkCommandBuffer); TYPEDATA_GEN(VkDynamicState); TYPEDATA_GEN(VkSurfaceFormatKHR); TYPEDATA_GEN(VkFormat); -TYPEDATA_GEN(VkClearValue, DEFAULT(0.f,0.f,0.f,1.f)); +TYPEDATA_GEN(VkClearValue, DEFAULT({{0.f,0.f,0.f,1.f}})); TYPEDATA_GEN(VkRenderingAttachmentInfoKHR, DEFAULT( .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, .imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, // Requires VK_KHR_synchronization2 .loadOp = VK_ATTACHMENT_LOAD_OP_NONE_KHR, .storeOp = VK_ATTACHMENT_STORE_OP_NONE, - .clearValue = (VkClearValue){0.f, 0.f, 0.f, 1.f}, + .clearValue = (VkClearValue){{{0.f, 0.f, 0.f, 1.f}}}, ) ); TYPEDATA_GEN(VkViewport, @@ -44,7 +43,7 @@ TYPEDATA_GEN(VkRenderingInfo, DEFAULT( .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, .flags = 0, - .renderArea = {0, 0, 0, 0}, + .renderArea = {{0, 0}, {0, 0}}, .layerCount = 1, .viewMask = 0, .colorAttachmentCount = 0, @@ -100,6 +99,9 @@ TYPEDATA_GEN(VkDescriptorSetLayoutCreateInfo, ) ); +TYPEDATA_GEN(VkVertexInputBindingDescription); +TYPEDATA_GEN(VkVertexInputAttributeDescription); + // ========================================================================================================= // // =================================evk Types=============================================================== // // ========================================================================================================= // @@ -116,11 +118,19 @@ typedef struct { u32 count; } evkDeviceQueueRequirement; +typedef struct { + VkPhysicalDeviceFeatures features10; + VkPhysicalDeviceVulkan11Features features11; + VkPhysicalDeviceVulkan12Features features12; + VkPhysicalDeviceVulkan13Features features13; +} evkPhysicalDeviceFeatures; + typedef struct { evkInstance instance; VkPhysicalDeviceType physicalDeviceType; ev_vec(evkDeviceQueueRequirement) queueRequirements; ev_vec(evstring) deviceExtensions; + evkPhysicalDeviceFeatures enabledFeatures; } evkDeviceCreateInfo; typedef struct { @@ -129,9 +139,9 @@ typedef struct { } evkDeviceQueueFamily; typedef struct { - bool dynamicRendering; - bool multiViewport; -} evkPhysicalDeviceFeatures; + VkPhysicalDeviceLimits limits; + VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf; +} evkDeviceProperties; #define MAX_QUEUE_FAMILIES ((VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT) + 1) typedef struct { @@ -139,7 +149,7 @@ typedef struct { VkPhysicalDevice _physicalDevice; evkInstance _instance; evkDeviceQueueFamily queueFamilies[MAX_QUEUE_FAMILIES]; - VkPhysicalDeviceLimits limits; + evkDeviceProperties props; evkPhysicalDeviceFeatures enabledFeatures; } evkDevice; @@ -174,11 +184,6 @@ typedef struct { VkPipelineLayout vk; } evkPipelineLayout; -typedef struct { - vec(VkDescriptorSetLayout) descriptorSetLayouts; - vec(VkPushConstantRange) pushConstantRanges; -} evkPipelineLayoutCreateInfo; - typedef struct { VkOffset2D renderOffset; VkExtent2D renderExtents; @@ -202,14 +207,30 @@ typedef union { }; } evkViewport; -typedef union { - VkDescriptorSetLayoutBinding vk; - struct { - VkDescriptorSetLayoutBinding; - u32 set; - }; +// typedef union { +// VkDescriptorSetLayoutBinding vk; +// struct { +// VkDescriptorSetLayoutBinding; +// u32 set; +// }; +// } evkDescriptorBinding; +// typedef VkDescriptorSetLayoutBinding evkDescriptorBinding; + +typedef struct { + evstring name; + VkDescriptorType descriptorType; + VkShaderStageFlags stageFlags; + uint32_t descriptorCount; + const VkSampler* pImmutableSamplers; + uint32_t binding; } evkDescriptorBinding; +// typedef struct { +// VkDescriptorSetLayout vk; +// vec(evkDescriptorBinding) bindings; +// } evkDescriptorSetLayout; +// typedef VkDescriptorSetLayout evkDescriptorSetLayout; + typedef struct { VkShaderStageFlags stage; vec(evkDescriptorBinding) bindings; @@ -265,6 +286,7 @@ typedef enum evkGPUMemoryUsage { EVK_GPU_MEMORY_USAGE_UNKNOWN = VMA_MEMORY_USAGE_UNKNOWN, EVK_GPU_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED, + EVK_GPU_MEMORY_USAGE_CPU_TO_GPU = VMA_MEMORY_USAGE_CPU_TO_GPU, EVK_GPU_MEMORY_USAGE_AUTO = VMA_MEMORY_USAGE_AUTO, EVK_GPU_MEMORY_USAGE_AUTO_PREFER_DEVICE = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, EVK_GPU_MEMORY_USAGE_AUTO_PREFER_HOST = VMA_MEMORY_USAGE_AUTO_PREFER_HOST, @@ -277,7 +299,6 @@ typedef struct { typedef struct { evkGPUAllocationFlags allocationFlags; - evkGPUMemoryUsage memoryUsage; evkGPUAllocator allocator; evkGPUMemoryPool pool; } evkGPUAllocationCreateInfo; @@ -315,6 +336,8 @@ typedef struct { VkBuffer vk; evkGPUAllocationData allocData; u32 sizeInBytes; + VkBufferUsageFlags usage; + VkDeviceAddress address; } evkBuffer; typedef struct { @@ -355,7 +378,88 @@ typedef struct { VkPipelineColorBlendAttachmentState blendState; } evkColorAttachment; +typedef enum { + EVK_VERTEX_ATTRIBUTE_INVALID = 0, + EVK_VERTEX_ATTRIBUTE_POSITION, + EVK_VERTEX_ATTRIBUTE_NORMAL, + EVK_VERTEX_ATTRIBUTE_TANGENT, + EVK_VERTEX_ATTRIBUTE_COLOR, + EVK_VERTEX_ATTRIBUTE_UV0, + EVK_VERTEX_ATTRIBUTE_UV1, + EVK_VERTEX_ATTRIBUTE_UV2, + EVK_VERTEX_ATTRIBUTE_UV3, + EVK_VERTEX_ATTRIBUTE_UV4, + EVK_VERTEX_ATTRIBUTE_UV5, + EVK_VERTEX_ATTRIBUTE_UV6, + EVK_VERTEX_ATTRIBUTE_UV7, + EVK_VERTEX_ATTRIBUTE_BLENDWEIGHT, + EVK_VERTEX_ATTRIBUTE_BLENDINDICES, + + EVK_VERTEX_ATTRIBUTE_TYPE_COUNT +} evkVertexAttributeType; + +typedef enum { + EVK_FMT_INVALID = 0, + EVK_FMT_FLOAT32, + EVK_FMT_UINT32, + EVK_FMT_SINT32, + EVK_FMT_FLOAT16, + EVK_FMT_UNORM16, + EVK_FMT_SNORM16, + EVK_FMT_UINT16, + EVK_FMT_SINT16, + EVK_FMT_UNORM8, + EVK_FMT_SNORM8, + EVK_FMT_UINT8, + EVK_FMT_SINT8, + + EVK_VERTEX_ATTRIBUTE_FORMAT_COUNT +} evkVertexAttributeFormat; + typedef struct { + evkVertexAttributeType type; + evkVertexAttributeFormat fmt; + u32 dim; +} evkVertexAttribute; + +typedef struct { + evkVertexAttribute attributes[EVK_VERTEX_ATTRIBUTE_TYPE_COUNT]; + VkVertexInputRate inputRate; +} evkVertexBufferLayout; +// typedef evkVertexAttribute evkVertexBufferLayout[EVK_VERTEX_ATTRIBUTE_TYPE_COUNT]; + +typedef struct { + VkDescriptorSetLayout vk; + vec(evstring) names; + vec(VkDescriptorSetLayoutBinding) vkBindings; + u64 size; + u64 offset; +} evkDescriptorSetLayout; + +typedef struct { + evkDevice* device; + evkGPUAllocator* allocator; + evkDescriptorSetLayout* layout; +} evkDescriptorSetCreateInfo; + +typedef struct { + evkDevice* device; + evkDescriptorSetLayout layout; + evkBuffer buffer; +} evkDescriptorSet; + +typedef enum { + EVK_PIPELINE_TYPE_GRAPHICS = VK_PIPELINE_BIND_POINT_GRAPHICS, + EVK_PIPELINE_TYPE_COMPUTE = VK_PIPELINE_BIND_POINT_COMPUTE, +} evkPipelineType; + +typedef struct { + vec(evkDescriptorSetLayout) setLayouts; + vec(VkPushConstantRange) pushConstantRanges; +} evkPipelineLayoutCreateInfo; + +typedef struct { + evkPipelineType type; vec(VkDynamicState) dynamicStates; vec(evkShader) shaderStages; @@ -369,14 +473,25 @@ typedef struct { u32 viewportCountOverride; vec(evkViewport) viewports; + + vec(evkVertexBufferLayout) vertexBufferLayouts; + vec(evkDescriptorSetLayout) setLayouts; } evkPipelineCreateInfo; typedef struct { VkPipeline vk; evkPipelineLayout layout; evkDevice _device; + evkPipelineType type; + evkDescriptorSet boundSets[MAX_DESCRIPTOR_SETS]; } evkPipeline; +typedef struct { + VkCommandBuffer vk; + bool recording; + evkPipeline* boundPipeline; +} evkCommandBuffer; + TYPEDATA_GEN(evkInstance, INVALID( .vk = VK_NULL_HANDLE, @@ -387,7 +502,7 @@ TYPEDATA_GEN(evkShader); TYPEDATA_GEN(evkPipelineLayoutCreateInfo, DEFAULT( - .descriptorSetLayouts = EV_VEC_EMPTY, + .setLayouts = EV_VEC_EMPTY, .pushConstantRanges = EV_VEC_EMPTY, ) ); @@ -435,6 +550,7 @@ TYPEDATA_GEN(evkColorAttachment); TYPEDATA_GEN(evkPipelineCreateInfo, DEFAULT( + .type = EVK_PIPELINE_TYPE_GRAPHICS, .dynamicStates = EV_VEC_EMPTY, .shaderStages = EV_VEC_EMPTY, @@ -445,4 +561,11 @@ TYPEDATA_GEN(evkPipelineCreateInfo, ) ); +TYPEDATA_GEN(evkVertexBufferLayout); +TYPEDATA_GEN(evkVertexAttribute); + TYPEDATA_GEN(evkDescriptorBinding); +TYPEDATA_GEN(evkDescriptorSetLayout); +TYPEDATA_GEN(evkDescriptorSet); + +TYPEDATA_GEN(evkCommandBuffer); diff --git a/evk/evkVertexLayout.c b/evk/evkVertexLayout.c new file mode 100644 index 0000000..5f36440 --- /dev/null +++ b/evk/evkVertexLayout.c @@ -0,0 +1 @@ +#include "evkVertexLayout.h" diff --git a/evk/evkVertexLayout.h b/evk/evkVertexLayout.h new file mode 100644 index 0000000..32426ed --- /dev/null +++ b/evk/evkVertexLayout.h @@ -0,0 +1,47 @@ +#pragma once + +#include "evk.h" + +const static VkFormat evkToVkFmtLUT[][5] = { + [EVK_FMT_INVALID] = { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED , VK_FORMAT_UNDEFINED , VK_FORMAT_UNDEFINED , VK_FORMAT_UNDEFINED }, + [EVK_FMT_FLOAT32] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT }, + [EVK_FMT_UINT32] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_UINT , VK_FORMAT_R32G32_UINT , VK_FORMAT_R32G32B32_UINT , VK_FORMAT_R32G32B32A32_UINT }, + [EVK_FMT_SINT32] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SINT , VK_FORMAT_R32G32_SINT , VK_FORMAT_R32G32B32_SINT , VK_FORMAT_R32G32B32A32_SINT }, + [EVK_FMT_FLOAT16] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_R16G16B16_SFLOAT, VK_FORMAT_R16G16B16A16_SFLOAT }, + [EVK_FMT_UNORM16] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R16_UNORM , VK_FORMAT_R16G16_UNORM , VK_FORMAT_R16G16B16_UNORM , VK_FORMAT_R16G16B16A16_UNORM }, + [EVK_FMT_SNORM16] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R16_SNORM , VK_FORMAT_R16G16_SNORM , VK_FORMAT_R16G16B16_SNORM , VK_FORMAT_R16G16B16A16_SNORM }, + [EVK_FMT_UINT16] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R16_UINT , VK_FORMAT_R16G16_UINT , VK_FORMAT_R16G16B16_UINT , VK_FORMAT_R16G16B16A16_UINT }, + [EVK_FMT_SINT16] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R16_SINT , VK_FORMAT_R16G16_SINT , VK_FORMAT_R16G16B16_SINT , VK_FORMAT_R16G16B16A16_SINT }, + [EVK_FMT_UNORM8] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R8_UNORM , VK_FORMAT_R8G8_UNORM , VK_FORMAT_R8G8B8_UNORM , VK_FORMAT_R8G8B8A8_UNORM }, + [EVK_FMT_SNORM8] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R8_SNORM , VK_FORMAT_R8G8_SNORM , VK_FORMAT_R8G8B8_SNORM , VK_FORMAT_R8G8B8A8_SNORM }, + [EVK_FMT_UINT8] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R8_UINT , VK_FORMAT_R8G8_UINT , VK_FORMAT_R8G8B8_UINT , VK_FORMAT_R8G8B8A8_UINT }, + [EVK_FMT_SINT8] = { VK_FORMAT_UNDEFINED, VK_FORMAT_R8_SINT , VK_FORMAT_R8G8_SINT , VK_FORMAT_R8G8B8_SINT , VK_FORMAT_R8G8B8A8_SINT }, +}; + +const static u32 evkFmtToSizeLUT[][5] = { + [EVK_FMT_INVALID] = { 0, 0, 0, 0, 0 }, + [EVK_FMT_FLOAT32] = { 0, 4, 8, 12, 16 }, + [EVK_FMT_UINT32] = { 0, 4, 8, 12, 16 }, + [EVK_FMT_SINT32] = { 0, 4, 8, 12, 16 }, + [EVK_FMT_FLOAT16] = { 0, 2, 4, 6, 8 }, + [EVK_FMT_UNORM16] = { 0, 2, 4, 6, 8 }, + [EVK_FMT_SNORM16] = { 0, 2, 4, 6, 8 }, + [EVK_FMT_UINT16] = { 0, 2, 4, 6, 8 }, + [EVK_FMT_SINT16] = { 0, 2, 4, 6, 8 }, + [EVK_FMT_UNORM8] = { 0, 1, 2, 3, 4 }, + [EVK_FMT_SNORM8] = { 0, 1, 2, 3, 4 }, + [EVK_FMT_UINT8] = { 0, 1, 2, 3, 4 }, + [EVK_FMT_SINT8] = { 0, 1, 2, 3, 4 }, +}; + +static EV_FORCEINLINE VkFormat evkVertexAttributeGetVkFormat(evkVertexAttribute attr) +{ + if(attr.dim > 4) assert(!"Unsupported Vertex Attribute Dimension"); + return evkToVkFmtLUT[attr.fmt][attr.dim]; +} + +static EV_FORCEINLINE u32 evkVertexAttributeGetSize(evkVertexAttribute attr) +{ + if(attr.dim > 4) assert(!"Unsupported Vertex Attribute Dimension"); + return evkFmtToSizeLUT[attr.fmt][attr.dim]; +} diff --git a/main.c b/main.c index a0b646e..71dea40 100644 --- a/main.c +++ b/main.c @@ -7,12 +7,6 @@ evstring PROJECT_NAME = evstr("evk"); -float vertexPositions[] = { - 0.f,-.5f, - .5f, .5f, - -.5f, .5f -}; - int main(void) { u32 width = 1024; @@ -20,10 +14,10 @@ int main(void) evkInstance instance = evkCreateInstance((evkInstanceCreateInfo){ .applicationInfo = EV_DEFAULT(evkApplicationInfo), - .layers = svec_init(evstring, { + .layers = svec_init(evstring, { evstr("VK_LAYER_KHRONOS_validation"), }), - .extensions = svec_init(evstring, { + .extensions = svec_init(evstring, { evstr("VK_KHR_surface"), evstr("VK_KHR_win32_surface"), }), @@ -51,6 +45,7 @@ int main(void) evstr("VK_KHR_synchronization2"), evstr("VK_KHR_buffer_device_address"), evstr("VK_EXT_descriptor_indexing"), + evstr("VK_EXT_descriptor_buffer"), }), }); @@ -85,6 +80,8 @@ int main(void) puts("Surface creation failed."); } + evkGPUAllocator allocator = evkGPUCreateAllocator(device); + evkSwapChain swapChain = evkCreateSwapChain((evkSwapChainCreateInfo){ .device = device, .surface = surface, @@ -99,7 +96,7 @@ int main(void) .poolFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT }); - vec(VkCommandBuffer) commandBuffers = evkAllocateCommandBuffers(device, commandPool, vec_len(&swapChain.images), true); + vec(evkCommandBuffer) commandBuffers = evkAllocateCommandBuffers(device, commandPool, vec_len(&swapChain.images), true); evkShaderCompiler compiler = evkCreateShaderCompiler(); @@ -109,10 +106,25 @@ int main(void) evkDestroyShaderCompiler(compiler); evkColorAttachment colorAttachment0 = { - swapChain.surfaceFormat.format, + swapChain.surfaceFormat.format, EV_DEFAULT(VkPipelineColorBlendAttachmentState) }; + // TODO Get this from shader reflection data + // evkDescriptorSetLayout setLayout_0 = evkCreateDescriptorSetLayout( + // &device, svec_init(evkDescriptorBinding, { + // { + // .name = evstr("positions"), + // .binding = 0, + // .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + // .descriptorCount = 1, + // .stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS, + // }, + // }) + // ); + // evkDescriptorSetLayout setLayout_0 = evkCreateDescriptorSetLayoutFromBindings(&device, vertShader.reflect.bindings); + evkDescriptorSetLayout setLayout_0 = evkCreateDescriptorSetLayoutFromShaders(&device, svec_init(evkShader, {vertShader, fragShader})); + evkPipelineCreateInfo pipelineCreateInfo = EV_DEFAULT(evkPipelineCreateInfo, dynamicStates = svec_init(VkDynamicState, { VK_DYNAMIC_STATE_VIEWPORT, @@ -126,8 +138,64 @@ int main(void) colorAttachment0, }), viewportCountOverride = 1, + + vertexBufferLayouts = svec_init(evkVertexBufferLayout, { + {{ // VB #0 + { EVK_VERTEX_ATTRIBUTE_POSITION, EVK_FMT_FLOAT32, 2 }, + }}, + }), + + setLayouts = svec_init(evkDescriptorSetLayout, {setLayout_0}), ); + evkDescriptorSet set_0 = evkCreateDescriptorSet(&(evkDescriptorSetCreateInfo){ + .device = &device, + .allocator = &allocator, + .layout = &setLayout_0 + }); + + + // // if stageflags is 0, it's all graphics + // // if descriptor count is 0, it's 1 + // // if + // evkDescriptorSetLayout set_0 = evkCreateDescriptorSetLayout(&device, svec_init(evkDescriptorBinding, { + // { "positions", VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER }, + // }) + // ); + + evkBuffer vertBuf = evkCreateBuffer(&device, (evkBufferCreateInfo) { + .queueFamilyIndices = svec_init(u32, {device.queueFamilies[VK_QUEUE_GRAPHICS_BIT].familyIndex}), + .sizeInBytes = 6 * 4, + .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + .allocationCreateInfo = { + .allocationFlags = EVK_GPU_ALLOCATION_CREATE_MAPPED_BIT | EVK_GPU_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .allocator = allocator, + }, + .exclusive = true, + }); + + evkBuffer uniBuf = evkCreateBuffer(&device, (evkBufferCreateInfo) { + .sizeInBytes = 12 * 4, + .usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + .allocationCreateInfo = { + .allocationFlags = EVK_GPU_ALLOCATION_CREATE_MAPPED_BIT | EVK_GPU_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .allocator = allocator, + }, + .exclusive = true, + }); + + float* vert_arr = (float*)vertBuf.allocData.allocationInfo.vma.pMappedData; + vert_arr[0] = 0.0f; vert_arr[1] = -0.5f; + vert_arr[2] = 0.5f; vert_arr[3] = 0.5f; + vert_arr[4] = -0.5f; vert_arr[5] = 0.5f; + + float* uni_arr = (float*)uniBuf.allocData.allocationInfo.vma.pMappedData; + uni_arr[0] = 0.0f; uni_arr[1] = -0.5f; uni_arr[2] = 0.0f; uni_arr[3] = 1.0f; + uni_arr[4] = 0.5f; uni_arr[5] = 0.5f; uni_arr[6] = 0.0f; uni_arr[7] = 1.0f; + uni_arr[8] = -0.5f; uni_arr[9] = 0.5f; uni_arr[10] = 0.0f; uni_arr[11] = 1.0f; + + evkSetDescriptor(&set_0, evstr("vertexData"), &uniBuf); + VkViewport viewport = EV_DEFAULT(VkViewport, width=width, height=height); VkRect2D scissor = EV_DEFAULT(VkRect2D,extent.width=width, extent.height=height); @@ -142,7 +210,7 @@ int main(void) u32 imageIdx; vkAcquireNextImageKHR(device.vk, swapChain.vk, UInt64.MAX, imageAcquiredSemaphore, VK_NULL_HANDLE, &imageIdx); - VkCommandBuffer cmdbuf = commandBuffers[imageIdx]; + evkCommandBuffer cmdbuf = commandBuffers[imageIdx]; VkRenderingAttachmentInfoKHR colorAttachment = EV_DEFAULT(VkRenderingAttachmentInfoKHR, imageView = swapChain.imageViews[imageIdx].vk, @@ -156,38 +224,43 @@ int main(void) colorAttachmentCount = 1, ); - evkBeginPrimaryCommandBuffer(cmdbuf); + evkBeginPrimaryCommandBuffer(&cmdbuf); + { + VkDeviceSize offset = 0; + vkCmdBindVertexBuffers(cmdbuf.vk, 0, 1, &vertBuf.vk, &offset); - vkCmdSetScissor(cmdbuf, 0, 1, &scissor); - vkCmdSetViewport(cmdbuf, 0, 1, &viewport); + evkCmdBindDescriptorSets(&cmdbuf, &graphicsPipeline, svec_init(evkDescriptorSet, { set_0 }), svec_init(u32, { 0 })); - vkCmdBeginRenderingKHR(cmdbuf, &renderingInfo); + vkCmdSetScissor(cmdbuf.vk, 0, 1, &scissor); + vkCmdSetViewport(cmdbuf.vk, 0, 1, &viewport); - vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.vk); - vkCmdDraw(cmdbuf, 3, 1, 0, 0); + vkCmdBeginRenderingKHR(cmdbuf.vk, &renderingInfo); - vkCmdEndRenderingKHR(cmdbuf); + evkCmdBindPipeline(&cmdbuf, &graphicsPipeline); + vkCmdDraw(cmdbuf.vk, 3, 1, 0, 0); - VkImageMemoryBarrier imageMemoryBarrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .image = swapChain.images[imageIdx].vk, - .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .layerCount = 1, - .levelCount = 1, - }, - }; + vkCmdEndRenderingKHR(cmdbuf.vk); - vkCmdPipelineBarrier(cmdbuf, 0, 0, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier); + VkImageMemoryBarrier imageMemoryBarrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .image = swapChain.images[imageIdx].vk, + .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .layerCount = 1, + .levelCount = 1, + }, + }; - evkEndCommandBuffer(cmdbuf); + vkCmdPipelineBarrier(cmdbuf.vk, 0, 0, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier); + } + evkEndCommandBuffer(&cmdbuf); VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; VkSubmitInfo submitInfo = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pCommandBuffers = &cmdbuf, + .pCommandBuffers = &cmdbuf, // TODO This won't work with more than a single cmdbuf .commandBufferCount = 1, .waitSemaphoreCount = 1, .pWaitSemaphores = &imageAcquiredSemaphore, @@ -210,7 +283,7 @@ int main(void) }; vkQueuePresentKHR(graphicsQueue, &presentInfo); - vkResetCommandBuffer(cmdbuf,VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); + vkResetCommandBuffer(cmdbuf.vk,VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); // Main Loop glfwPollEvents(); @@ -224,15 +297,18 @@ int main(void) evkDestroyPipeline(graphicsPipeline); + evkDestroyDescriptorSet(&device, &set_0); + evkDestroyDescriptorSetLayout(&device, &setLayout_0); + evkDestroyShader(device, vertShader); evkDestroyShader(device, fragShader); - vkFreeCommandBuffers(device.vk, commandPool.vk, vec_len(&commandBuffers), commandBuffers); + evkFreeCommandBuffers(device, commandPool, commandBuffers); evkDestroyCommandPool(device, commandPool); evkDestroySwapChain(device, swapChain); -SwapchainCreationFailed: +// SwapchainCreationFailed: vkDestroySurfaceKHR(instance.vk, swapChain.surface, NULL); VKSurfaceCreationFailed: diff --git a/meson-native-clang b/meson-native-clang index 2bd8f74..2840a22 100644 --- a/meson-native-clang +++ b/meson-native-clang @@ -5,4 +5,7 @@ cpp = 'clang++.exe' cpp_ld = 'lld' [properties] -c_args = ['-DEV_CC_CLANG=1'] +c_args = ['-DEV_CC_CLANG=1','-fcolor-diagnostics', '-fansi-escape-codes'] + +[cmake] +CMAKE_C_COMPILER = 'clang.exe' diff --git a/meson.build b/meson.build index d8afbf2..7f3b855 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('evk', ['c','cpp'], version : '0.1', - default_options : ['c_std=gnu23']) + default_options : ['c_std=gnu23', 'default_library=static']) build_config = configuration_data() @@ -15,6 +15,12 @@ endif configure_file(output: 'evk_buildconfig.h', configuration: build_config) +disabled_warnings = { + 'clang': [ + 'microsoft-anon-tag', + ], +} + subproject('evol-headers') evh_c_args = [] @@ -26,6 +32,10 @@ elif cc.get_id() == 'clang' evh_c_args += '-DEV_CC_CLANG=1' endif +foreach w : disabled_warnings[cc.get_id()] + evh_c_args += '-Wno-'+w +endforeach + evk_incdir = [ '.', ] @@ -45,6 +55,7 @@ evk_src = [ 'evk/evkDescriptor.c', 'evk/evkRender.c', 'evk/evkImage.c', + 'evk/evkBuffer.c', 'evk/evkMemory.c', ] diff --git a/shaders/tri.vert b/shaders/tri.vert index 331b5a1..269a19a 100644 --- a/shaders/tri.vert +++ b/shaders/tri.vert @@ -1,15 +1,15 @@ #version 450 #pragma shader_stage(vertex) -vec2 positions[3] = vec2[]( - vec2(0.0, -0.5), - vec2(0.5, 0.5), - vec2(-0.5, 0.5) -); - // in layout(location=0) vec2 position; +layout(set=0, binding=0) uniform data { + vec4 positions[3]; +} vertexData; + void main() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + // gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); // gl_Position = vec4(position, 0.0, 1.0); + // gl_Position = vec4(inputData.positions[gl_VertexIndex], 0.0, 1.0); + gl_Position = vertexData.positions[gl_VertexIndex]; } diff --git a/subprojects/glfw.wrap b/subprojects/glfw.wrap index c5a9751..f12a295 100644 --- a/subprojects/glfw.wrap +++ b/subprojects/glfw.wrap @@ -1,13 +1,11 @@ -[wrap-file] -directory = glfw-3.3.10 -source_url = https://github.com/glfw/glfw/archive/refs/tags/3.3.10.tar.gz -source_filename = glfw-3.3.10.tar.gz -source_hash = 4ff18a3377da465386374d8127e7b7349b685288cb8e17122f7e1179f73769d5 -patch_filename = glfw_3.3.10-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/glfw_3.3.10-1/get_patch -patch_hash = 3567f96c2576a5fc8c9cafd9059f919d7da404f6c22450c6c2ce3f9938909b8b -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/glfw_3.3.10-1/glfw-3.3.10.tar.gz -wrapdb_version = 3.3.10-1 +[wrap-git] +directory = glfw + +url = https://github.com/glfw/glfw +revision = 3.3.10 +depth=1 + +patch_directory = glfw [provide] glfw3 = glfw_dep diff --git a/subprojects/packagefiles/glfw/meson.build b/subprojects/packagefiles/glfw/meson.build new file mode 100644 index 0000000..c98f848 --- /dev/null +++ b/subprojects/packagefiles/glfw/meson.build @@ -0,0 +1,145 @@ +# Modified Meson WrapDB file +project( + 'glfw', + 'c', + version: '3.3.10', + license: 'Zlib', + default_options: ['b_ndebug=if-release', 'c_std=c99', 'warning_level=0'], + meson_version: '>=0.58.0', +) +#@ Project variables +sys_os = host_machine.system() +sys_cc = meson.get_compiler('c') +opt_libdir = get_option('libdir') +is_posix = sys_os != 'windows' + +if get_option('default_library') != 'static' + add_project_arguments('-D_GLFW_BUILD_DLL', language: 'c') +endif + +if sys_os == 'windows' + opt_display = 'win32' +elif sys_os == 'darwin' + opt_display = 'cocoa' +else + opt_display = 'x11' +endif + +### Dependencies ### +deps = [] +#@ Backend API + # X11 +if opt_display == 'x11' + foreach x : ['x11', 'xrandr', 'xinerama', 'xcursor', 'xi', 'xkbcommon'] + deps += dependency(x, required: true) + endforeach + # Win32 +elif opt_display == 'win32' + if sys_os != 'windows' + error('Non Windows is unsupportred') + endif + # Cocoa +elif opt_display == 'cocoa' + if sys_os != 'darwin' + error('Non macOS is unsupported') + endif + deps += dependency('appleframeworks', modules: ['Cocoa', 'CoreFoundation', 'IOKit']) +endif + +#@ System Dependencies +foreach l : ['m', 'rt'] + deps += sys_cc.find_library(l, required: false) +endforeach +if meson.version().version_compare('>= 0.62') + deps += dependency('dl', required: false) +else + deps += sys_cc.find_library('dl', required: false) +endif +deps += dependency('threads') + +### Configuration ### +cfg_data = configuration_data() +foreach d : ['osmesa', 'x11', 'wayland', 'win32', 'cocoa'] + cfg_data.set('_GLFW_' + d.to_upper(), opt_display == d) +endforeach +cfg_file = configure_file(configuration: cfg_data, output: 'glfw_config.h') + +### Targets ### +#@ Primary target: +## GLFW library +# Common files +s_common = files('src/context.c', 'src/init.c', 'src/input.c', 'src/monitor.c', 'src/vulkan.c', 'src/window.c') +s_common += cfg_file + +# Backend files +if opt_display == 'x11' + s_display = files( + 'src/egl_context.c', + 'src/glx_context.c', + 'src/osmesa_context.c', + 'src/posix_thread.c', + 'src/posix_time.c', + 'src/x11_init.c', + 'src/x11_monitor.c', + 'src/x11_window.c', + 'src/xkb_unicode.c', + 'src/@0@_joystick.c'.format(sys_os == 'linux' ? 'linux' : 'null'), + ) +elif opt_display == 'win32' + s_display = files( + 'src/egl_context.c', + 'src/osmesa_context.c', + 'src/wgl_context.c', + 'src/win32_init.c', + 'src/win32_joystick.c', + 'src/win32_monitor.c', + 'src/win32_thread.c', + 'src/win32_time.c', + 'src/win32_window.c', + ) +elif opt_display == 'cocoa' + add_languages('objc', native: false) + s_display = files( + 'src/cocoa_init.m', + 'src/cocoa_joystick.m', + 'src/cocoa_monitor.m', + 'src/cocoa_time.c', + 'src/cocoa_window.m', + 'src/egl_context.c', + 'src/nsgl_context.m', + 'src/osmesa_context.c', + 'src/posix_thread.c', + ) + add_project_arguments('-D_GLFW_USE_CONFIG_H', language: 'objc') + if host_machine.system() == 'darwin' + add_project_arguments('-D_DARWIN_C_SOURCE', language: 'objc') + endif +endif +srcfiles = [s_common, s_display] +incdirs = include_directories('include', 'src') + +#@ Flags +add_project_arguments('-D_GLFW_USE_CONFIG_H', language: 'c') +if host_machine.system() == 'darwin' + add_project_arguments('-D_DARWIN_C_SOURCE', language: 'c') +endif + +c_args = ['-Wno-everything'] + +# Build +glfw_lib = library( + 'glfw3', + srcfiles, + include_directories: incdirs, + dependencies: deps, + version: meson.project_version(), + build_by_default: true, + pic: true, + c_args: c_args, +) +glfw_dep = declare_dependency( + include_directories: incdirs, + link_with: glfw_lib, +) + +meson.override_dependency('glfw3', glfw_dep) diff --git a/subprojects/packagefiles/libshaderc/meson.build b/subprojects/packagefiles/libshaderc/meson.build index b71f4df..c7017a0 100644 --- a/subprojects/packagefiles/libshaderc/meson.build +++ b/subprojects/packagefiles/libshaderc/meson.build @@ -1,13 +1,27 @@ -project('libshaderc', 'cpp', default_options: ['buildtype=release']) +project('libshaderc', 'cpp') -fs = import('fs') -cxxc = meson.get_compiler('cpp') - -shaderc_inc = include_directories('install/include') - -shaderc_dep = declare_dependency( - dependencies: cxxc.find_library('shaderc_combined', dirs: meson.current_source_dir()/'install/lib'), - include_directories: shaderc_inc, -) +python = find_program('python3') +run_command(python, './utils/git-sync-deps', check: true) +cmake = import('cmake') +opts = cmake.subproject_options() +opts.add_cmake_defines({ + 'CMAKE_MSVC_RUNTIME_LIBRARY': 'MultiThreaded', + 'CMAKE_POLICY_DEFAULT_CMP0091': 'NEW', + 'SHADERC_SKIP_INSTALL': 'ON', + 'SHADERC_SKIP_TESTS': 'ON', + 'SHADERC_SKIP_EXAMPLES': 'ON', + 'SHADERC_SKIP_COPYRIGHT_CHECK': 'ON' +}) +shaderc_proj = cmake.subproject('shaderc', options: opts) +shaderc_dep = declare_dependency(dependencies: [ + shaderc_proj.dependency('shaderc'), + shaderc_proj.dependency('shaderc_util'), + shaderc_proj.dependency('SPIRV'), + shaderc_proj.dependency('SPIRV-Tools-static'), + shaderc_proj.dependency('SPIRV-Tools-opt'), + shaderc_proj.dependency('glslang'), + shaderc_proj.dependency('GenericCodeGen'), + shaderc_proj.dependency('MachineIndependent'), +]) meson.override_dependency('shaderc', shaderc_dep) diff --git a/subprojects/packagefiles/libshaderc_old/meson.build b/subprojects/packagefiles/libshaderc_old/meson.build new file mode 100644 index 0000000..1392216 --- /dev/null +++ b/subprojects/packagefiles/libshaderc_old/meson.build @@ -0,0 +1,13 @@ +project('libshaderc', 'cpp', default_options: ['buildtype=release', 'default_library=static']) + +fs = import('fs') +cxxc = meson.get_compiler('cpp') + +shaderc_inc = include_directories('install/include') + +shaderc_dep = declare_dependency( + dependencies: cxxc.find_library('shaderc_combined', dirs: meson.current_source_dir()/'install/lib'), + include_directories: shaderc_inc, +) + +meson.override_dependency('shaderc', shaderc_dep) diff --git a/subprojects/packagefiles/shaderc_cmake/meson.build b/subprojects/packagefiles/shaderc_cmake/meson.build new file mode 100644 index 0000000..a548478 --- /dev/null +++ b/subprojects/packagefiles/shaderc_cmake/meson.build @@ -0,0 +1 @@ +project('shaderc_cmake', 'cpp') diff --git a/subprojects/packagefiles/vma/vk_mem_alloc.cpp b/subprojects/packagefiles/vma/vk_mem_alloc.cpp index 9c32887..cafa49e 100644 --- a/subprojects/packagefiles/vma/vk_mem_alloc.cpp +++ b/subprojects/packagefiles/vma/vk_mem_alloc.cpp @@ -1,4 +1,7 @@ #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0 #define VMA_IMPLEMENTATION +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Weverything" #include +#pragma clang diagnostic pop diff --git a/subprojects/shaderc_cmake.wrap b/subprojects/shaderc_cmake.wrap new file mode 100644 index 0000000..e9730b7 --- /dev/null +++ b/subprojects/shaderc_cmake.wrap @@ -0,0 +1,10 @@ +[wrap-git] +directory = shaderc_cmake + +url = https://github.com/google/shaderc +revision = v2024.4 +depth=1 +patch_directory = shaderc_cmake + +[provide] +dependency_names = shaderc_cmake diff --git a/subprojects/shaderc.wrap b/subprojects/shaderc_old.wrap similarity index 79% rename from subprojects/shaderc.wrap rename to subprojects/shaderc_old.wrap index e17f54b..a33fb3f 100644 --- a/subprojects/shaderc.wrap +++ b/subprojects/shaderc_old.wrap @@ -1,12 +1,12 @@ [wrap-file] -directory = libshaderc +directory = libshaderc_old source_url = https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/windows/continuous_release_2019/64/20241106-090939/install.zip source_filename = libshaderc-upstream-msvc.zip source_hash = a6879869e580d5991ebd9909f3665d1f6fe39cdb9830adf4f48b35dfd3782a78 lead_directory_missing = libshaderc -patch_directory = libshaderc +patch_directory = libshaderc_old [provide] -dependency_names = shaderc +dependency_names = shaderc_old