diff --git a/assets/shaders/triangle.frag.spv b/assets/shaders/triangle.frag.spv new file mode 100644 index 0000000..c9fb610 Binary files /dev/null and b/assets/shaders/triangle.frag.spv differ diff --git a/assets/shaders/triangle.vert.spv b/assets/shaders/triangle.vert.spv new file mode 100644 index 0000000..291e27e Binary files /dev/null and b/assets/shaders/triangle.vert.spv differ diff --git a/build-vma.sh b/build-vma.sh index e9dd872..5872b42 100755 --- a/build-vma.sh +++ b/build-vma.sh @@ -1,6 +1,30 @@ #!/bin/bash set -eu +# SHADERS + +shader_compiler="glslc" +shader_flags="--target-spv=spv1.6 -std=460" +shader_out="-oassets/shaders/" + +mkdir -p assets/shaders + +for shader in src/shaders/*.glsl; do + base_name=$(basename -- "$shader" .glsl) + + case "$base_name" in + *.vert) shader_stage="-fshader-stage=vert" ;; + *.frag) shader_stage="-fshader-stage=frag" ;; + *.tesc) shader_stage="-fshader-stage=tesc" ;; + *.tese) shader_stage="-fshader-stage=tese" ;; + *.geom) shader_stage="-fshader-stage=geom" ;; + *.comp) shader_stage="-fshader-stage=comp" ;; + *) continue ;; + esac + + $shader_compiler $shader_flags $shader_stage $shader "${shader_out}${base_name}.spv" +done + if [ -x "$(command -v g++)" ]; then cpp_compiler="g++"; c_compiler="gcc"; elif [ -x "$(command -v clang++)" ]; then cpp_compiler="clang++"; c_compiler="clang"; else echo "Unable to find c++ cpp_compiler"; exit -1; fi; diff --git a/dub.json b/dub.json index c27b067..59f9655 100644 --- a/dub.json +++ b/dub.json @@ -13,7 +13,7 @@ "sourcePaths": ["src/gears", "src/shared", "src/generated"], "libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++"], "libs-windows": [], - "preGenerateCommands-linux": ["./build-vma.sh"], + "preGenerateCommands-linux": ["./build-vma.sh", "build/Packer"], "preGenerateCommands-windows": [], }, { @@ -37,6 +37,7 @@ "sourceFiles-linux": ["build/libxxhash.a", "build/libstb_image.a"], "preGenerateCommands-linux": ["./build-vma.sh"], "preGenerateCommands-windows": [], + "versions": ["codegen"], } ] } diff --git a/src/gears/main.d b/src/gears/main.d index 1eb6169..2f4ad84 100644 --- a/src/gears/main.d +++ b/src/gears/main.d @@ -6,13 +6,34 @@ import u = util : Result; import p = platform; import a = alloc; import vk = vulkan : Vulkan; +import ap = assets; +import r = renderer; void main() { p.Window window = p.CreateWindow("Video Game", 1920, 1080); + assert(ap.OpenAssetPack(), "OpenAssetPack failure"); + Result!(Vulkan) result = vk.Init(&window, u.MB(24), u.MB(32)); Vulkan vulkan = result.value; + u8[] vert_bytes = ap.LoadAssetData("shaders/triangle.vert"); + u8[] frag_bytes = ap.LoadAssetData("shaders/triangle.frag"); + + assert(vert_bytes != null && frag_bytes != null, "Unable to load shader data"); + + auto vert_module = vk.BuildShader(&vulkan, vert_bytes); + auto frag_module = vk.BuildShader(&vulkan, frag_bytes); + + assert(vert_module.ok && frag_module.ok, "Unable to build vulkan shaders"); + + r.GfxPipelineInfo pipeline_info = { + vertex_shader: vert_module.value, + frag_shader: frag_module.value, + }; + + auto pipeline = vk.CreateGraphicsPipeline(&vulkan, &pipeline_info); + vk.Destroy(&vulkan); } diff --git a/src/gears/vulkan.d b/src/gears/vulkan.d index 21670c8..759ae5a 100644 --- a/src/gears/vulkan.d +++ b/src/gears/vulkan.d @@ -313,17 +313,18 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info) { sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, stage: VK_SHADER_STAGE_VERTEX_BIT, - module: cast(VkShaderModule)build_info.vertex_shader, pName: "main", }, { sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, stage: VK_SHADER_STAGE_FRAGMENT_BIT, - module: cast(VkShaderModule)build_info.frag_shader, pName: "main", }, ]; + __traits(getMember, shader_info.ptr + 0, "module") = build_info.vertex_shader; + __traits(getMember, shader_info.ptr + 1, "module") = build_info.frag_shader; + VkGraphicsPipelineCreateInfo create_info = { sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, pNext: &rendering_info, @@ -341,6 +342,9 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info) }; VkPipeline pipeline; + + VkResult result = vkCreateGraphicsPipelines(vk.device, null, 1, &create_info, null, &pipeline); + assert(VkCheck("CreateGraphicsPipeline failure", result), "Unable to build pipeline"); return pipeline; } diff --git a/src/gears/vulkan_logging.d b/src/gears/vulkan_logging.d index efd5525..76a1cfc 100644 --- a/src/gears/vulkan_logging.d +++ b/src/gears/vulkan_logging.d @@ -1,6 +1,8 @@ public import includes; import std.stdio; import vulkan : Vulkan; +import std.conv; +import std.string; VkBool32 DebugCallback( @@ -56,8 +58,10 @@ DebugCallback( mt = "Unknown"; break; } + + string msg = to!string(callback_data.pMessage); - writefln("[%s: %s]\n%s\n", ms, mt, callback_data.pMessage); + writefln("[%s: %s]\n%r\n", ms, mt, msg); return VK_FALSE; } diff --git a/src/generated/assets_codegen.d b/src/generated/assets_codegen.d index e3ebbc2..eea100f 100644 --- a/src/generated/assets_codegen.d +++ b/src/generated/assets_codegen.d @@ -26,30 +26,18 @@ static immutable u64[] MODEL_HASHES = [ ]; static immutable string[] SHADER_FILES = [ - "shaders/gui.frag.spv", - "shaders/pbr.frag.spv", - "shaders/gui.vert.spv", - "shaders/quad.frag.spv", - "shaders/quad.vert.spv", - "shaders/pbr.vert.spv", + "shaders/triangle.vert.spv", + "shaders/triangle.frag.spv", ]; static immutable string[] SHADER_NAMES = [ - "shaders/gui.frag", - "shaders/pbr.frag", - "shaders/gui.vert", - "shaders/quad.frag", - "shaders/quad.vert", - "shaders/pbr.vert", + "shaders/triangle.vert", + "shaders/triangle.frag", ]; static immutable u64[] SHADER_HASHES = [ - 15780387719315455808, - 2230071466542309169, - 14797956403837654625, - 8430018914716708078, - 14432191255225961360, - 8518761701216801634, + 8769314645675479020, + 6282520872716708711, ]; static immutable string[] TEXTURE_FILES = [ diff --git a/src/packer/packer.d b/src/packer/packer.d index bf6d6c9..85e36e9 100644 --- a/src/packer/packer.d +++ b/src/packer/packer.d @@ -149,6 +149,8 @@ TestFile() u8[] data = asset.rawRead(new u8[asset.size()]); assert(data.length == info.length, "TestFile failure: File length read is incorrect"); + assert(hashes[i] == info.hash, "TestFile failure: File hash is incorrect"); + ap.seek(info.offset); u8[] pack_data = ap.rawRead(new u8[info.length]); assert(equal!((a, b) => a == b)(data[], pack_data[]), "TestFile failure: Asset data does not match file data"); diff --git a/src/shared/alloc.d b/src/shared/alloc.d index 75d3579..e051024 100644 --- a/src/shared/alloc.d +++ b/src/shared/alloc.d @@ -93,3 +93,14 @@ Free(Arena* arena) { pureFree(arena.mem); } + +void +FreeArray(T)(T[] arr) +{ + pureFree(arr.ptr); +} + +void Free(T)(T* ptr) +{ + pureFree(ptr); +} diff --git a/src/shared/assets.d b/src/shared/assets.d index ffc1985..87af0d8 100644 --- a/src/shared/assets.d +++ b/src/shared/assets.d @@ -1,6 +1,30 @@ import aliases; import std.file; -import assets_codegen; +import std.stdio; +import util; +import std.exception; +import alloc; + +version(codegen) +{ + const u64 ASSET_COUNT = 0; + + enum AssetType { None }; +} +else +{ + import assets_codegen; + + const u64 ASSET_COUNT = MODEL_FILES.length + SHADER_FILES.length + TEXTURE_FILES.length; +} + +File Asset_File; + +FileHeader Asset_Header; + +AssetInfo[ASSET_COUNT] Asset_Info; + +u8[][ASSET_COUNT] Asset_Data; const u32 FILE_VERSION = 1; @@ -36,3 +60,80 @@ struct AssetInfo u64 length; AssetType type; } + +bool +OpenAssetPack() +{ + bool success = true; + string file_path = isFile("build/assets.sgp") ? "build/assets.sgp" : "assets.sgp"; + + // TODO: replace this with something that doesn't throw an exception and figure out if this is the best way to handle thing (probably isnt) + try + { + Asset_File = File(file_path, "rb"); + } + catch (ErrnoException e) + { + success = false; + Logf("OpenAssetPack failure: Unable to open file %s", file_path); + } + + FileHeader[1] header_arr; + + Asset_File.rawRead(header_arr); + + Asset_Header = header_arr[0]; + + assert(Asset_Header.file_version == FILE_VERSION, "OpenAssetPack failure: file version incorrect"); + + Asset_File.seek(Asset_Header.asset_info_offset); + + Asset_File.rawRead(Asset_Info); + + return success; +} + +u8[] +LoadAssetData(string name) +{ + u64 hash = Hash(name); + u8[] data = null; + + foreach(i, info; Asset_Info) + { + if (info.hash == hash) + { + if (Asset_Data[i].ptr == null) + { + Asset_Data[i] = AllocArray!(u8)(info.length); + Asset_File.seek(info.offset); + Asset_File.rawRead(Asset_Data[i]); + assert(Asset_Data[i] != null && Asset_Data[i].length == info.length, "LoadAssetData failure: Asset data loaded incorrectly."); + } + + data = Asset_Data[i]; + break; + } + } + + return data; +} + +void +UnloadAssetData(string name) +{ + u64 hash = Hash(name); + + foreach(i, info; Asset_Info) + { + if (info.hash == hash) + { + if (Asset_Data[i] != null) + { + FreeArray(Asset_Data[i]); + break; + } + } + } +} +