Added better failure logging, added create hex pipeline

main
noah metz 2024-10-30 17:36:53 -06:00
parent 40d31430c2
commit 62d17bee4a
8 changed files with 334 additions and 91 deletions

@ -2,7 +2,7 @@ ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
CFLAGS = -I $(ROOT_DIR)/include -I/usr/local/include -O0 -g -Wall -Wextra CFLAGS = -I $(ROOT_DIR)/include -I/usr/local/include -O0 -g -Wall -Wextra
LDFLAGS = -lfreetype -lz -lglfw -lvulkan -ldl -Xlinker -rpath -Xlinker /opt/homebrew/lib LDFLAGS = -lfreetype -lz -lglfw -lvulkan -ldl -Xlinker -rpath -Xlinker /opt/homebrew/lib
SOURCES = src/main.c src/draw.c src/ui.c src/gpu.c lib/spng.c lib/vma.cpp SOURCES = src/main.c src/draw.c src/ui.c src/gpu.c src/hex.c lib/spng.c lib/vma.cpp
OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
VERT_SPV = $(addsuffix .vert.spv, $(basename $(wildcard shader/*.vert))) VERT_SPV = $(addsuffix .vert.spv, $(basename $(wildcard shader/*.vert)))
FRAG_SPV = $(addsuffix .frag.spv, $(basename $(wildcard shader/*.frag))) FRAG_SPV = $(addsuffix .frag.spv, $(basename $(wildcard shader/*.frag)))

@ -2,6 +2,7 @@
#define GPU_H #define GPU_H
#define VK_USE_PLATFORM_MACOS_MVK #define VK_USE_PLATFORM_MACOS_MVK
#include "vulkan/vk_enum_string_helper.h"
#include "vulkan/vulkan_core.h" #include "vulkan/vulkan_core.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
@ -28,28 +29,43 @@
#define WINDOW_MIN_WIDTH 800 #define WINDOW_MIN_WIDTH 800
#define WINDOW_MIN_HEIGHT 600 #define WINDOW_MIN_HEIGHT 600
typedef struct GPUQueueStruct {
VkQueue handle;
uint32_t family;
uint32_t index;
} GPUQueue;
VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool);
VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, GPUQueue transfer_queue);
void command_copy_buffer(VkCommandBuffer command_buffer, VkBuffer src, VkBuffer dst, VkDeviceSize src_offset, VkDeviceSize dst_offset, VkDeviceSize size);
VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, GPUQueue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family, VkImageAspectFlags aspect_flags);
#define VK_RESULT(x) {\ #define VK_RESULT(x) {\
result = x;\ result = x;\
if(result != VK_SUCCESS) {\ if(result != VK_SUCCESS) {\
fprintf(stderr, "%s failed with %s\n", #x, string_VkResult(result));\
return x;\ return x;\
}\ }\
} }
typedef struct ComputePipelineStruct {
VkPipelineLayout layout;
VkPipeline pipeline;
} ComputePipeline;
typedef struct GraphicsPipelineStruct {
VkPipelineLayout layout;
VkPipeline pipeline;
} GraphicsPipeline;
typedef struct DrawCommandStruct {
uint32_t vertex_count;
uint32_t instance_count;
uint32_t first_vertex;
uint32_t first_instance;
} DrawCommand;
typedef struct DispatchCommandStruct {
uint32_t x;
uint32_t y;
uint32_t z;
} DispatchCommand;
typedef struct GPUQueueStruct {
VkQueue handle;
uint32_t family;
uint32_t index;
} GPUQueue;
typedef struct SwapchainDetailsStruct { typedef struct SwapchainDetailsStruct {
VkSurfaceCapabilitiesKHR capabilities; VkSurfaceCapabilitiesKHR capabilities;
@ -180,4 +196,39 @@ VkResult add_transfers(
VkDeviceSize size, VkDeviceSize size,
RenderContext* gpu); RenderContext* gpu);
VkCommandBuffer command_begin_single(
VkDevice device,
VkCommandPool transfer_pool);
VkResult command_end_single(
VkDevice device,
VkCommandBuffer command_buffer,
VkCommandPool transfer_pool,
GPUQueue transfer_queue);
void command_copy_buffer(
VkCommandBuffer command_buffer,
VkBuffer src,
VkBuffer dst,
VkDeviceSize src_offset,
VkDeviceSize dst_offset,
VkDeviceSize size);
VkResult command_transition_image_layout(
VkDevice device,
VkCommandPool transfer_pool,
GPUQueue transfer_queue,
VkImageLayout old_layout,
VkImageLayout new_layout,
VkImage image,
VkAccessFlags src_mask,
VkAccessFlags dst_mask,
VkPipelineStageFlags source,
VkPipelineStageFlags dest,
uint32_t source_family,
uint32_t dest_family,
VkImageAspectFlags aspect_flags);
VkShaderModule load_shader_file(const char* path, VkDevice device);
#endif #endif

@ -0,0 +1,17 @@
#ifndef HEX_H
#define HEX_H
#include "gpu.h"
typedef struct HexPushStruct {
VkDeviceAddress context;
VkDeviceAddress world;
} HexPush;
VkResult create_hex_pipeline(
VkDevice device,
VkRenderPass render_pass,
GraphicsPipeline* graphics,
ComputePipeline* compute);
#endif

@ -15,29 +15,6 @@
#define ANCHOR_BOTTOM_RIGHT 3 #define ANCHOR_BOTTOM_RIGHT 3
#define ANCHOR_CENTER 4 #define ANCHOR_CENTER 4
typedef struct ComputePipelineStruct {
VkPipelineLayout layout;
VkPipeline pipeline;
} ComputePipeline;
typedef struct GraphicsPipelineStruct {
VkPipelineLayout layout;
VkPipeline pipeline;
} GraphicsPipeline;
typedef struct DrawCommandStruct {
uint32_t vertex_count;
uint32_t instance_count;
uint32_t first_vertex;
uint32_t first_instance;
} DrawCommand;
typedef struct DispatchCommandStruct {
uint32_t x;
uint32_t y;
uint32_t z;
} DispatchCommand;
typedef struct UIPushConstantStruct { typedef struct UIPushConstantStruct {
VkDeviceAddress layer; VkDeviceAddress layer;
float time; float time;

@ -42,8 +42,6 @@ VkFormat depth_formats[] = {
}; };
uint32_t depth_format_count = sizeof(depth_formats) / sizeof(VkFormat); uint32_t depth_format_count = sizeof(depth_formats) / sizeof(VkFormat);
void glfw_error(int error, const char* description) { void glfw_error(int error, const char* description) {
fprintf(stderr, "GLFW_ERR: 0x%02x - %s\n", error, description); fprintf(stderr, "GLFW_ERR: 0x%02x - %s\n", error, description);
} }
@ -63,6 +61,49 @@ GLFWwindow* init_window() {
return window; return window;
} }
VkShaderModule load_shader_file(const char* path, VkDevice device) {
FILE* file;
file = fopen(path, "rb");
if(file == 0) {
return VK_NULL_HANDLE;
}
int result = fseek(file, 0, SEEK_END);
if(result != 0) {
return VK_NULL_HANDLE;
}
long buffer_size = ftell(file);
result = fseek(file, 0, SEEK_SET);
if(result != 0) {
return VK_NULL_HANDLE;
}
char * buffer = malloc(buffer_size);
if(buffer == 0) {
return VK_NULL_HANDLE;
}
size_t read = fread(buffer, 1, buffer_size, file);
VkShaderModuleCreateInfo shader_info = {
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = read,
.pCode = (uint32_t*)buffer,
};
VkShaderModule shader;
result = vkCreateShaderModule(device, &shader_info, 0, &shader);
free(buffer);
if(result != VK_SUCCESS) {
return VK_NULL_HANDLE;
}
return shader;
}
bool check_validation_layers(const char ** layers, uint32_t num_layers) { bool check_validation_layers(const char ** layers, uint32_t num_layers) {
uint32_t layer_count; uint32_t layer_count;
VkResult result; VkResult result;

@ -0,0 +1,201 @@
#include "hex.h"
#include "gpu.h"
#include "vulkan/vulkan_core.h"
VkResult create_hex_pipeline(
VkDevice device,
VkRenderPass render_pass,
GraphicsPipeline* graphics,
ComputePipeline* compute) {
VkResult result;
// Compute Pipeline
VkShaderModule compute_shader = load_shader_file("shader/hex.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 = {
.size = sizeof(HexPush),
.offset = 0,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT,
};
VkPipelineLayoutCreateInfo compute_layout_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pPushConstantRanges = &push_constant,
.pushConstantRangeCount = 1,
};
VK_RESULT(vkCreatePipelineLayout(device, &compute_layout_info, NULL, &compute->layout));
VkComputePipelineCreateInfo compute_pipeline_info = {
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.stage = compute_shader_stage,
.layout = compute->layout,
};
VK_RESULT(vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_info, NULL, &compute->pipeline));
// Graphics Pipeline
VkShaderModule vert_shader = load_shader_file("shader/hex.vert.spv", device);
VkShaderModule frag_shader = load_shader_file("shader/hex.frag.spv", device);
VkPipelineShaderStageCreateInfo graphics_stages[] = {
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.pName = "main",
.module = vert_shader,
},
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.pName = "main",
.module = frag_shader,
},
};
VkPipelineLayoutCreateInfo graphics_layout_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pPushConstantRanges = &push_constant,
.pushConstantRangeCount = 1,
};
VK_RESULT(vkCreatePipelineLayout(device, &graphics_layout_info, NULL, &graphics->layout));
VkPipelineVertexInputStateCreateInfo vertex_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
};
VkPipelineInputAssemblyStateCreateInfo input_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.primitiveRestartEnable = VK_FALSE,
};
VkViewport viewport = {
.x = 0.0f,
.y = 0.0f,
.width = (float)(100),
.height = (float)(100),
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
VkRect2D scissor = {
.offset = {
.x = 0,
.y = 0,
},
.extent = {
.width = 100,
.height = 100,
},
};
VkPipelineViewportStateCreateInfo viewport_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.viewportCount = 1,
.pViewports = &viewport,
.scissorCount = 1,
.pScissors = &scissor,
};
VkPipelineRasterizationStateCreateInfo raster_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.depthClampEnable = VK_TRUE,
.rasterizerDiscardEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
.lineWidth = 1.0f,
.cullMode = VK_CULL_MODE_BACK_BIT,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
.depthBiasEnable = VK_FALSE,
.depthBiasConstantFactor = 0.0f,
.depthBiasClamp = 0.0f,
.depthBiasSlopeFactor = 0.0f,
};
VkPipelineColorBlendAttachmentState blend_attachments = {
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
.blendEnable = VK_TRUE,
.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.alphaBlendOp = VK_BLEND_OP_ADD,
};
VkPipelineColorBlendStateCreateInfo blend_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_COPY,
.attachmentCount = 1,
.pAttachments = &blend_attachments,
};
VkDynamicState dynamic_states[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
};
VkPipelineDynamicStateCreateInfo dynamic_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = sizeof(dynamic_states)/sizeof(VkDynamicState),
.pDynamicStates = dynamic_states,
};
VkPipelineMultisampleStateCreateInfo multisample_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.sampleShadingEnable = VK_FALSE,
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
.minSampleShading = 1.0f,
.pSampleMask = 0,
.alphaToCoverageEnable = VK_FALSE,
.alphaToOneEnable = VK_FALSE,
};
VkPipelineDepthStencilStateCreateInfo depth_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = VK_TRUE,
.depthWriteEnable = VK_TRUE,
.depthCompareOp = VK_COMPARE_OP_LESS,
.depthBoundsTestEnable = VK_TRUE,
.minDepthBounds = 0.0f,
.maxDepthBounds = 1.0f,
.stencilTestEnable = VK_FALSE,
};
VkGraphicsPipelineCreateInfo graphics_pipeline_info = {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.layout = graphics->layout,
.stageCount = sizeof(graphics_stages)/sizeof(VkPipelineShaderStageCreateInfo),
.pStages = graphics_stages,
.pVertexInputState = &vertex_info,
.pInputAssemblyState = &input_info,
.pViewportState = &viewport_info,
.pRasterizationState = &raster_info,
.pColorBlendState = &blend_info,
.pDynamicState = &dynamic_info,
.pMultisampleState = &multisample_info,
.pDepthStencilState = &depth_info,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = -1,
};
VK_RESULT(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphics_pipeline_info, NULL, &graphics->pipeline));
return VK_SUCCESS;
}

@ -2,6 +2,7 @@
#include "ui.h" #include "ui.h"
#include "gpu.h" #include "gpu.h"
#include "draw.h" #include "draw.h"
#include "hex.h"
#include "arpa/inet.h" #include "arpa/inet.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
@ -28,6 +29,10 @@ void* network_thread(void* data) {
VkResult main_thread(ClientContext* context) { VkResult main_thread(ClientContext* context) {
VkResult result; VkResult result;
GraphicsPipeline graphics;
ComputePipeline compute;
VK_RESULT(create_hex_pipeline(context->render.device, context->render.render_pass, &graphics, &compute));
GPUString strings[] = { GPUString strings[] = {
{ {
.pos = {0, 32}, .pos = {0, 32},

@ -11,48 +11,6 @@
#include "spng.h" #include "spng.h"
#include <sys/param.h> #include <sys/param.h>
VkShaderModule load_shader_file(const char* path, VkDevice device) {
FILE* file;
file = fopen(path, "rb");
if(file == 0) {
return VK_NULL_HANDLE;
}
int result = fseek(file, 0, SEEK_END);
if(result != 0) {
return VK_NULL_HANDLE;
}
long buffer_size = ftell(file);
result = fseek(file, 0, SEEK_SET);
if(result != 0) {
return VK_NULL_HANDLE;
}
char * buffer = malloc(buffer_size);
if(buffer == 0) {
return VK_NULL_HANDLE;
}
size_t read = fread(buffer, 1, buffer_size, file);
VkShaderModuleCreateInfo shader_info = {
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = read,
.pCode = (uint32_t*)buffer,
};
VkShaderModule shader;
result = vkCreateShaderModule(device, &shader_info, 0, &shader);
free(buffer);
if(result != VK_SUCCESS) {
return VK_NULL_HANDLE;
}
return shader;
}
VkResult create_ui_pipeline( VkResult create_ui_pipeline(
VkDevice device, VkDevice device,
VkRenderPass render_pass, VkRenderPass render_pass,
@ -124,15 +82,8 @@ VkResult create_ui_pipeline(
}, },
}; };
VkVertexInputBindingDescription bindings[] = {};
VkVertexInputAttributeDescription attributes[] = {};
VkPipelineVertexInputStateCreateInfo input_info = { VkPipelineVertexInputStateCreateInfo input_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pVertexBindingDescriptions = bindings,
.vertexBindingDescriptionCount = sizeof(bindings)/sizeof(VkVertexInputBindingDescription),
.pVertexAttributeDescriptions = attributes,
.vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription),
}; };
VkPipelineInputAssemblyStateCreateInfo input_assembly_info = { VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {