Changed multiple render passes to subpasses

main
noah metz 2024-10-15 00:06:46 -06:00
parent 6988abcd86
commit 28cd4efbaf
8 changed files with 198 additions and 49 deletions

@ -10,11 +10,13 @@ SOURCES = src/main.c src/render.c src/vma.cpp src/pipeline.c src/command.c src/s
OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
VERT_SPV = $(addsuffix .vert.spv, $(basename $(wildcard shader_src/*.vert)))
FRAG_SPV = $(addsuffix .frag.spv, $(basename $(wildcard shader_src/*.frag)))
COMP_SPV = $(addsuffix .comp.spv, $(basename $(wildcard shader_src/*.comp)))
SPV_FILES = $(VERT_SPV) $(FRAG_SPV) $(COMP_SPV)
export MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=1
.PHONY: all
all: roleplay $(VERT_SPV) $(FRAG_SPV)
all: roleplay $(SPV_FILES)
roleplay: $(OBJECTS)
$(CPP) $(CFLAGS) $(LDFLAGS) -o $@ $^
@ -28,8 +30,7 @@ roleplay: $(OBJECTS)
.PHONY: clean clean_compdb
clean:
rm -f $(FRAG_SPV)
rm -f $(VERT_SPV)
rm -f $(SPV_FILES)
rm -f $(OBJECTS)
rm -f roleplay
rm -rf roleplay.dSYM
@ -38,18 +39,20 @@ clean_compdb:
rm -rf .compdb
rm compile_commands.json
run: roleplay $(VERT_SPV) $(FRAG_SPV)
run: roleplay $(SPV_FILES)
./roleplay
roleplay.dSYM: roleplay
$(DSYM) roleplay
debug: roleplay roleplay.dSYM $(VERT_SPV) $(FRAG_SPV)
debug: roleplay roleplay.dSYM $(SPV_FILES)
$(GDB) roleplay
%.vert.spv: %.vert
glslangValidator -V -o $@ $<
%.frag.spv: %.frag
glslangValidator -V -o $@ $<
%.comp.spv: %.comp
glslangValidator -V -o $@ $<

@ -34,6 +34,12 @@ typedef struct TextStruct {
uint32_t offset;
} Text;
typedef struct TextPointersStruct {
VkDeviceAddress strings;
VkDeviceAddress codes;
VkDeviceAddress characters;
} TextPointers;
typedef struct CharStruct {
vec3 pos;
vec4 color;

@ -71,8 +71,7 @@ typedef struct RenderContextStruct {
VkCommandPool graphics_pool;
VkCommandPool transfer_pool;
VkRenderPass world_render_pass;
VkRenderPass ui_render_pass;
VkRenderPass render_pass;
VkCommandBuffer* swapchain_command_buffers;

@ -0,0 +1,64 @@
#version 450
#extension GL_EXT_buffer_reference : require
struct Symbol {
uint x;
uint top;
uint width;
};
struct Character {
vec3 pos;
vec4 color;
float size;
uint code;
};
struct String {
vec3 pos;
vec4 color;
float size;
uint offset;
uint length;
};
layout(buffer_reference, std430) readonly buffer SymbolList{
Symbol symbols[];
};
layout(buffer_reference, std430) writeonly buffer CharacterList{
Character characters[];
};
layout(buffer_reference, std430) readonly buffer Characters{
uint codes[];
};
layout(buffer_reference, std430) readonly buffer Strings{
String strings[];
};
layout(set = 0, binding = 0) uniform UIUniform {
mat4 screen;
} ubo;
layout(set = 1, binding = 0) uniform Font {
uint num_symbols;
uint width;
uint height;
uint space_width;
SymbolList symbol_list;
} font;
layout(buffer_reference, std430) readonly buffer Pointers {
Strings strings;
Characters codes;
CharacterList characters;
};
layout(std430, push_constant) uniform Push {
Pointers pointers;
} push;
void main() {
}

@ -26,7 +26,7 @@ layout(set = 0, binding = 0) uniform UIUniform {
mat4 screen;
} ubo;
layout(set = 1, binding = 0) uniform FontUniform {
layout(set = 1, binding = 0) uniform Font {
uint num_symbols;
uint width;
uint height;
@ -34,8 +34,13 @@ layout(set = 1, binding = 0) uniform FontUniform {
SymbolList symbol_list;
} font;
layout(std430, push_constant) uniform Push {
layout(buffer_reference, std430) readonly buffer Pointers {
uint padding[4];
CharacterList characters;
};
layout(std430, push_constant) uniform Push {
Pointers pointers;
} push;
layout(location = 0) in vec2 inVertexPosition;
@ -44,7 +49,7 @@ layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec2 fragUV;
void main() {
Character character = push.characters.characters[gl_InstanceIndex];
Character character = push.pointers.characters.characters[gl_InstanceIndex];
Symbol symbol = font.symbol_list.symbols[character.code];
float fragU = (inVertexPosition.x*symbol.width + symbol.x) / font.width;

@ -106,7 +106,7 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
VmaAllocation colored_rect_memory;
VmaAllocation text_memory;
result = init_pipelines(render_context->device, render_context->allocator, render_context->swapchain_extent, render_context->world_render_pass, render_context->transfer_queue, render_context->transfer_pool, &ui_context);
result = init_pipelines(render_context->device, render_context->allocator, render_context->swapchain_extent, render_context->render_pass, render_context->transfer_queue, render_context->transfer_pool, &ui_context);
if(result != VK_SUCCESS) {
return result;
}
@ -197,10 +197,42 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
vmaUnmapMemory(render_context->allocator, text_memory);
VkBuffer text_pointer_buffer;
VmaAllocation text_pointer_memory;
VkBufferCreateInfo text_pointer_buffer_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.size = sizeof(TextPointers),
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
VmaAllocationCreateInfo text_pointer_memory_info = {
.usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
};
result = vmaCreateBuffer(render_context->allocator, &text_pointer_buffer_info, &text_pointer_memory_info, &text_pointer_buffer, &text_pointer_memory, NULL);
if(result != VK_SUCCESS) {
return result;
}
TextPointers* pointers;
result = vmaMapMemory(render_context->allocator, text_pointer_memory, (void**)&pointers);
if(result != VK_SUCCESS) {
return result;
}
VkBufferDeviceAddressInfo test_address_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = text_buffer,
};
pointers->characters = vkGetBufferDeviceAddress(render_context->device, &test_address_info);
vmaUnmapMemory(render_context->allocator, text_pointer_memory);
VkBufferDeviceAddressInfo pointers_address_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = text_pointer_buffer,
};
UILayer test_layer = {
.colored_rects = colored_rect_buffer,
@ -209,7 +241,7 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
.font = test_font_descriptor,
.text_count = 2,
.texts = text_buffer,
.texts_address = vkGetBufferDeviceAddress(render_context->device, &test_address_info),
.texts_address = vkGetBufferDeviceAddress(render_context->device, &pointers_address_info),
};
while(glfwWindowShouldClose(window) == 0) {

@ -286,6 +286,46 @@ VkPipelineVertexInputStateCreateInfo input_info = {
}
VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDescriptorSetLayout ui_descriptor_layout, VkDescriptorSetLayout font_layout, GraphicsPipeline* pipeline, ComputePipeline* compute) {
VkResult result;
VkShaderModule compute_shader = load_shader_file("shader_src/ui_text.comp.spv", device);
if(compute_shader == VK_NULL_HANDLE) {
return VK_ERROR_UNKNOWN;
}
VkPipelineShaderStageCreateInfo compute_shader_stage = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
.pName = "main",
.module = compute_shader,
};
VkPushConstantRange push_constant = {
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT,
.size = 8,
};
VkPipelineLayoutCreateInfo compute_layout_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_constant,
};
result = vkCreatePipelineLayout(device, &compute_layout_info, NULL, &compute->layout);
if(result != VK_SUCCESS) {
return result;
}
VkComputePipelineCreateInfo compute_pipeline_info = {
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.layout = compute->layout,
.stage = compute_shader_stage,
};
result = vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_info, NULL, &compute->pipeline);
if(result != VK_SUCCESS) {
return result;
}
VkShaderModule vert_shader = load_shader_file("shader_src/ui_text.vert.spv", device);
if(vert_shader == VK_NULL_HANDLE) {
return VK_ERROR_UNKNOWN;
@ -339,11 +379,6 @@ VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDe
VkDescriptorSetLayout all_layouts[] = {ui_descriptor_layout, font_layout};
VkPushConstantRange push_constant = {
.size = 8,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
};
VkPipelineLayoutCreateInfo layout_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = sizeof(all_layouts)/sizeof(VkDescriptorSetLayout),
@ -358,7 +393,7 @@ VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDe
.primitiveRestartEnable = VK_FALSE,
};
VkResult result = create_ui_pipeline(device, render_pass, shader_stages, sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), input_info, layout_info, input_assembly_info, pipeline);
result = create_ui_pipeline(device, render_pass, shader_stages, sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), input_info, layout_info, input_assembly_info, pipeline);
if(result != VK_SUCCESS) {
return result;
}

@ -27,6 +27,10 @@ const char * instance_extensions[] = {
uint32_t instance_extension_count = sizeof(instance_extensions) / sizeof(const char *);
const char * device_extensions[] = {
#ifdef __APPLE__
"VK_KHR_portability_subset",
#endif
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
};
@ -125,8 +129,6 @@ VkResult create_instance(VkInstance* instance) {
.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR,
};
VkResult result = vkCreateInstance(&instance_info, 0, instance);
if(result != VK_SUCCESS) {
return result;
@ -575,17 +577,17 @@ VkResult find_depth_format(VkPhysicalDevice physical_device, VkImageTiling tilin
return VK_ERROR_UNKNOWN;
}
VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat depth_format, VkRenderPass* render_pass, VkImageLayout initial_layout, VkImageLayout final_layout, VkAttachmentLoadOp color_load_op) {
VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat depth_format, VkRenderPass* render_pass) {
VkAttachmentDescription attachments[] = {
{
.format = format.format,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = color_load_op,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
.initialLayout = initial_layout,
.finalLayout = final_layout,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
},
{
.format = depth_format,
@ -619,6 +621,12 @@ VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat
.pColorAttachments = color_attachment_refs,
.pDepthStencilAttachment = &depth_attachment_ref,
},
{
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.colorAttachmentCount = sizeof(color_attachment_refs)/sizeof(VkAttachmentReference),
.pColorAttachments = color_attachment_refs,
.pDepthStencilAttachment = &depth_attachment_ref,
},
};
// This basically says "make sure nothing else is writing to the depth_stencil or the color attachment during the pipeline
@ -631,6 +639,15 @@ VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
},
{
.srcSubpass = 0,
.dstSubpass = 1,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
}
};
@ -931,12 +948,7 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) {
return result;
}
result = create_render_pass(context->device, context->swapchain_format, context->depth_format, &context->world_render_pass, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_ATTACHMENT_LOAD_OP_CLEAR);
if(result != VK_SUCCESS) {
return result;
}
result = create_render_pass(context->device, context->swapchain_format, context->depth_format, &context->ui_render_pass, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_ATTACHMENT_LOAD_OP_LOAD);
result = create_render_pass(context->device, context->swapchain_format, context->depth_format, &context->render_pass);
if(result != VK_SUCCESS) {
return result;
}
@ -946,7 +958,7 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) {
return result;
}
result = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->world_render_pass, context->swapchain_extent, &context->swapchain_framebuffers);
result = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent, &context->swapchain_framebuffers);
if(result != VK_SUCCESS) {
return result;
}
@ -1005,30 +1017,20 @@ VkResult draw_frame(RenderContext* context, UIContext* ui_context, UILayer* ui_l
VkClearValue clear_values[2] = {{.color={{0.0f, 0.0f, 0.0f, 1.0f}}}, {.depthStencil={1.0f, 0.0f}}};
VkDeviceSize offset = 0;
// World Render Pass
VkRenderPassBeginInfo world_render_pass_begin = {
VkRenderPassBeginInfo render_pass_begin = {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = context->world_render_pass,
.renderPass = context->render_pass,
.framebuffer = context->swapchain_framebuffers[image_index],
.renderArea.offset = {0, 0},
.renderArea.extent = context->swapchain_extent,
.clearValueCount = 2,
.pClearValues = clear_values,
};
vkCmdBeginRenderPass(command_buffer, &world_render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
vkCmdEndRenderPass(command_buffer);
vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
// World subpass
// UI Render Pass
VkRenderPassBeginInfo ui_render_pass_begin = {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = context->ui_render_pass,
.framebuffer = context->swapchain_framebuffers[image_index],
.renderArea.offset = {0, 0},
.renderArea.extent = context->swapchain_extent,
.clearValueCount = 2,
.pClearValues = clear_values,
};
vkCmdBeginRenderPass(command_buffer, &ui_render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE);
// UI subpass
// Draw UI colored rects ////////////////////////////////
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_rect.pipeline);
@ -1044,12 +1046,15 @@ VkResult draw_frame(RenderContext* context, UIContext* ui_context, UILayer* ui_l
}
/////////////////////////////////////////////////////////
// Draw UI text /////////////////////////////////////////
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->ui_compute_text.pipeline);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.pipeline);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.layout, 0, 1, &ui_context->ui_descriptor_set, 0, NULL);
for(uint32_t i = 0; i < ui_layer_count; i++) {
if(ui_layers[i].text_count > 0) {
// Bind Font Descriptor
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.layout, 1, 1, &ui_layers[i].font.set, 0, NULL);
vkCmdPushConstants(command_buffer, ui_context->ui_pipeline_text.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 8, &ui_layers[i].texts_address);
// Push pointers
vkCmdPushConstants(command_buffer, ui_context->ui_pipeline_text.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, &ui_layers[i].texts_address);
vkCmdDrawIndexed(command_buffer, 6, ui_layers[i].text_count, 0, 0, 0);
}
}