still flickering? :(

This commit is contained in:
Vicente Ferrari Smith 2026-02-18 08:15:17 +01:00
parent 19f2acc2ec
commit 268d417373
13 changed files with 412 additions and 369 deletions

82
.idea/editor.xml generated
View File

@ -246,100 +246,22 @@
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/EXPORT_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/REQUIRES_EXPRESSION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
</component>
</project>

View File

@ -35,8 +35,6 @@ target_include_directories(stb INTERFACE ${stb_SOURCE_DIR})
add_executable(v main.cpp
renderer/init.cpp
renderer/init.h
renderer/swapchain.cpp
renderer/swapchain.h
renderer/renderer.cpp
renderer/renderer.h
misc.cpp

View File

@ -10,7 +10,6 @@
#include <GLFW/glfw3.h>
#include "renderer/init.h"
#include "renderer/swapchain.h"
#include "renderer/renderer.h"
#include "renderer/texture.h"

View File

@ -176,15 +176,15 @@ void createDevice() {
}
}
if (int r = glfwGetPhysicalDevicePresentationSupport(instance, physicalDevice, queueFamily) == GLFW_FALSE) {
return;
}
std::println("{}", queueFamily);
std::vector<const char*> devExts = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME,
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME,
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME,
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME,
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
};
uint32_t extensionCount = 0;
@ -208,41 +208,74 @@ void createDevice() {
.pQueuePriorities = &prio
};
VkPhysicalDeviceDescriptorIndexingFeatures indexingFeatures{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
VkPhysicalDeviceVulkan14Features enabledVk14Features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES,
.pNext = nullptr,
.globalPriorityQuery = false,
.shaderSubgroupRotate = false,
.shaderSubgroupRotateClustered = false,
.shaderFloatControls2 = false,
.shaderExpectAssume = false,
.rectangularLines = false,
.bresenhamLines = false,
.smoothLines = false,
.stippledRectangularLines = false,
.stippledBresenhamLines = false,
.stippledSmoothLines = false,
.vertexAttributeInstanceRateDivisor = false,
.vertexAttributeInstanceRateZeroDivisor = false,
.indexTypeUint8 = false,
.dynamicRenderingLocalRead = false,
.maintenance5 = false,
.maintenance6 = false,
.pipelineProtectedAccess = false,
.pipelineRobustness = false,
.hostImageCopy = false,
.pushDescriptor = false,
};
VkPhysicalDeviceVulkan13Features enabledVk13Features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
.pNext = nullptr,
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE,
.descriptorBindingPartiallyBound = VK_TRUE,
.runtimeDescriptorArray = VK_TRUE
.robustImageAccess = false,
.inlineUniformBlock = false,
.descriptorBindingInlineUniformBlockUpdateAfterBind = false,
.pipelineCreationCacheControl = false,
.privateData = false,
.shaderDemoteToHelperInvocation = false,
.shaderTerminateInvocation = false,
.subgroupSizeControl = false,
.computeFullSubgroups = false,
.synchronization2 = true,
.textureCompressionASTC_HDR = false,
.shaderZeroInitializeWorkgroupMemory = false,
.dynamicRendering = true,
.shaderIntegerDotProduct = false,
.maintenance4 = false
};
VkPhysicalDeviceTimelineSemaphoreFeatures timeline{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
.pNext = &indexingFeatures,
.timelineSemaphore = VK_TRUE
VkPhysicalDeviceVulkan12Features enabledVk12Features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.pNext = &enabledVk13Features,
.descriptorIndexing = true,
.shaderSampledImageArrayNonUniformIndexing = true,
.descriptorBindingSampledImageUpdateAfterBind = true,
.descriptorBindingPartiallyBound = true,
.descriptorBindingVariableDescriptorCount = true,
.runtimeDescriptorArray = true,
.bufferDeviceAddress = true,
};
VkPhysicalDeviceSynchronization2Features sync2{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES,
.pNext = &timeline,
.synchronization2 = VK_TRUE
const VkPhysicalDeviceFeatures enabledVk10Features{
.samplerAnisotropy = true,
};
VkPhysicalDeviceDynamicRenderingFeatures dyn{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,
.pNext = &sync2,
.dynamicRendering = VK_TRUE
};
const VkDeviceCreateInfo dci{
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &dyn,
.pNext = &enabledVk12Features,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &qci,
.enabledExtensionCount = (uint32_t)devExts.size(),
.ppEnabledExtensionNames = devExts.data(),
.pEnabledFeatures = &enabledVk10Features,
};
vkCreateDevice(physicalDevice, &dci, nullptr, &device);
@ -272,3 +305,83 @@ void createDevice() {
res = vmaCreateAllocator(&allocatorCreateInfo, &allocator);
}
void createSwapchain(GLFWwindow* window) {
int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
swapchain_extent = {
static_cast<uint32_t>(fbWidth),
static_cast<uint32_t>(fbHeight)
};
VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
.pNext = nullptr,
.surface = surface,
};
VkSurfaceCapabilities2KHR surfCapabilities{
.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
};
vkGetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, &surfaceInfo, &surfCapabilities);
const VkSwapchainCreateInfoKHR sci{
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.surface = surface,
.minImageCount = surfCapabilities.surfaceCapabilities.minImageCount,
.imageFormat = swapchain_format.format,
.imageColorSpace = swapchain_format.colorSpace,
.imageExtent = swapchain_extent,
.imageArrayLayers = 1,
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = VK_PRESENT_MODE_FIFO_KHR,
.clipped = VK_TRUE
};
vkCreateSwapchainKHR(device, &sci, nullptr, &swapchain);
uint32_t imgCount;
vkGetSwapchainImagesKHR(device, swapchain, &imgCount, nullptr);
std::print("imgCount: {}", imgCount);
images = std::vector<VkImage>(imgCount);
vkGetSwapchainImagesKHR(device, swapchain, &imgCount, images.data());
imageLayouts = std::vector<VkImageLayout>(
imgCount,
VK_IMAGE_LAYOUT_UNDEFINED
);
imageViews = std::vector<VkImageView>(imgCount);
const VkSemaphoreCreateInfo seci{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
};
renderFinished.resize(imgCount);
for (uint32_t i = 0; i < imgCount; i++) {
VkImageViewCreateInfo ivci{};
ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
ivci.image = images[i];
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
ivci.format = swapchain_format.format; // must match swapchain format
ivci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ivci.subresourceRange.baseMipLevel = 0;
ivci.subresourceRange.levelCount = 1;
ivci.subresourceRange.baseArrayLayer = 0;
ivci.subresourceRange.layerCount = 1;
vkCreateImageView(device, &ivci, nullptr, &imageViews[i]);
vkCreateSemaphore(device, &seci, nullptr, &renderFinished[i]);
}
}

