diff --git a/.idea/editor.xml b/.idea/editor.xml
index 33921db..8d0e15e 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -246,22 +246,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 440e867..c5c142a 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,7 +2,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9e52fa6..f5df2d3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,8 @@ set(CMAKE_CXX_STANDARD 23)
include(FetchContent)
-find_package(Vulkan REQUIRED)
+variable_watch($ENV{VULKAN_SDK})
+find_package(Vulkan REQUIRED COMPONENTS volk)
FetchContent_Declare(
glfw
diff --git a/main.cpp b/main.cpp
index 7aefef7..6aa8352 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4,7 +4,7 @@
#include
#define VOLK_IMPLEMENTATION
-#include
+#include
#define VMA_IMPLEMENTATION
#include
#include
diff --git a/renderer/init.cpp b/renderer/init.cpp
index ec392fd..7f52672 100644
--- a/renderer/init.cpp
+++ b/renderer/init.cpp
@@ -56,17 +56,27 @@ int createInstance(GLFWwindow *window) {
uint32_t extensions_count;
const char** extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
std::vector instance_exts;
- instance_exts.reserve(extensions_count + 1);
- // Copy GLFW-required extensions
+
for (uint32_t i = 0; i < extensions_count; i++) {
instance_exts.push_back(extensions[i]);
}
// Append portability enumeration (MANDATORY on macOS)
- instance_exts.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
instance_exts.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ instance_exts.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
- for (auto& ext : instance_exts) {
- std::print("extension {}\n", ext);
+ uint32_t availableCount = 0;
+ vkEnumerateInstanceExtensionProperties(nullptr, &availableCount, nullptr);
+
+ std::vector available(availableCount);
+ vkEnumerateInstanceExtensionProperties(nullptr, &availableCount, available.data());
+
+ bool has_portability_extension = false;
+
+ for (const VkExtensionProperties &property : available) {
+ if (strcmp(property.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) {
+ has_portability_extension = true;
+ instance_exts.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
+ }
}
constexpr VkApplicationInfo app{
@@ -90,10 +100,9 @@ int createInstance(GLFWwindow *window) {
dbg.pfnUserCallback = debugCallback;
- const VkInstanceCreateInfo ici{
+ VkInstanceCreateInfo ici{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = &dbg,
- .flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR,
.pApplicationInfo = &app,
.enabledLayerCount = 1,
.ppEnabledLayerNames = layers,
@@ -101,6 +110,10 @@ int createInstance(GLFWwindow *window) {
.ppEnabledExtensionNames = instance_exts.data(),
};
+ if (has_portability_extension) {
+ ici.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+ }
+
VkResult res = vkCreateInstance(&ici, nullptr, &instance);
if (res != VK_SUCCESS) {
printf("vkCreateInstance failed: %d\n", res);
@@ -165,16 +178,28 @@ void createDevice() {
std::println("{}", queueFamily);
- const char* devExts[] = {
+ std::vector 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,
- "VK_KHR_portability_subset"
};
+ uint32_t extensionCount = 0;
+ vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);
+
+ std::vector availableExtensions(extensionCount);
+ vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data());
+
+ for (const auto& ext : availableExtensions) {
+ if (strcmp(ext.extensionName, "VK_KHR_portability_subset") == 0) {
+ devExts.push_back("VK_KHR_portability_subset");
+ break;
+ }
+ }
+
float prio = 1.0f;
VkDeviceQueueCreateInfo qci{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
@@ -216,8 +241,8 @@ void createDevice() {
.pNext = &dyn,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &qci,
- .enabledExtensionCount = 7,
- .ppEnabledExtensionNames = devExts
+ .enabledExtensionCount = (uint32_t)devExts.size(),
+ .ppEnabledExtensionNames = devExts.data(),
};
vkCreateDevice(physicalDevice, &dci, nullptr, &device);
diff --git a/renderer/init.h b/renderer/init.h
index 2ffc028..592a71c 100644
--- a/renderer/init.h
+++ b/renderer/init.h
@@ -9,16 +9,19 @@
#include
#include
-inline VkInstance instance;
-inline VkPhysicalDevice physicalDevice;
-inline VkDevice device;
-inline VkQueue graphics_queue;
-inline uint32_t queueFamily;
+inline VkInstance instance{};
+inline VkPhysicalDevice physicalDevice{};
+inline VkDevice device{};
+inline VkQueue graphics_queue{};
+inline uint32_t queueFamily{};
-inline VkSurfaceKHR surface;
-inline VkDebugUtilsMessengerEXT debugMessenger;
+inline VkSurfaceKHR surface{};
+inline VkDebugUtilsMessengerEXT debugMessenger{};
-inline VmaAllocator allocator;
+inline VmaAllocator allocator{};
+
+inline uint32_t MAX_FRAMES_IN_FLIGHT = 2;
+inline constexpr uint32_t MAX_VERTICES_PER_BATCH = 65536;
int createInstance(GLFWwindow* window);
void createSurface(GLFWwindow* window);
diff --git a/renderer/renderer.cpp b/renderer/renderer.cpp
index c6df79e..d30deb6 100644
--- a/renderer/renderer.cpp
+++ b/renderer/renderer.cpp
@@ -15,14 +15,6 @@ bool SortKey::operator<(const SortKey& b) const {
Renderer::Renderer(GLFWwindow *window) {
- VkCommandPoolCreateInfo cpci{
- .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
- .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
- .queueFamilyIndex = queueFamily
- };
-
- vkCreateCommandPool(device, &cpci, nullptr, &commandPool);
-
create_pipeline_layout();
colored_quad_pipeline = create_graphics_pipeline(
device,
@@ -37,20 +29,7 @@ Renderer::Renderer(GLFWwindow *window) {
}
void Renderer::begin_frame() {
- uint64_t waitValue = 0;
-
- if (frameValue >= MAX_FRAMES_IN_FLIGHT) {
- waitValue = frameValue - MAX_FRAMES_IN_FLIGHT + 1;
-
- VkSemaphoreWaitInfo waitInfo{
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
- .semaphoreCount = 1,
- .pSemaphores = &timelineSemaphore,
- .pValues = &waitValue
- };
-
- vkWaitSemaphores(device, &waitInfo, UINT64_MAX);
- }
+ commands.clear();
}
void Renderer::flush() {
@@ -122,7 +101,7 @@ void Renderer::create_pipeline_layout() {
bindings[0] = VkDescriptorSetLayoutBinding{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .descriptorCount = 1000,
+ .descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
};
@@ -130,7 +109,7 @@ void Renderer::create_pipeline_layout() {
.binding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
- .stageFlags = VK_SHADER_STAGE_VERTEX_BIT // The vertex shader "pulls" from here
+ .stageFlags = VK_SHADER_STAGE_VERTEX_BIT
};
VkDescriptorBindingFlags flags[2] = {
@@ -146,7 +125,7 @@ void Renderer::create_pipeline_layout() {
VkDescriptorSetLayoutCreateInfo dslci{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .pNext = &layoutFlags, // Attach the flags
+ .pNext = &layoutFlags,
.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
.bindingCount = 2,
.pBindings = bindings
@@ -175,44 +154,55 @@ void Renderer::create_pipeline_layout() {
}
void Renderer::createFrameResources() {
- VkSemaphoreTypeCreateInfo typeInfo{
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
- .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
- .initialValue = 0
- };
- const VkSemaphoreCreateInfo semaphoreci{
+ const VkSemaphoreCreateInfo seci{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
- .pNext = &typeInfo
};
- vkCreateSemaphore(device, &semaphoreci, nullptr, &timelineSemaphore);
+ VkFenceCreateInfo fenceInfo{
+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ .flags = VK_FENCE_CREATE_SIGNALED_BIT,
+ };
- const VkSemaphoreCreateInfo seci{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
+ VkCommandPoolCreateInfo cpci{
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
+ .queueFamilyIndex = queueFamily
+ };
- for (auto & frame : frames) {
+ frames.resize(MAX_FRAMES_IN_FLIGHT);
+
+ for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
+ Frame &frame = frames[i];
vkCreateSemaphore(device, &seci, nullptr, &frame.imageAvailable);
- vkCreateSemaphore(device, &seci, nullptr, &frame.renderFinished);
- }
- const VkCommandBufferAllocateInfo cbai{
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .commandPool = commandPool,
- .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- .commandBufferCount = 1
- };
+ vkCreateFence(device, &fenceInfo, nullptr, &frame.in_flight_fence);
+
+
+ vkCreateCommandPool(device, &cpci, nullptr, &frame.commandPool);
+
+ const VkCommandBufferAllocateInfo cbai{
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .commandPool = frame.commandPool,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandBufferCount = 1
+ };
- for (auto &frame : frames) {
vkAllocateCommandBuffers(device, &cbai, &frame.command_buffer);
}
- VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
- bufferInfo.size = 1024 * 1024 * 4;
- bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
- VmaAllocationCreateInfo allocInfo = {};
- allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
- allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+ 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);
@@ -237,12 +227,40 @@ void Renderer::createFrameResources() {
void Renderer::end_frame() {
+ Frame &frame = frames[currentFrame];
+
+ vkWaitForFences(device, 1, &frame.in_flight_fence, VK_TRUE, UINT64_MAX);
+ vkResetFences(device, 1, &frame.in_flight_fence);
+
commands = counting_sort_descending(commands, [](const RenderCommand &cmd){
return cmd.key.depth;
});
+ VkMemoryPropertyFlags memPropFlags;
+ vmaGetAllocationMemoryProperties(allocator, vertexAllocation, &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, 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_FRAME);
+ vertex_p2_st2_col4_a1_u32 *currentFrameStart = vPtr + (currentFrame * MAX_VERTICES_PER_BATCH);
uint32_t totalVertices = 0;
for (auto& cmd : commands) {
@@ -251,7 +269,7 @@ void Renderer::end_frame() {
switch (cmd.pipeline) {
case PipelineType::ColoredQuad: {
- const auto &q = cmd.textured_quad;
+ const auto &q = cmd.colored_quad;
// Calculate spatial corners
float x0 = q.position.x;
@@ -260,16 +278,21 @@ void Renderer::end_frame() {
float y1 = q.position.y + q.size.y;
// Calculate UV corners
- float u0 = q.uvMin.x;
- float v0 = q.uvMin.y;
- float u1 = q.uvMax.x;
- float v1 = q.uvMax.y;
+ // float u0 = q.uvMin.x;
+ // float v0 = q.uvMin.y;
+ // float u1 = q.uvMax.x;
+ // float v1 = q.uvMax.y;
// Define the 4 corners of the quad
- vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {u0, v0}, q.color, 1, q.textureID };
- vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {u1, v0}, q.color, 1, q.textureID };
- vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {u0, v1}, q.color, 1, q.textureID };
- vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {u1, v1}, q.color, 1, q.textureID };
+ vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {0, 0}, q.color, 1, 0 };
+ vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {0, 0}, q.color, 1, 0 };
+ vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {0, 0}, q.color, 1, 0 };
+ vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {0, 0}, q.color, 1, 0 };
+
+ // vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {u0, v0}, q.color, 1, q.textureID };
+ // vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {u1, v0}, q.color, 1, q.textureID };
+ // vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {u0, v1}, q.color, 1, q.textureID };
+ // vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {u1, v1}, q.color, 1, q.textureID };
// --- Triangle 1 (TL, TR, BL) ---
vPtr[0] = vTL;
@@ -295,12 +318,12 @@ void Renderer::end_frame() {
device,
swapchain,
UINT64_MAX,
- frames[currentFrame].imageAvailable,
+ frame.imageAvailable,
VK_NULL_HANDLE,
&imageIndex
);
- VkCommandBuffer command_buffer = frames[currentFrame].command_buffer;
+ VkCommandBuffer command_buffer = frame.command_buffer;
vkResetCommandBuffer(command_buffer, 0);
recordCommandBuffer(
@@ -311,33 +334,20 @@ void Renderer::end_frame() {
imageLayouts[imageIndex]
);
- commands.clear();
-
imageLayouts[imageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- frameValue++;
-
VkSemaphoreSubmitInfo waitBinary{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = frames[currentFrame].imageAvailable,
+ .semaphore = frame.imageAvailable,
.stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
};
VkSemaphoreSubmitInfo signalBinary{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = frames[currentFrame].renderFinished,
+ .semaphore = renderFinished[imageIndex],
.stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
};
- VkSemaphoreSubmitInfo signalTimeline{
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = timelineSemaphore,
- .value = frameValue,
- .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
- };
-
- VkSemaphoreSubmitInfo signals[] = { signalBinary, signalTimeline };
-
VkCommandBufferSubmitInfo cmdInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.commandBuffer = command_buffer,
@@ -349,16 +359,16 @@ void Renderer::end_frame() {
.pWaitSemaphoreInfos = &waitBinary,
.commandBufferInfoCount = 1,
.pCommandBufferInfos = &cmdInfo,
- .signalSemaphoreInfoCount = 2,
- .pSignalSemaphoreInfos = signals,
+ .signalSemaphoreInfoCount = 1,
+ .pSignalSemaphoreInfos = &signalBinary,
};
- vkQueueSubmit2(graphics_queue, 1, &submit, VK_NULL_HANDLE);
+ vkQueueSubmit2(graphics_queue, 1, &submit, frame.in_flight_fence);
VkPresentInfoKHR present{
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.waitSemaphoreCount = 1,
- .pWaitSemaphores = &frames[currentFrame].renderFinished,
+ .pWaitSemaphores = &renderFinished[imageIndex],
.swapchainCount = 1,
.pSwapchains = &swapchain,
.pImageIndices = &imageIndex,
@@ -425,7 +435,7 @@ void Renderer::recordCommandBuffer(
vkCmdSetScissor(command_buffer, 0, 1, &sc);
PipelineType lastPipeline = PipelineType::None; // Track current state
- uint32_t vertexOffset = currentFrame * MAX_VERTICES_PER_FRAME;
+ uint32_t vertexOffset = currentFrame * MAX_VERTICES_PER_BATCH;
uint32_t currentBatchVertices = 0;
for (const auto & cmd : commands) {
@@ -479,31 +489,31 @@ VkPipeline Renderer::get_pipeline(PipelineType type) const {
}
}
-void Renderer::bind_material(VkCommandBuffer cmd, uint16_t materialID) {
- // In a real app, you'd have an array/map: std::vector textureSets;
- VkDescriptorSet set = textureSets[materialID];
-
- vkCmdBindDescriptorSets(
- cmd,
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- pipelineLayout, // Our shared layout
- 0, // Starting at Set 0
- 1, // Binding 1 set
- &set,
- 0, nullptr
- );
-}
+// void Renderer::bind_material(VkCommandBuffer cmd, uint16_t materialID) {
+// // In a real app, you'd have an array/map: std::vector textureSets;
+// VkDescriptorSet set = textureSets[materialID];
+//
+// vkCmdBindDescriptorSets(
+// cmd,
+// VK_PIPELINE_BIND_POINT_GRAPHICS,
+// pipelineLayout, // Our shared layout
+// 0, // Starting at Set 0
+// 1, // Binding 1 set
+// &set,
+// 0, nullptr
+// );
+// }
void Renderer::create_descriptor_pool() {
VkDescriptorPoolSize pool_sizes[] = {
- { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 10 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 },
};
VkDescriptorPoolCreateInfo pool_info{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
- .maxSets = 1000,
+ .maxSets = 1,
.poolSizeCount = 2,
.pPoolSizes = pool_sizes
};
@@ -517,9 +527,7 @@ void Renderer::create_descriptor_pool() {
.pSetLayouts = &descriptor_set_layout
};
- if (vkAllocateDescriptorSets(device, &alloc_info, &set) != VK_SUCCESS) {
- throw std::runtime_error("Failed to allocate bindless descriptor set!");
- }
+ vkAllocateDescriptorSets(device, &alloc_info, &set);
}
void Renderer::update_bindless_slot(uint32_t slot, VkImageView view, VkSampler sampler) {
@@ -618,7 +626,7 @@ Texture Renderer::upload_texture(int w, int h, void* pixels) {
void Renderer::immediate_submit(std::function&& func) const {
VkCommandBufferAllocateInfo allocInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
- allocInfo.commandPool = commandPool; // Use a pool created with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
+ allocInfo.commandPool = frames[currentFrame].commandPool; // Use a pool created with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
@@ -643,7 +651,7 @@ void Renderer::immediate_submit(std::function&& func) con
vkQueueSubmit(graphics_queue, 1, &submit, VK_NULL_HANDLE);
vkQueueWaitIdle(graphics_queue);
- vkFreeCommandBuffers(device, commandPool, 1, &cmd);
+ vkFreeCommandBuffers(device, frames[currentFrame].commandPool, 1, &cmd);
}
void Renderer::transition_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) const {
@@ -690,9 +698,7 @@ VkImageView Renderer::create_image_view(VkImage image, VkFormat format) const {
viewInfo.subresourceRange.layerCount = 1;
VkImageView view;
- if (vkCreateImageView(device, &viewInfo, nullptr, &view) != VK_SUCCESS) {
- throw std::runtime_error("failed to create image view!");
- }
+ vkCreateImageView(device, &viewInfo, nullptr, &view);
return view;
}
@@ -717,7 +723,5 @@ void Renderer::create_default_sampler() {
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
- if (vkCreateSampler(device, &samplerInfo, nullptr, &defaultSampler) != VK_SUCCESS) {
- throw std::runtime_error("failed to create texture sampler!");
- }
+ vkCreateSampler(device, &samplerInfo, nullptr, &defaultSampler);
}
diff --git a/renderer/renderer.h b/renderer/renderer.h
index 9cd9689..ff7228f 100644
--- a/renderer/renderer.h
+++ b/renderer/renderer.h
@@ -5,6 +5,7 @@
#ifndef V_RENDERER_H
#define V_RENDERER_H
+#include "init.h"
#include
#include
#include
@@ -22,17 +23,6 @@ enum class PROJECTION_TYPE : uint8_t {
COUNT,
};
-struct vertex_p2_col4 {
- glm::vec2 pos;
- glm::vec4 col;
-};
-
-struct vertex_p2_st2_col4 {
- glm::vec2 pos;
- glm::vec2 st;
- glm::vec4 col;
-};
-
struct vertex_p2_st2_col4_a1_u32 {
glm::vec2 pos;
glm::vec2 st;
@@ -55,21 +45,6 @@ struct vertex_p2_st2_col4_a1_u32 {
}
};
-struct vertex_st2 {
- glm::vec2 st;
-};
-
-struct vertex_p2_scale2_rot1_st2 {
- glm::vec2 pos;
- glm::vec2 scale;
- float rot;
- glm::vec2 st;
-};
-
-typedef vertex_st2 quad_st2[6];
-
-typedef vertex_p2_scale2_rot1_st2 quad_pos2_scale2_rot1_st2[6];
-
// commands
enum class PipelineType : uint8_t {
@@ -140,7 +115,7 @@ struct RenderCommand {
////////////////////////////////////////////////////////////////////////////////////////////////
struct Renderer {
- std::vector commands;
+ std::vector commands{};
void begin_frame();
void end_frame();
@@ -163,47 +138,40 @@ struct Renderer {
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;
- VkPipeline colored_quad_pipeline;
- VkPipeline line_pipeline;
- VkPipeline text_pipeline;
- VkPipeline chunk_pipeline;
- VkDescriptorSet set;
+ VkDescriptorSetLayout descriptor_set_layout{};
+ VkPipelineLayout pipelineLayout{};
+ VkPipeline textured_quad_pipeline{};
+ VkPipeline colored_quad_pipeline{};
+ VkPipeline line_pipeline{};
+ VkPipeline text_pipeline{};
+ VkPipeline chunk_pipeline{};
+ VkDescriptorSet set{};
- VkSampler defaultSampler;
+ VkSampler defaultSampler{};
uint32_t nextTextureSlot = 0;
- VkCommandPool commandPool;
-
- static constexpr uint32_t MAX_FRAMES_IN_FLIGHT = 2;
- static constexpr uint32_t MAX_VERTICES_PER_FRAME = 65536;
-
struct Frame {
+ VkCommandPool commandPool{};
VkCommandBuffer command_buffer{};
+
VkSemaphore imageAvailable{};
- VkSemaphore renderFinished{};
+ VkFence in_flight_fence{};
};
- Frame frames[MAX_FRAMES_IN_FLIGHT];
+ std::vector frames;
uint32_t currentFrame = 0;
- VkSemaphore timelineSemaphore{};
- uint64_t frameValue = 0;
+ VkBuffer vertexBuffer{};
+ VmaAllocation vertexAllocation{};
+ VmaAllocationInfo vertexAllocInfo{};
- VkBuffer vertexBuffer;
- VmaAllocation vertexAllocation;
- VmaAllocationInfo vertexAllocInfo;
-
- VkDescriptorPool descriptorPool;
- std::vector textureSets;
+ VkDescriptorPool descriptorPool{};
+ std::vector textureSets{};
VkPipeline get_pipeline(PipelineType type) const;
- void bind_material(VkCommandBuffer cmd, uint16_t materialID);
+ // void bind_material(VkCommandBuffer cmd, uint16_t materialID);
void create_descriptor_pool();
- VkDescriptorSet create_texture_descriptor(VkImageView imageView, VkSampler sampler);
void update_bindless_slot(uint32_t slot, VkImageView view, VkSampler sampler);
// Returns the resource info so the Manager can store it
diff --git a/renderer/swapchain.cpp b/renderer/swapchain.cpp
index fb653cc..1c7b929 100644
--- a/renderer/swapchain.cpp
+++ b/renderer/swapchain.cpp
@@ -3,6 +3,7 @@
//
#include "swapchain.h"
+#include
void createSwapchain(GLFWwindow* window) {
int fbWidth, fbHeight;
@@ -13,10 +14,24 @@ void createSwapchain(GLFWwindow* window) {
static_cast(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 = 2,
+ .minImageCount = MAX_FRAMES_IN_FLIGHT,
.imageFormat = swapchain_format.format,
.imageColorSpace = swapchain_format.colorSpace,
.imageExtent = swapchain_extent,
@@ -33,6 +48,7 @@ void createSwapchain(GLFWwindow* window) {
uint32_t imgCount;
vkGetSwapchainImagesKHR(device, swapchain, &imgCount, nullptr);
+ std::print("imgCount: {}", imgCount);
images = std::vector(imgCount);
vkGetSwapchainImagesKHR(device, swapchain, &imgCount, images.data());
@@ -43,6 +59,12 @@ void createSwapchain(GLFWwindow* window) {
imageViews = std::vector(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;
@@ -60,5 +82,7 @@ void createSwapchain(GLFWwindow* window) {
ivci.subresourceRange.layerCount = 1;
vkCreateImageView(device, &ivci, nullptr, &imageViews[i]);
+
+ vkCreateSemaphore(device, &seci, nullptr, &renderFinished[i]);
}
}
diff --git a/renderer/swapchain.h b/renderer/swapchain.h
index 7ce5cef..224bd14 100644
--- a/renderer/swapchain.h
+++ b/renderer/swapchain.h
@@ -14,6 +14,7 @@ inline VkSurfaceFormatKHR swapchain_format{
VK_FORMAT_B8G8R8A8_UNORM,
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
};
+inline std::vector renderFinished;
inline std::vector images;
inline std::vector imageViews;
diff --git a/renderer/texture_sheet.h b/renderer/texture_sheet.h
index 8decc73..fc0aae4 100644
--- a/renderer/texture_sheet.h
+++ b/renderer/texture_sheet.h
@@ -10,7 +10,7 @@
#include "texture.h"
-constexpr std::string TEXTURE_SHEETS_PATH = "data/texture_sheets";
+inline const std::string TEXTURE_SHEETS_PATH = "data/texture_sheets";
typedef std::string texture_cell_id;
typedef std::string texture_sheet_id;
diff --git a/shaders/triangle.frag b/shaders/triangle.frag
index 85fb0ad..05c2395 100644
--- a/shaders/triangle.frag
+++ b/shaders/triangle.frag
@@ -11,5 +11,5 @@ layout(location = 0) out vec4 out_color;
void main() {
// outColor = texture(texSamplers[nonuniformEXT(tex_id)], uv) * color;
- out_color = color;
+ out_color = vec4(1);
}
diff --git a/shaders/triangle.frag.spv b/shaders/triangle.frag.spv
index 9cefaee..8c5544c 100644
Binary files a/shaders/triangle.frag.spv and b/shaders/triangle.frag.spv differ
diff --git a/shaders/triangle.vert b/shaders/triangle.vert
index 4c24852..062c031 100644
--- a/shaders/triangle.vert
+++ b/shaders/triangle.vert
@@ -9,8 +9,6 @@ struct Vertex {
uint textureID;
};
-layout(set = 0, binding = 0) uniform sampler2D globalTextures[];
-
layout(std430, set = 0, binding = 1) readonly buffer VertexBuffer {
Vertex vertices[];
} vBuf;
@@ -21,16 +19,6 @@ layout(location = 2) out flat uint tex_id;
void main() {
- Vertex testVertices[6] = Vertex[](
- Vertex(vec2(-0.5, -0.5), vec2(0.0, 0.0), vec4(1.0, 0.0, 0.0, 1.0), 1.0, 0),
- Vertex(vec2( 0.5, -0.5), vec2(1.0, 0.0), vec4(0.0, 1.0, 0.0, 1.0), 1.0, 0),
- Vertex(vec2(-0.5, 0.5), vec2(0.0, 1.0), vec4(0.0, 0.0, 1.0, 1.0), 1.0, 0),
-
- Vertex(vec2( 0.5, 0.5), vec2(1.0, 1.0), vec4(1.0, 1.0, 1.0, 1.0), 1.0, 0),
- Vertex(vec2(-0.5, 0.5), vec2(0.0, 1.0), vec4(0.0, 0.0, 1.0, 1.0), 1.0, 0),
- Vertex(vec2( 0.5, -0.5), vec2(1.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), 1.0, 0)
- );
-
Vertex v = vBuf.vertices[gl_VertexIndex];
uv = v.uv;
diff --git a/shaders/triangle.vert.spv b/shaders/triangle.vert.spv
index 062e3ad..94e0639 100644
Binary files a/shaders/triangle.vert.spv and b/shaders/triangle.vert.spv differ