diff --git a/src/gears/main.d b/src/gears/main.d index 8656dd8..fd0cf98 100644 --- a/src/gears/main.d +++ b/src/gears/main.d @@ -4,6 +4,13 @@ import aliases; import core.memory; import p = platform; import r = renderer; +import util; +import core.simd; + +struct Floats +{ + f32 r = 0.0, g = 0.0, b = 0.0, a = 0.0; +} void main() { diff --git a/src/gears/renderer.d b/src/gears/renderer.d index c6887a0..d56829a 100644 --- a/src/gears/renderer.d +++ b/src/gears/renderer.d @@ -2,13 +2,15 @@ import aliases; import includes; import assets; import util; -import ap = assets; -import vk = vulkan; +import alloc; +import vulkan; +import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepCompute, Dispatch, FinishFrame, BeginFrame; +import assets; import u = util; import p = platform; alias Shader = VkShaderModule; -alias Pipeline = vk.PipelineHandle; +alias Pipeline = PipelineHandle; alias Attribute = VkVertexInputAttributeDescription; alias Buffer = VkBuffer; @@ -20,7 +22,7 @@ enum InputRate : int alias IR = InputRate; -enum Format: VkFormat +enum Format : VkFormat { UINT = VK_FORMAT_R32_UINT, R_F32 = VK_FORMAT_R32_SFLOAT, @@ -62,7 +64,10 @@ struct GfxPipelineInfo struct Renderer { - vk.Vulkan vulkan; + Arena arena; + Arena temp_arena; + + Vulkan vk; p.Window* window; GlobalUniforms globals; @@ -110,22 +115,32 @@ struct MeshPart struct Model { - Buffer vertex_buffer; - Buffer index_buffer; - MeshPart[] parts; + Buffer vertex_buffer; + Buffer index_buffer; + MeshPart[] parts; + + string name; + + Buffer[] materials; + u32[] m_indices; + + ImageView[] textures; + u32[] t_indices; } Renderer Init(p.Window* window) { - u.Result!(vk.Vulkan) vk_result = vk.Init(window, u.MB(24), u.MB(32)); + u.Result!(Vulkan) vk_result = Init(window, u.MB(24), u.MB(32)); assert(vk_result.ok, "Init failure: Unable to initialize Vulkan"); Renderer rd = { - vulkan: vk_result.value, + arena: CreateArena(u.MB(16)), + temp_arena: CreateArena(u.MB(16)), + vk: vk_result.value, window: window, - ui_vertex_buf: vk.GetUIVertexBuffer(&vk_result.value), - ui_index_buf: vk.GetUIIndexBuffer(&vk_result.value), + ui_vertex_buf: GetUIVertexBuffer(&vk_result.value), + ui_index_buf: GetUIIndexBuffer(&vk_result.value), }; GfxPipelineInfo triangle_info = { @@ -156,40 +171,112 @@ Init(p.Window* window) bool Cycle(Renderer* rd) { - bool success = vk.BeginFrame(&rd.vulkan); - rd.ui_count = 0; + bool success = BeginFrame(rd); + if (success) { - vk.Bind(&rd.vulkan, rd.compute_pipeline); + Bind(rd, &rd.compute_pipeline); - vk.SetUniform(&rd.vulkan, &rd.globals); + SetUniform(rd, &rd.globals); - DrawRect(rd, 150.0, 300.0, 200.0, 350.0, Vec4(r: 0.0, g: 0.0, b: 1.0, a: 1.0)); + DrawRect(rd, 150.0, 300.0, 500.0, 700.0, Vec4(r: 0.0, g: 0.0, b: 1.0, a: 1.0)); - vk.PrepCompute(&rd.vulkan); + PrepCompute(rd); - vk.Dispatch(&rd.vulkan); + Dispatch(rd); - vk.BeginRender(&rd.vulkan); + BeginRender(rd); - vk.Bind(&rd.vulkan, rd.ui_pipeline); + Bind(rd, &rd.ui_pipeline); - vk.BindUIBuffers(&rd.vulkan); + BindUIBuffers(rd); - vk.DrawIndexed(&rd.vulkan, 6, rd.ui_count); + DrawIndexed(rd, 6, rd.ui_count); - vk.Bind(&rd.vulkan, rd.triangle_pipeline); + Bind(rd, &rd.triangle_pipeline); - vk.Draw(&rd.vulkan, 3, 1); + Draw(rd, 3, 1); - success = vk.FinishFrame(&rd.vulkan); + success = FinishFrame(rd); } return success; } +Model +LoadModel(Renderer* rd, string name) +{ + Model model = { + name: name, + }; + + u8[] data = LoadAssetData(&rd.temp_arena, name); + m3d_t* m3d = m3d_load(data.ptr, null, null, null); + + return model; +} + +bool +BeginFrame(Renderer* rd) +{ + return BeginFrame(&rd.vk); +} + +bool +FinishFrame(Renderer* rd) +{ + return FinishFrame(&rd.vk); +} + +void +Dispatch(Renderer* rd) +{ + Dispatch(&rd.vk); +} + +void +PrepCompute(Renderer* rd) +{ + PrepCompute(&rd.vk); +} + +void +SetUniform(Renderer* rd, GlobalUniforms* uniforms) +{ + SetUniform(&rd.vk, uniforms); +} + +void +BeginRender(Renderer* rd) +{ + BeginRender(&rd.vk); +} + +void +BindUIBuffers(Renderer* rd) +{ + BindUIBuffers(&rd.vk); +} + +void +DrawIndexed(Renderer* rd, u32 index_count, u32 instance_count) +{ + DrawIndexed(&rd.vk, index_count, instance_count); +} + +void +Draw(Renderer* rd, u32 index_count, u32 instance_count) +{ + Draw(&rd.vk, index_count, instance_count); +} + +void Bind(Renderer* rd, Pipeline* pipeline) +{ + Bind(&rd.vk, pipeline); +} + void DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col) { @@ -214,21 +301,21 @@ DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col) Pipeline BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) { - return vk.CreateGraphicsPipeline(&rd.vulkan, info); + return CreateGraphicsPipeline(&rd.vk, info); } Pipeline BuildCompPipeline(Renderer* rd, string compute) { - return vk.CreateComputePipeline(&rd.vulkan, compute); + return CreateComputePipeline(&rd.vk, compute); } void Destroy(Renderer* rd) { - vk.Destroy(&rd.vulkan, rd.triangle_pipeline); - vk.Destroy(&rd.vulkan, rd.compute_pipeline); - vk.Destroy(&rd.vulkan); + Destroy(&rd.vk, rd.triangle_pipeline); + Destroy(&rd.vk, rd.compute_pipeline); + Destroy(&rd.vk); } diff --git a/src/gears/vulkan.d b/src/gears/vulkan.d index a3d34d2..42c6b71 100644 --- a/src/gears/vulkan.d +++ b/src/gears/vulkan.d @@ -6,7 +6,7 @@ import std.algorithm.comparison; import core.stdc.string : strcmp; import std.format : sformat; import u = util : HashTable, Result, Logf, Log, MB; -import a = alloc; +import alloc; import p = platform; import ap = assets; import renderer; @@ -134,8 +134,8 @@ struct DescBindings struct Vulkan { - a.Arena arena; - a.Arena[FRAME_OVERLAP] frame_arenas; + Arena arena; + Arena[FRAME_OVERLAP] frame_arenas; u32 frame_index; u32 semaphore_index; @@ -212,10 +212,10 @@ Init(p.Window* window, u64 permanent_mem, u64 frame_mem) bool success = true; Vulkan vk = { - arena: a.CreateArena(permanent_mem), + arena: CreateArena(permanent_mem), frame_arenas: [ - a.CreateArena(frame_mem), - a.CreateArena(frame_mem), + CreateArena(frame_mem), + CreateArena(frame_mem), ], window: window, }; @@ -604,9 +604,82 @@ ImmSubmit(Vulkan* vk, void delegate() fn) return success; } -void +bool +TransferAssets(Vulkan* vk) +{ + return true; +} + +ImageView +CreateImageView(Vulkan* vk, u32 w, u32 h, u32 ch) +{ + VmaAllocationCreateInfo alloc_info = { + usage: VMA_MEMORY_USAGE_GPU_ONLY, + requiredFlags: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + }; + + VkImageCreateInfo image_info = { + sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + imageType: VK_IMAGE_TYPE_2D, + mipLevels: 1, + arrayLayers: 1, + format: VK_FORMAT_R8G8B8A8_SRGB, + tiling: VK_IMAGE_TILING_OPTIMAL, + initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, + usage: VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + samples: VK_SAMPLE_COUNT_1_BIT, + extent: { + width: w, + height: h, + depth: 1, + }, + }; + + if (vk.gfx_index != vk.tfer_index) + { + image_info.sharingMode = VK_SHARING_MODE_CONCURRENT; + image_info.queueFamilyIndexCount = 2; + image_info.pQueueFamilyIndices = cast(const u32*)[vk.gfx_index, vk.tfer_index]; + } + + ImageView view = { + format: VK_IMAGE_LAYOUT_UNDEFINED, + }; + + VkResult result = vmaCreateImage(vk.vma, &image_info, &alloc_info, &view.image, *view.alloc, null); + // TODO: handle errors and realloc + assert(VkCheck("CreateImageView failure: vmaCreateImage error", result), "CreateImageView failure"); + + VkImageViewCreateInfo view_info = { + sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + image: view.image, + viewType: VK_IMAGE_VIEW_TYPE_2D, + format: VK_FORMAT_R8G8B8A8_SRGB, + subresourceRange: { + aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, + levelCount: 1, + layerCount: 1, + }, + }; + + result = vkCreateImageView(vk.device, &view_info, null, &view.view); + // TODO: also handle here + assert(VkCheck("CreateImageView failure: vkCreateImageView error", result), "CreateImageView failure"); + + return view; +} + +u32 +Push(Vulkan* vk, ImageView* view) +{ + +} + +bool Transfer(Vulkan* vk, Buffer* buf, u8[] data) { + bool success = true; + u64 copied = 0; while(copied != data.length) { @@ -627,15 +700,19 @@ Transfer(Vulkan* vk, Buffer* buf, u8[] data) vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©); }; - ImmSubmit(vk, fn); + success = ImmSubmit(vk, fn); copied += copy_length; } + + return success; } -void +bool Transfer(Vulkan* vk, Image* image, u8[] data, u32 w, u32 h) { + bool success = true; + u64 copied = 0; while(copied != data.length) { @@ -669,10 +746,12 @@ Transfer(Vulkan* vk, Image* image, u8[] data, u32 w, u32 h) Transition(vk.imm_cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); }; - ImmSubmit(vk, fn); + success = ImmSubmit(vk, fn); copied += copy_length; } + + return success; } pragma(inline): void @@ -717,7 +796,7 @@ Copy(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent } void -Bind(Vulkan* vk, PipelineHandle pipeline) +Bind(Vulkan* vk, PipelineHandle* pipeline) { vkCmdBindPipeline(vk.cmds[vk.frame_index], pipeline.type, pipeline.handle); @@ -907,14 +986,10 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info) }, ]; - u8[] vert_bytes = ap.LoadAssetData(build_info.vertex_shader); - u8[] frag_bytes = ap.LoadAssetData(build_info.frag_shader); - - scope(exit) - { - ap.UnloadAssetData(build_info.vertex_shader); - ap.UnloadAssetData(build_info.frag_shader); - } + Arena* arena = &vk.frame_arenas[0]; + + u8[] vert_bytes = ap.LoadAssetData(arena, build_info.vertex_shader); + u8[] frag_bytes = ap.LoadAssetData(arena, build_info.frag_shader); assert(vert_bytes && frag_bytes, "Unable to load shaders"); @@ -969,9 +1044,8 @@ CreateComputePipeline(Vulkan* vk, string shader) }, }; - u8[] comp_bytes = ap.LoadAssetData(shader); + u8[] comp_bytes = ap.LoadAssetData(&vk.frame_arenas[0], shader); assert(comp_bytes != null, "Unable to load compute shader data"); - scope(exit) ap.UnloadAssetData(shader); Result!(Shader) comp_module = BuildShader(vk, comp_bytes); assert(comp_module.ok, "Unable to build compute shader"); @@ -1221,7 +1295,7 @@ InitDescriptors(Vulkan* vk) vk.desc_bindings[i].lookup_table = u.CreateHashTable!(string, u32)(8); u32 DESC_MAX_BINDINGS = 512; - vk.desc_bindings[i].free = a.AllocArray!(u32)(&vk.arena, DESC_MAX_BINDINGS); + vk.desc_bindings[i].free = AllocArray!(u32)(&vk.arena, DESC_MAX_BINDINGS); u32 free_count = 0; for(i32 j = DESC_MAX_BINDINGS-1; j >= 0; j -= 1) @@ -1323,7 +1397,7 @@ InitFrameStructures(Vulkan* vk) Push(vk, SI.FrameStructures); bool success = true; - a.Arena* arena = &vk.frame_arenas[0]; + Arena* arena = &vk.frame_arenas[0]; VkSemaphoreCreateInfo sem_info = { sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; @@ -1344,7 +1418,7 @@ InitFrameStructures(Vulkan* vk) }; u32 sem_count = cast(u32)vk.present_images.length; - vk.submit_sems = a.AllocArray!(VkSemaphore)(arena, sem_count); + vk.submit_sems = AllocArray!(VkSemaphore)(arena, sem_count); foreach(i; 0 .. sem_count) { @@ -1537,16 +1611,16 @@ CreateDrawImages(Vulkan* vk) void SelectSwapchainFormats(Vulkan* vk) { - a.Arena* arena = &vk.frame_arenas[0]; + Arena* arena = &vk.frame_arenas[0]; u32 format_count; vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physical_device, vk.surface, &format_count, null); - VkSurfaceFormatKHR[] formats = a.AllocArray!(VkSurfaceFormatKHR)(arena, format_count); + VkSurfaceFormatKHR[] formats = AllocArray!(VkSurfaceFormatKHR)(arena, format_count); vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physical_device, vk.surface, &format_count, formats.ptr); u32 mode_count; vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physical_device, vk.surface, &mode_count, null); - VkPresentModeKHR[] modes = a.AllocArray!(VkPresentModeKHR)(arena, mode_count); + VkPresentModeKHR[] modes = AllocArray!(VkPresentModeKHR)(arena, mode_count); vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physical_device, vk.surface, &mode_count, modes.ptr); VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; @@ -1569,7 +1643,7 @@ CreateSwapchain(Vulkan* vk) Push(vk, SI.Swapchain); bool success = true; - a.Arena* arena = &vk.frame_arenas[0]; + Arena* arena = &vk.frame_arenas[0]; VkSurfaceCapabilitiesKHR cap; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk.physical_device, vk.surface, &cap); @@ -1604,11 +1678,11 @@ CreateSwapchain(Vulkan* vk) u32 count; vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &count, null); - VkImage[] images = a.AllocArray!(VkImage)(arena, count); + VkImage[] images = AllocArray!(VkImage)(arena, count); vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &count, images.ptr); - VkImageView[] views = a.AllocArray!(VkImageView)(arena, count); + VkImageView[] views = AllocArray!(VkImageView)(arena, count); - vk.present_images = a.AllocArray!(ImageView)(&vk.arena, count); + vk.present_images = AllocArray!(ImageView)(&vk.arena, count); VkImageViewCreateInfo view_info = { sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, @@ -1693,11 +1767,11 @@ InitDevice(Vulkan* vk) Push(vk, SI.Device); bool success = false; - a.Arena* arena = &vk.frame_arenas[0]; + Arena* arena = &vk.frame_arenas[0]; u32 count; vkEnumeratePhysicalDevices(vk.instance, &count, null); - VkPhysicalDevice[] devices = a.AllocArray!(VkPhysicalDevice)(arena, count); + VkPhysicalDevice[] devices = AllocArray!(VkPhysicalDevice)(arena, count); vkEnumeratePhysicalDevices(vk.instance, &count, devices.ptr); VkPhysicalDevice physical_device = null; @@ -1882,7 +1956,7 @@ CheckDeviceFeatures(VkPhysicalDevice device) } bool -CheckDeviceProperties(a.Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surface, b32* discrete) +CheckDeviceProperties(Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surface, b32* discrete) { bool success = false; @@ -1893,7 +1967,7 @@ CheckDeviceProperties(a.Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surf { u32 ext_count; vkEnumerateDeviceExtensionProperties(device, null, &ext_count, null); - VkExtensionProperties[] ext_props = a.AllocArray!(VkExtensionProperties)(arena, ext_count); + VkExtensionProperties[] ext_props = AllocArray!(VkExtensionProperties)(arena, ext_count); vkEnumerateDeviceExtensionProperties(device, null, &ext_count, ext_props.ptr); i32 matched = 0; @@ -1924,7 +1998,7 @@ CheckDeviceProperties(a.Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surf } QueueInfo -CheckQueueProperties(a.Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surface) +CheckQueueProperties(Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surface) { const u32 T_BIT = VK_QUEUE_TRANSFER_BIT; const u32 C_BIT = VK_QUEUE_COMPUTE_BIT; @@ -1939,7 +2013,7 @@ CheckQueueProperties(a.Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surfa u32 count; vkGetPhysicalDeviceQueueFamilyProperties(device, &count, null); - VkQueueFamilyProperties[] properties = a.AllocArray!(VkQueueFamilyProperties)(arena, count); + VkQueueFamilyProperties[] properties = AllocArray!(VkQueueFamilyProperties)(arena, count); vkGetPhysicalDeviceQueueFamilyProperties(device, &count, properties.ptr); if (count == 1 && properties[0].queueCount == 1 && u.BitEq(properties[0].queueFlags, T_BIT | C_BIT | G_BIT)) @@ -2002,7 +2076,7 @@ CheckQueueProperties(a.Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surfa pragma(inline): void Push(Vulkan* vk, StepInitialized step) { - u.Node!(SI)* node = a.Alloc!(u.Node!(SI)); + u.Node!(SI)* node = Alloc!(u.Node!(SI)); node.value = step; u.PushFront(&vk.cleanup_list, node, null); } @@ -2012,10 +2086,10 @@ DestroyRenderer(Vulkan* vk) { foreach(i, arena; vk.frame_arenas) { - a.Free(vk.frame_arenas.ptr + i); + Free(vk.frame_arenas.ptr + i); } - a.Free(&vk.arena); + Free(&vk.arena); } void @@ -2187,11 +2261,11 @@ InitInstance(Vulkan* vk) Push(vk, SI.Instance); bool success = true; - a.Arena* arena = &vk.frame_arenas[0]; + Arena* arena = &vk.frame_arenas[0]; u32 count; vkEnumerateInstanceLayerProperties(&count, null); - VkLayerProperties[] layers = a.AllocArray!(VkLayerProperties)(arena, count); + VkLayerProperties[] layers = AllocArray!(VkLayerProperties)(arena, count); vkEnumerateInstanceLayerProperties(&count, layers.ptr); foreach(i, layer; layers) diff --git a/src/shared/assets.d b/src/shared/assets.d index 8225d08..62cf7a5 100644 --- a/src/shared/assets.d +++ b/src/shared/assets.d @@ -103,13 +103,43 @@ OpenAssetPack() } } -u8[] -LoadAssetData(string name) +pragma(inline): void +CheckAssetPack() { if (!Asset_Pack_Opened) { OpenAssetPack(); } +} + +u8[] +LoadAssetData(Arena* arena, string name) +{ + CheckAssetPack(); + + u64 hash = Hash(name); + u8[] data = null; + + foreach(i, info; Asset_Info) + { + if (info.hash == hash) + { + data = AllocArray!(u8)(arena, info.length); + Asset_File.seek(info.offset); + Asset_File.rawRead(data); + assert(data != null && data.length == info.length, "LoadAssetData failure: Asset data loaded incorrectly"); + + break; + } + } + + return data; +} + +u8[] +LoadAssetData(string name) +{ + CheckAssetPack(); u64 hash = Hash(name); u8[] data = null;