View File

@ -8,6 +8,7 @@
#include <volk/volk.h>
#include <GLFW/glfw3.h>
#include <vma/vk_mem_alloc.h>
#include <vector>
inline VkInstance instance{};
inline VkPhysicalDevice physicalDevice{};
@ -20,9 +21,23 @@ inline VkDebugUtilsMessengerEXT debugMessenger{};
inline VmaAllocator allocator{};
inline uint32_t MAX_FRAMES_IN_FLIGHT = 2;
inline constexpr uint32_t MAX_FRAMES_IN_FLIGHT = 2;
inline constexpr uint32_t MAX_VERTICES_PER_BATCH = 65536;
inline VkSwapchainKHR swapchain;
inline VkExtent2D swapchain_extent;
inline VkSurfaceFormatKHR swapchain_format{
VK_FORMAT_B8G8R8A8_UNORM,
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
};
inline std::vector<VkSemaphore> renderFinished;
inline std::vector<VkImage> images;
inline std::vector<VkImageView> imageViews;
inline std::vector<VkImageLayout> imageLayouts;
void createSwapchain(GLFWwindow* window);
int createInstance(GLFWwindow* window);
void createSurface(GLFWwindow* window);
void pickPhysicalDevice();

View File

@ -5,7 +5,7 @@
#include "renderer.h"
#include "init.h"
#include "sprite.h"
#include "swapchain.h"
#include <vma/vk_mem_alloc.h>
bool SortKey::operator<(const SortKey& b) const {
if (depth != b.depth) return depth < b.depth;
@ -174,6 +174,7 @@ void Renderer::createFrameResources() {
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
Frame &frame = frames[i];
vkCreateSemaphore(device, &seci, nullptr, &frame.imageAvailable);
vkCreateFence(device, &fenceInfo, nullptr, &frame.in_flight_fence);
@ -189,42 +190,101 @@ void Renderer::createFrameResources() {
};
vkAllocateCommandBuffers(device, &cbai, &frame.command_buffer);
VkBufferCreateInfo bufferInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = 1024 * 1024 * 4,
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
};
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT;
vmaCreateBuffer(
allocator,
&bufferInfo,
&allocCreateInfo,
&frame.vertexBuffer.buffer,
&frame.vertexBuffer.allocation,
&frame.vertexBuffer.info);
}
VkBufferCreateInfo bufferInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = 1024 * 1024 * 4,
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
};
VmaAllocationCreateInfo allocInfo = {
.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT,
.usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
};
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &vertexBuffer, &vertexAllocation, &vertexAllocInfo);
VkDescriptorBufferInfo vertexBufferInfo{
.buffer = vertexBuffer,
.offset = 0,
.range = VK_WHOLE_SIZE
};
VkWriteDescriptorSet bufferWrite{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = set,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &vertexBufferInfo
};
vkUpdateDescriptorSets(device, 1, &bufferWrite, 0, nullptr);
}
AllocatedBuffer Renderer::create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage) {
// allocate buffer
VkBufferCreateInfo bufferInfo = {.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
bufferInfo.pNext = nullptr;
bufferInfo.size = allocSize;
bufferInfo.usage = usage;
VmaAllocationCreateInfo vmaallocInfo = {};
vmaallocInfo.usage = memoryUsage;
vmaallocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
AllocatedBuffer newBuffer{};
// allocate the buffer
vmaCreateBuffer(allocator, &bufferInfo, &vmaallocInfo, &newBuffer.buffer, &newBuffer.allocation, &newBuffer.info);
return newBuffer;
}
void Renderer::destroy_buffer(const AllocatedBuffer& buffer) {
vmaDestroyBuffer(allocator, buffer.buffer, buffer.allocation);
}
// GPUMeshBuffers Renderer::uploadMesh(std::span<uint32_t> indices, std::span<vertex_p2_st2_col4_a1_u32> vertices) {
// const size_t vertexBufferSize = vertices.size() * sizeof(vertex_p2_st2_col4_a1_u32);
// const size_t indexBufferSize = indices.size() * sizeof(uint32_t);
//
// GPUMeshBuffers newSurface;
//
// //create vertex buffer
// newSurface.vertexBuffer = create_buffer(vertexBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
// VMA_MEMORY_USAGE_GPU_ONLY);
//
// //find the adress of the vertex buffer
// VkBufferDeviceAddressInfo deviceAdressInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,.buffer = newSurface.vertexBuffer.buffer };
// newSurface.vertexBufferAddress = vkGetBufferDeviceAddress(device, &deviceAdressInfo);
//
// //create index buffer
// newSurface.indexBuffer = create_buffer(indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
// VMA_MEMORY_USAGE_GPU_ONLY);
//
// AllocatedBuffer staging = create_buffer(vertexBufferSize + indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
//
// void* data = staging.allocation->GetMappedData();
//
// // copy vertex buffer
// memcpy(data, vertices.data(), vertexBufferSize);
// // copy index buffer
// memcpy((char*)data + vertexBufferSize, indices.data(), indexBufferSize);
//
// immediate_submit([&](VkCommandBuffer cmd) {
// VkBufferCopy vertexCopy{ 0 };
// vertexCopy.dstOffset = 0;
// vertexCopy.srcOffset = 0;
// vertexCopy.size = vertexBufferSize;
//
// vkCmdCopyBuffer(cmd, staging.buffer, newSurface.vertexBuffer.buffer, 1, &vertexCopy);
//
// VkBufferCopy indexCopy{ 0 };
// indexCopy.dstOffset = 0;
// indexCopy.srcOffset = vertexBufferSize;
// indexCopy.size = indexBufferSize;
//
// vkCmdCopyBuffer(cmd, staging.buffer, newSurface.indexBuffer.buffer, 1, &indexCopy);
// });
//
// destroy_buffer(staging);
//
// return newSurface;
//
// }
void Renderer::end_frame() {
Frame &frame = frames[currentFrame];
@ -232,40 +292,24 @@ void Renderer::end_frame() {
vkWaitForFences(device, 1, &frame.in_flight_fence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &frame.in_flight_fence);
uint32_t imageIndex;
vkAcquireNextImageKHR(
device,
swapchain,
UINT64_MAX,
frame.imageAvailable,
VK_NULL_HANDLE,
&imageIndex
);
commands = counting_sort_descending(commands, [](const RenderCommand &cmd){
return cmd.key.depth;
});
VkMemoryPropertyFlags memPropFlags;
vmaGetAllocationMemoryProperties(allocator, vertexAllocation, &memPropFlags);
std::vector<vertex_p2_st2_col4_a1_u32> vertices;
if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
// The Allocation ended up in a mappable memory.
// Calling vmaCopyMemoryToAllocation() does vmaMapMemory(), memcpy(), vmaUnmapMemory(), and vmaFlushAllocation().
VkResult result = vmaCopyMemoryToAllocation(allocator, myData, alloc, 0, myDataSize);
// Check result...
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.buffer = buf;
bufMemBarrier.offset = 0;
bufMemBarrier.size = VK_WHOLE_SIZE;
// It's important to insert a buffer memory barrier here to ensure writing to the buffer has finished.
vkCmdPipelineBarrier(c, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
}
vertex_p2_st2_col4_a1_u32 *vPtr = (vertex_p2_st2_col4_a1_u32 *) vertexAllocInfo.pMappedData;
vertex_p2_st2_col4_a1_u32 *currentFrameStart = vPtr + (currentFrame * MAX_VERTICES_PER_BATCH);
uint32_t totalVertices = 0;
for (auto& cmd : commands) {
vPtr = currentFrameStart + totalVertices;
switch (cmd.pipeline) {
case PipelineType::ColoredQuad: {
@ -295,34 +339,22 @@ void Renderer::end_frame() {
// vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {u1, v1}, q.color, 1, q.textureID };
// --- Triangle 1 (TL, TR, BL) ---
vPtr[0] = vTL;
vPtr[1] = vTR;
vPtr[2] = vBL;
vertices.push_back(vTL);
vertices.push_back(vTR);
vertices.push_back(vBL);
// --- Triangle 2 (TR, BR, BL) ---
vPtr[3] = vTR;
vPtr[4] = vBR;
vPtr[5] = vBL;
vertices.push_back(vTR);
vertices.push_back(vBR);
vertices.push_back(vBL);
break;
}
default:
break;
}
totalVertices += 6;
}
uint32_t imageIndex;
vkAcquireNextImageKHR(
device,
swapchain,
UINT64_MAX,
frame.imageAvailable,
VK_NULL_HANDLE,
&imageIndex
);
VkCommandBuffer command_buffer = frame.command_buffer;
vkResetCommandBuffer(command_buffer, 0);
@ -331,7 +363,9 @@ void Renderer::end_frame() {
images[imageIndex],
imageViews[imageIndex],
swapchain_extent,
imageLayouts[imageIndex]
imageLayouts[imageIndex],
frame,
vertices
);
imageLayouts[imageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
@ -379,15 +413,46 @@ void Renderer::end_frame() {
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
void Renderer::upload_vertex_buffer(
VkCommandBuffer cmd,
const Frame &frame,
std::span<const vertex_p2_st2_col4_a1_u32> vertices) const {
VkMemoryPropertyFlags memPropFlags;
vmaGetAllocationMemoryProperties(allocator, frame.vertexBuffer.allocation, &memPropFlags);
if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
// The Allocation ended up in a mappable memory.
// Calling vmaCopyMemoryToAllocation() does vmaMapMemory(), memcpy(), vmaUnmapMemory(), and vmaFlushAllocation().
VkResult result = vmaCopyMemoryToAllocation(allocator, vertices.data(), frame.vertexBuffer.allocation, 0, vertices.size() * sizeof(vertex_p2_st2_col4_a1_u32));
// Check result...
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.buffer = frame.vertexBuffer.buffer;
bufMemBarrier.offset = 0;
bufMemBarrier.size = VK_WHOLE_SIZE;
// It's important to insert a buffer memory barrier here to ensure writing to the buffer has finished.
vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
}
}
void Renderer::recordCommandBuffer(
VkCommandBuffer command_buffer,
VkCommandBuffer cmd,
VkImage image,
VkImageView imageView,
VkExtent2D extent,
VkImageLayout oldLayout) const
VkImageLayout oldLayout,
const Frame &frame,
const std::vector<vertex_p2_st2_col4_a1_u32> &vertices) const
{
VkCommandBufferBeginInfo begin{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
vkBeginCommandBuffer(command_buffer, &begin);
vkBeginCommandBuffer(cmd, &begin);
{
VkImageMemoryBarrier2 toColor{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
@ -404,7 +469,7 @@ void Renderer::recordCommandBuffer(
.imageMemoryBarrierCount = 1,
.pImageMemoryBarriers = &toColor
};
vkCmdPipelineBarrier2(command_buffer, &dep);
vkCmdPipelineBarrier2(cmd, &dep);
}
VkClearValue clearColor = {{{0.1f, 0.1f, 0.2f, 1.0f}}};
@ -425,31 +490,35 @@ void Renderer::recordCommandBuffer(
.pColorAttachments = &colorAttach
};
vkCmdBeginRendering(command_buffer, &ri);
upload_vertex_buffer(cmd, frame, vertices);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, 0, nullptr);
vkCmdBeginRendering(cmd, &ri);
VkViewport vp{0.0f, 0.0f, (float)extent.width, (float)extent.height, 0.0f, 1.0f};
VkRect2D sc{{0, 0}, extent};
vkCmdSetViewport(command_buffer, 0, 1, &vp);
vkCmdSetScissor(command_buffer, 0, 1, &sc);
vkCmdSetViewport(cmd, 0, 1, &vp);
vkCmdSetScissor(cmd, 0, 1, &sc);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, 0, nullptr);
VkDeviceSize vOffset{ 0 };
vkCmdBindVertexBuffers(cmd, 0, 1, &frame.vertexBuffer.buffer, &vOffset);
PipelineType lastPipeline = PipelineType::None; // Track current state
uint32_t vertexOffset = currentFrame * MAX_VERTICES_PER_BATCH;
uint32_t currentBatchVertices = 0;
for (const auto & cmd : commands) {
for (const auto & render_command : commands) {
// Only switch pipelines if we have to
if (cmd.pipeline != lastPipeline) {
if (render_command.pipeline != lastPipeline) {
// If we were mid-batch, draw what we have before switching
if (currentBatchVertices > 0) {
vkCmdDraw(command_buffer, currentBatchVertices, 1, vertexOffset, 0);
vkCmdDraw(cmd, currentBatchVertices, 1, vertexOffset, 0);
vertexOffset += currentBatchVertices;
currentBatchVertices = 0;
}
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, get_pipeline(cmd.pipeline));
lastPipeline = cmd.pipeline;
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, get_pipeline(render_command.pipeline));
lastPipeline = render_command.pipeline;
}
currentBatchVertices += 6;
@ -457,10 +526,10 @@ void Renderer::recordCommandBuffer(
// Draw the final batch
if (currentBatchVertices > 0) {
vkCmdDraw(command_buffer, currentBatchVertices, 1, vertexOffset, 0);
vkCmdDraw(cmd, currentBatchVertices, 1, vertexOffset, 0);
}
vkCmdEndRendering(command_buffer);
vkCmdEndRendering(cmd);
// 3. Transition back to Present
{
@ -474,10 +543,10 @@ void Renderer::recordCommandBuffer(
toPresent.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
VkDependencyInfo dep{ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .imageMemoryBarrierCount = 1, .pImageMemoryBarriers = &toPresent };
vkCmdPipelineBarrier2(command_buffer, &dep);
vkCmdPipelineBarrier2(cmd, &dep);
}
vkEndCommandBuffer(command_buffer);
vkEndCommandBuffer(cmd);
}
VkPipeline Renderer::get_pipeline(PipelineType type) const {

View File

@ -13,6 +13,8 @@
#include "sprite.h"
#include "texture.h"
#include <misc.h>
#include <array>
#include <span>
enum class PROJECTION_TYPE : uint8_t {
NONE,
@ -34,13 +36,15 @@ struct vertex_p2_st2_col4_a1_u32 {
return {0, sizeof(vertex_p2_st2_col4_a1_u32), VK_VERTEX_INPUT_RATE_VERTEX};
}
static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions() {
static std::array<VkVertexInputAttributeDescription, 5> getAttributeDescriptions() {
return {
{0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, pos)},
{1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, st)},
{2, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, col)},
{3, 0, VK_FORMAT_R32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, alpha)},
{4, 0, VK_FORMAT_R32_UINT, offsetof(vertex_p2_st2_col4_a1_u32, textureID)},
{
{0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, pos)},
{1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, st)},
{2, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, col)},
{3, 0, VK_FORMAT_R32_SFLOAT, offsetof(vertex_p2_st2_col4_a1_u32, alpha)},
{4, 0, VK_FORMAT_R32_UINT, offsetof(vertex_p2_st2_col4_a1_u32, textureID)},
}
};
}
};
@ -114,30 +118,21 @@ struct RenderCommand {
////////////////////////////////////////////////////////////////////////////////////////////////
struct AllocatedBuffer {
VkBuffer buffer;
VmaAllocation allocation;
VmaAllocationInfo info;
};
struct GPUMeshBuffers {
AllocatedBuffer indexBuffer;
AllocatedBuffer vertexBuffer;
VkDeviceAddress vertexBufferAddress;
};
struct Renderer {
std::vector<RenderCommand> commands{};
void begin_frame();
void end_frame();
void flush();
void submit_sprite(glm::vec2 pos, const sprite_t &sprite);
void submit_quad();
explicit Renderer(GLFWwindow *window);
void create_pipeline_layout();
void createFrameResources();
void create_default_sampler();
void recordCommandBuffer(
VkCommandBuffer cmd,
VkImage image,
VkImageView imageView,
VkExtent2D extent,
VkImageLayout oldLayout) const;
void immediate_submit(std::function<void(VkCommandBuffer)>&& func) const;
void transition_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) const;
VkImageView create_image_view(VkImage image, VkFormat format) const;
VkDescriptorSetLayout descriptor_set_layout{};
VkPipelineLayout pipelineLayout{};
VkPipeline textured_quad_pipeline{};
@ -157,18 +152,46 @@ struct Renderer {
VkSemaphore imageAvailable{};
VkFence in_flight_fence{};
AllocatedBuffer vertexBuffer{};
};
std::vector<Frame> frames;
uint32_t currentFrame = 0;
VkBuffer vertexBuffer{};
VmaAllocation vertexAllocation{};
VmaAllocationInfo vertexAllocInfo{};
VkDescriptorPool descriptorPool{};
std::vector<VkDescriptorSet> textureSets{};
void begin_frame();
void end_frame();
void flush();
void submit_sprite(glm::vec2 pos, const sprite_t &sprite);
void submit_quad();
explicit Renderer(GLFWwindow *window);
void create_pipeline_layout();
void createFrameResources();
void create_default_sampler();
void recordCommandBuffer(
VkCommandBuffer cmd,
VkImage image,
VkImageView imageView,
VkExtent2D extent,
VkImageLayout oldLayout,
const Frame &frame,
const std::vector<vertex_p2_st2_col4_a1_u32> &vertices) const;
void immediate_submit(std::function<void(VkCommandBuffer)>&& func) const;
void transition_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) const;
VkImageView create_image_view(VkImage image, VkFormat format) const;
AllocatedBuffer create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage);
void destroy_buffer(const AllocatedBuffer& buffer);
// GPUMeshBuffers uploadMesh(std::span<uint32_t> indices, std::span<vertex_p2_st2_col4_a1_u32> vertices);
void upload_vertex_buffer(
VkCommandBuffer cmd,
const Frame &frame,
std::span<const vertex_p2_st2_col4_a1_u32> vertices) const;
VkPipeline get_pipeline(PipelineType type) const;
// void bind_material(VkCommandBuffer cmd, uint16_t materialID);
void create_descriptor_pool();
@ -232,10 +255,10 @@ struct Renderer {
// --- Vertex Input (Matching our vertex_p2_st2_col4 struct) ---
VkPipelineVertexInputStateCreateInfo vi{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = 0,
.pVertexBindingDescriptions = nullptr,
.vertexAttributeDescriptionCount = 0,
.pVertexAttributeDescriptions = nullptr,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &binding,
.vertexAttributeDescriptionCount = attrs.size(),
.pVertexAttributeDescriptions = attrs.data(),
};
// --- Input Assembly (Changes based on Topology parameter) ---

View File

@ -1,88 +0,0 @@
//
// Created by Vicente Ferrari Smith on 13.02.26.
//
#include "swapchain.h"
#include <print>
void createSwapchain(GLFWwindow* window) {
int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
swapchain_extent = {
static_cast<uint32_t>(fbWidth),
static_cast<uint32_t>(fbHeight)
};
VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
.pNext = nullptr,
.surface = surface,
};
VkSurfaceCapabilities2KHR surfCapabilities{
.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
};
vkGetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, &surfaceInfo, &surfCapabilities);
MAX_FRAMES_IN_FLIGHT = std::min(surfCapabilities.surfaceCapabilities.minImageCount + 1, surfCapabilities.surfaceCapabilities.maxImageCount);
const VkSwapchainCreateInfoKHR sci{
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.surface = surface,
.minImageCount = MAX_FRAMES_IN_FLIGHT,
.imageFormat = swapchain_format.format,
.imageColorSpace = swapchain_format.colorSpace,
.imageExtent = swapchain_extent,
.imageArrayLayers = 1,
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = VK_PRESENT_MODE_FIFO_KHR,
.clipped = VK_TRUE
};
vkCreateSwapchainKHR(device, &sci, nullptr, &swapchain);
uint32_t imgCount;
vkGetSwapchainImagesKHR(device, swapchain, &imgCount, nullptr);
std::print("imgCount: {}", imgCount);
images = std::vector<VkImage>(imgCount);
vkGetSwapchainImagesKHR(device, swapchain, &imgCount, images.data());
imageLayouts = std::vector<VkImageLayout>(
imgCount,
VK_IMAGE_LAYOUT_UNDEFINED
);
imageViews = std::vector<VkImageView>(imgCount);
const VkSemaphoreCreateInfo seci{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
};
renderFinished.resize(imgCount);
for (uint32_t i = 0; i < imgCount; i++) {
VkImageViewCreateInfo ivci{};
ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
ivci.image = images[i];
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
ivci.format = swapchain_format.format; // must match swapchain format
ivci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ivci.subresourceRange.baseMipLevel = 0;
ivci.subresourceRange.levelCount = 1;
ivci.subresourceRange.baseArrayLayer = 0;
ivci.subresourceRange.layerCount = 1;
vkCreateImageView(device, &ivci, nullptr, &imageViews[i]);
vkCreateSemaphore(device, &seci, nullptr, &renderFinished[i]);
}
}

View File

@ -1,25 +0,0 @@
//
// Created by Vicente Ferrari Smith on 13.02.26.
//
#ifndef V_SWAPCHAIN_H
#define V_SWAPCHAIN_H
#include "init.h"
#include <vector>
inline VkSwapchainKHR swapchain;
inline VkExtent2D swapchain_extent;
inline VkSurfaceFormatKHR swapchain_format{
VK_FORMAT_B8G8R8A8_UNORM,
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
};
inline std::vector<VkSemaphore> renderFinished;
inline std::vector<VkImage> images;
inline std::vector<VkImageView> imageViews;
inline std::vector<VkImageLayout> imageLayouts;
void createSwapchain(GLFWwindow* window);
#endif //V_SWAPCHAIN_H

View File

@ -5,7 +5,8 @@ layout(set = 0, binding = 0) uniform sampler2D texSamplers[];
layout(location = 0) in vec2 uv;
layout(location = 1) in vec4 color;
layout(location = 2) in flat uint tex_id;
layout(location = 2) in float alpha;
layout(location = 3) in flat uint tex_id;
layout(location = 0) out vec4 out_color;

Binary file not shown.

View File

@ -1,5 +1,5 @@
#version 460
#extension GL_EXT_nonuniform_qualifier : require
#extension GL_EXT_buffer_reference : require
struct Vertex {
vec2 pos;
@ -9,20 +9,36 @@ struct Vertex {
uint textureID;
};
layout(std430, set = 0, binding = 1) readonly buffer VertexBuffer {
Vertex vertices[];
} vBuf;
layout(location = 0) in vec2 inPos; // Matches VK_FORMAT_R32G32_SFLOAT
layout(location = 1) in vec2 inTexCoord; // Matches VK_FORMAT_R32G32_SFLOAT
layout(location = 2) in vec4 inColor; // Matches VK_FORMAT_R32G32B32A32_SFLOAT
layout(location = 3) in float inAlpha; // Matches VK_FORMAT_R32_SFLOAT
layout(location = 4) in uint inTextureID; // Matches VK_FORMAT_R32_UINT
//layout(std430, set = 0, binding = 1) readonly buffer VertexBuffer {
// Vertex vertices[];
//} vBuf;
//layout(buffer_reference, std430) readonly buffer VertexBuffer{
// Vertex vertices[];
//};
//push constants block
//layout(push_constant) uniform constants {
// mat4 render_matrix;
// VertexBuffer vertexBuffer;
//} PushConstants;
layout(location = 0) out vec2 uv;
layout(location = 1) out vec4 color;
layout(location = 2) out flat uint tex_id;
layout(location = 2) out float alpha;
layout(location = 3) out flat uint tex_id;
void main() {
Vertex v = vBuf.vertices[gl_VertexIndex];
uv = v.uv;
color = v.color;
tex_id = v.textureID;
gl_Position = vec4(v.pos, 0.0, 1.0);
uv = inTexCoord;
color = inColor;
alpha = inAlpha;
tex_id = inTextureID;
gl_Position = vec4(inPos, 0.0, 1.0);
}

Binary file not shown.