From 0df52ab5114e5f88ddaef8c1a3e94c7f9c6e7713 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Sat, 9 Nov 2024 10:28:49 -0600 Subject: [PATCH] Compile shaders from the code --- CMakeLists.txt | 9 +- bootstrap/bloat-buster/gui.c | 32 +++-- bootstrap/bloat-buster/shader_compilation.c | 110 ++++++++++++++++++ .../include/bloat-buster/shader_compilation.h | 10 ++ bootstrap/shaders/triangle.frag.spv | Bin 380 -> 0 bytes bootstrap/shaders/triangle.vert.spv | Bin 1748 -> 0 bytes 6 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 bootstrap/bloat-buster/shader_compilation.c create mode 100644 bootstrap/include/bloat-buster/shader_compilation.h delete mode 100644 bootstrap/shaders/triangle.frag.spv delete mode 100644 bootstrap/shaders/triangle.vert.spv diff --git a/CMakeLists.txt b/CMakeLists.txt index a7cf14d..3cf4fd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,6 @@ target_link_libraries(${RUNNER_NAME} PRIVATE ${LIBRARY_NAME}) add_executable("${COMPILER_NAME}" "bootstrap/bloat-buster/main.c" "bootstrap/bloat-buster/pdb_image.c" - "bootstrap/bloat-buster/gui.c" ) target_link_libraries(${COMPILER_NAME} PRIVATE ${LIBRARY_NAME}) @@ -178,11 +177,14 @@ if (USE_LLVM) "bootstrap/bloat-buster/llvm.cpp" "bootstrap/bloat-buster/lld_driver.c" "bootstrap/bloat-buster/lld_api.cpp" + "bootstrap/bloat-buster/gui.c" ) endif() - if (NOT BB_IS_CI) + find_package(glslang REQUIRED) + target_link_libraries(${COMPILER_NAME} PRIVATE glslang::glslang glslang::SPIRV glslang::glslang-default-resource-limits) + set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) @@ -206,4 +208,7 @@ if (NOT BB_IS_CI) add_subdirectory(dependencies/volk-1.3.301 volk) target_link_libraries(${COMPILER_NAME} PRIVATE volk) + target_sources(${COMPILER_NAME} PRIVATE + "bootstrap/bloat-buster/shader_compilation.c" + ) endif() diff --git a/bootstrap/bloat-buster/gui.c b/bootstrap/bloat-buster/gui.c index 780ea76..5d0c1ad 100644 --- a/bootstrap/bloat-buster/gui.c +++ b/bootstrap/bloat-buster/gui.c @@ -6,6 +6,8 @@ #include #include +#include + [[noreturn]] [[gnu::cold]] fn void wrong_vulkan_result(VkResult result, String call_string, String file, int line) { unused(result); @@ -108,19 +110,14 @@ fn void vk_transition_image(VkCommandBuffer command_buffer, VkImage image, VkIma vkCmdPipelineBarrier2(command_buffer, &dependency_info); } -fn VkShaderModule vk_shader_module_create(Arena* arena, VkDevice device, const VkAllocationCallbacks* allocator, String path) +fn VkShaderModule vk_shader_module_create(Arena* arena, VkDevice device, const VkAllocationCallbacks* allocator, String path, ShaderStage shader_stage) { - auto file = file_read(arena, path); - - if (file.length % sizeof(u32) != 0) - { - failed_execution(); - } + auto binary = compile_shader(arena, path, shader_stage); VkShaderModuleCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .codeSize = file.length, - .pCode = (u32*)file.pointer, + .codeSize = binary.length, + .pCode = (u32*)binary.pointer, }; VkShaderModule shader_module; @@ -374,9 +371,8 @@ void run_app(Arena* arena) failed_execution(); } - auto debug_utils_extension = strlit(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); const char* extensions[] = { - string_to_c(debug_utils_extension), + VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME, }; @@ -773,8 +769,8 @@ void run_app(Arena* arena) VkPipeline graphics_pipeline; VkPipelineLayout graphics_pipeline_layout; { - VkShaderModule vertex_shader = vk_shader_module_create(arena, device, allocation_callbacks, strlit("bootstrap/shaders/triangle.vert.spv")); - VkShaderModule fragment_shader = vk_shader_module_create(arena, device, allocation_callbacks, strlit("bootstrap/shaders/triangle.frag.spv")); + VkShaderModule vertex_shader = vk_shader_module_create(arena, device, allocation_callbacks, strlit("bootstrap/shaders/triangle.vert"), SHADER_STAGE_VERTEX); + VkShaderModule fragment_shader = vk_shader_module_create(arena, device, allocation_callbacks, strlit("bootstrap/shaders/triangle.frag"), SHADER_STAGE_FRAGMENT); VkPushConstantRange push_constant_ranges[] = { { @@ -983,22 +979,24 @@ void run_app(Arena* arena) Vec4 color; }; + Vec4 color = { .v = { 1.0f, 0.0f, 0.0f, 1.0f } }; + Vertex vertices[] = { { .position = { .v = { 0.5, -0.5, 0, 1 } }, - .color = { .v = { 255.0f, 0, 0, 1 } }, + .color = color, }, { .position = { .v = { 0.5, 0.5, 0, 1 } }, - .color = { .v = { 255.0f, 0, 0, 1 } }, + .color = color, }, { .position = { .v = { -0.5, -0.5, 0, 1 } }, - .color = { .v = { 255.0f, 0, 0, 1 } }, + .color = color, }, { .position = { .v = { -0.5, 0.5, 0, 1 } }, - .color = { .v = { 255.0f, 0, 0, 1 } }, + .color = color, }, }; diff --git a/bootstrap/bloat-buster/shader_compilation.c b/bootstrap/bloat-buster/shader_compilation.c new file mode 100644 index 0000000..8924e83 --- /dev/null +++ b/bootstrap/bloat-buster/shader_compilation.c @@ -0,0 +1,110 @@ +#include +#include + + +// Required for use of glslang_default_resource +#include + +typedef struct SpirVBinary { + uint32_t *words; // SPIR-V words + int size; // number of words in SPIR-V binary +} SpirVBinary; + +fn SpirVBinary compileShaderToSPIRV_Vulkan(Arena* arena, glslang_stage_t stage, String shader_source, String filename) +{ + if (!glslang_initialize_process()) + { + failed_execution(); + } + + const glslang_input_t input = { + .language = GLSLANG_SOURCE_GLSL, + .stage = stage, + .client = GLSLANG_CLIENT_VULKAN, + .client_version = GLSLANG_TARGET_VULKAN_1_3, + .target_language = GLSLANG_TARGET_SPV, + .target_language_version = GLSLANG_TARGET_SPV_1_6, + .code = string_to_c(shader_source), + .default_version = 450, + .default_profile = GLSLANG_NO_PROFILE, + .force_default_version_and_profile = false, + .forward_compatible = false, + .messages = GLSLANG_MSG_DEFAULT_BIT, + .resource = glslang_default_resource(), + }; + + glslang_shader_t* shader = glslang_shader_create(&input); + + + SpirVBinary bin = { + .words = NULL, + .size = 0, + }; + if (!glslang_shader_preprocess(shader, &input)) { + print("GLSL preprocessing failed {s}\n", filename); + print("{cstr}\n", glslang_shader_get_info_log(shader)); + print("{cstr}\n", glslang_shader_get_info_debug_log(shader)); + print("{cstr}\n", input.code); + glslang_shader_delete(shader); + return bin; + } + + if (!glslang_shader_parse(shader, &input)) { + print("GLSL parsing failed {s}\n", filename); + print("{cstr}\n", glslang_shader_get_info_log(shader)); + print("{cstr}\n", glslang_shader_get_info_debug_log(shader)); + print("{cstr}\n", glslang_shader_get_preprocessed_code(shader)); + glslang_shader_delete(shader); + return bin; + } + + glslang_program_t* program = glslang_program_create(); + glslang_program_add_shader(program, shader); + + if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) { + print("GLSL linking failed {s}\n", filename); + print("{cstr}\n", glslang_program_get_info_log(program)); + print("{cstr}\n", glslang_program_get_info_debug_log(program)); + glslang_program_delete(program); + glslang_shader_delete(shader); + return bin; + } + + glslang_program_SPIRV_generate(program, stage); + + bin.size = glslang_program_SPIRV_get_size(program); + bin.words = arena_allocate(arena, u32, bin.size); + glslang_program_SPIRV_get(program, bin.words); + + const char* spirv_messages = glslang_program_SPIRV_get_messages(program); + if (spirv_messages) + print("({s}) {cstr}\b", filename, spirv_messages); + + glslang_program_delete(program); + glslang_shader_delete(shader); + + return bin; +} + +String compile_shader(Arena* arena, String path, ShaderStage shader_stage) +{ + auto file = file_read(arena, path); + + glslang_stage_t stage; + switch (shader_stage) + { + case SHADER_STAGE_VERTEX: + stage = GLSLANG_STAGE_VERTEX; + break; + case SHADER_STAGE_FRAGMENT: + stage = GLSLANG_STAGE_FRAGMENT; + break; + } + + auto result = compileShaderToSPIRV_Vulkan(arena, stage, file, path); + + return (String) { + .pointer = (u8*)result.words, + .length = result.size * sizeof(*result.words), + }; +} diff --git a/bootstrap/include/bloat-buster/shader_compilation.h b/bootstrap/include/bloat-buster/shader_compilation.h new file mode 100644 index 0000000..8125798 --- /dev/null +++ b/bootstrap/include/bloat-buster/shader_compilation.h @@ -0,0 +1,10 @@ +#include +#include + +typedef enum ShaderStage : u8 +{ + SHADER_STAGE_VERTEX, + SHADER_STAGE_FRAGMENT, +} ShaderStage; + +EXPORT String compile_shader(Arena* arena, String path, ShaderStage shader_stage); diff --git a/bootstrap/shaders/triangle.frag.spv b/bootstrap/shaders/triangle.frag.spv deleted file mode 100644 index 4f5904efec83454dbdfe9f271498e9f4d9562919..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmYk1%L>9!3`C=~zMlxXlZtzBp(2QG1l_pv3krf1w1rxK(64eMc;@=R3u!WwNhbC3 zqmo(9YF4&}y_wmt8a?7@9c-kcABn3L1_C)cU+A$^FKuw;o`d{3|K^{ZrX0Gm07vTb; zk6yP3%Rk^-ChKp+FF#lw;?%E_Ir-NYmZ!Km7s^k&^fdE;@yRP#?W_~hujy*9@RR8U F@dENn78U>i diff --git a/bootstrap/shaders/triangle.vert.spv b/bootstrap/shaders/triangle.vert.spv deleted file mode 100644 index 6049064abeb6e2e57c92967f39da42a3f6c46fcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1748 zcmZ9MTTc^F6oogG4g!i71iU~kqN1SagBlZq38E=P9;z7P+oY5MCaIlfW=hnb=U-9( zgD)noZ#o;$Lsrh-YhPJspfbETYBppOcFvyI;9Rz0F=pI9u9}V8nC&!o!*`n>!rsx> zEN-_tVU{Op>o5xU`UeM5s`{X)X>9LouV(rF>eFXMyGg6qPxYYRMa|%h2%lSV7yFuU zUw9-`^fRpcyOKw2)Ee92+fN_M31J#(PSkBjiUl6qkM{b9VK0rl`GHjxIolhbiMvsn zM_)`;LAilhFUjIOPKq4@Rg%Y!?WB{Wx~tk{T=#KdSM7We>t=bYn`g2E?FYv>F8aS7 z2qB-j7j&PUi_iIgF8sf91L@?or#;ynp2NJj9kGUH1$rm5Woy00-tl#OJ z#L$*E=T!B>+b8{eqm7CO`f&XidA1?5nKJtND1 zmsxetA8z5(t0tds7!K6skCit3l4_azOMi)6eVS@X?qV z^mrT>9eA>L!;u`r)HL9Pt~v*`M9;(aQJs{tM#B zXFhLQ7dXW6?+C=_hyms->E;cHvll+!FC6ie(x#R;K5t3w1v1l?apd(tXDF=OK1bBS(xh|m1y0%4^n*ur15L*+EPICe= zcHq6