diff --git a/assets/models/cube.m3d b/assets/models/cube.m3d new file mode 100644 index 0000000..a10dee6 Binary files /dev/null and b/assets/models/cube.m3d differ diff --git a/assets/shaders/gradient.comp.spv b/assets/shaders/gradient.comp.spv index 23de3cb..8a334e2 100644 Binary files a/assets/shaders/gradient.comp.spv and b/assets/shaders/gradient.comp.spv differ diff --git a/assets/shaders/gui.frag.spv b/assets/shaders/gui.frag.spv index fec021e..3b9e09f 100644 Binary files a/assets/shaders/gui.frag.spv and b/assets/shaders/gui.frag.spv differ diff --git a/assets/shaders/gui.vert.spv b/assets/shaders/gui.vert.spv index 07752bf..96f037c 100644 Binary files a/assets/shaders/gui.vert.spv and b/assets/shaders/gui.vert.spv differ diff --git a/assets/shaders/pbr.frag.spv b/assets/shaders/pbr.frag.spv new file mode 100644 index 0000000..50f1403 Binary files /dev/null and b/assets/shaders/pbr.frag.spv differ diff --git a/assets/shaders/pbr.vert.spv b/assets/shaders/pbr.vert.spv new file mode 100644 index 0000000..4733175 Binary files /dev/null and b/assets/shaders/pbr.vert.spv differ diff --git a/assets/shaders/triangle.frag.spv b/assets/shaders/triangle.frag.spv index 2bd01d0..e179e70 100644 Binary files a/assets/shaders/triangle.frag.spv and b/assets/shaders/triangle.frag.spv differ diff --git a/assets/shaders/triangle.vert.spv b/assets/shaders/triangle.vert.spv index 7f35aa6..b7669bd 100644 Binary files a/assets/shaders/triangle.vert.spv and b/assets/shaders/triangle.vert.spv differ diff --git a/src/gears/main.d b/src/gears/main.d index afc8383..c500f64 100644 --- a/src/gears/main.d +++ b/src/gears/main.d @@ -7,11 +7,6 @@ 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() { p.Window window = p.CreateWindow("Video Game", 1920, 1080); diff --git a/src/gears/renderer.d b/src/gears/renderer.d index 8e7e857..7fe0e8f 100644 --- a/src/gears/renderer.d +++ b/src/gears/renderer.d @@ -6,6 +6,7 @@ import alloc; import vulkan; import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepCompute, Dispatch, FinishFrame, BeginFrame; import assets; +import std.math.traits : isNaN; import u = util; import p = platform; @@ -28,6 +29,8 @@ enum Format : VkFormat RG_F32 = VK_FORMAT_R32G32_SFLOAT, RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT, RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT, + RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT, + RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM, } alias FMT = Format; @@ -74,6 +77,7 @@ struct Renderer u32[] ui_index_buf; u32 ui_count; + Pipeline pbr_pipeline; Pipeline triangle_pipeline; Pipeline compute_pipeline; Pipeline ui_pipeline; @@ -173,6 +177,19 @@ Init(p.Window* window) ], }; + GfxPipelineInfo pbr_info = { + vertex_shader: "shaders/pbr.vert", + frag_shader: "shaders/pbr.frag", + input_rate_stride: Vertex.sizeof, + vertex_attributes: [ + { binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 }, + { binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.n.offsetof }, + { binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.uv.offsetof }, + { binding: 0, location: 3, format: FMT.RGBA_UNORM, offset: Vertex.col.offsetof }, + ], + }; + + rd.pbr_pipeline = BuildGfxPipeline(&rd, &pbr_info); rd.triangle_pipeline = BuildGfxPipeline(&rd, &triangle_info); rd.ui_pipeline = BuildGfxPipeline(&rd, &ui_info); rd.compute_pipeline = BuildCompPipeline(&rd, "shaders/gradient.comp"); @@ -207,18 +224,144 @@ Cycle(Renderer* rd) BindUIBuffers(rd); - DrawIndexed(rd, 6, rd.ui_count); + DrawIndexed(rd, 6, rd.ui_count, 0); Bind(rd, &rd.triangle_pipeline); Draw(rd, 3, 1); + Bind(rd, &rd.pbr_pipeline); + + DrawModel(rd, &rd.yoder); + success = FinishFrame(rd); } return success; } +pragma(inline): void +DrawModel(Renderer* rd, Model* model) +{ + BindBuffers(&rd.vk, &model.index_buffer, &model.vertex_buffer); + + foreach(i, part; model.parts) + { + DrawIndexed(rd, part.length, 1, part.offset); + } +} + +pragma(inline): void +CopyVertex(Vec4* dst, m3dv_t* src) +{ + asm + { + mov R8, src; + mov R9, dst; + movups XMM0, src.x.offsetof[R8]; + movups dst.x.offsetof[R9], XMM0; + } + +debug +{ + assert(dst.x == src.x && dst.y == src.y && dst.z == src.z && dst.w == src.w, "Vertex copy failed"); + assert(!isNaN(dst.x) && !isNaN(dst.y) && !isNaN(dst.z) && !isNaN(dst.w), "Vertex contains NaN"); +} +} + +pragma(inline): bool +BeginFrame(Renderer* rd) +{ + return BeginFrame(&rd.vk); +} + +pragma(inline): bool +FinishFrame(Renderer* rd) +{ + return FinishFrame(&rd.vk); +} + +pragma(inline): void +Dispatch(Renderer* rd) +{ + Dispatch(&rd.vk); +} + +pragma(inline): void +PrepCompute(Renderer* rd) +{ + PrepCompute(&rd.vk); +} + +pragma(inline): void +SetUniform(Renderer* rd, GlobalUniforms* uniforms) +{ + SetUniform(&rd.vk, uniforms); +} + +pragma(inline): void +BeginRender(Renderer* rd) +{ + BeginRender(&rd.vk); +} + +pragma(inline): void +BindUIBuffers(Renderer* rd) +{ + BindUIBuffers(&rd.vk); +} + +pragma(inline): void +DrawIndexed(Renderer* rd, u32 index_count, u32 instance_count, u32 index_offset) +{ + DrawIndexed(&rd.vk, index_count, instance_count, index_offset); +} + +pragma(inline): void +Draw(Renderer* rd, u32 index_count, u32 instance_count) +{ + Draw(&rd.vk, index_count, instance_count); +} + +pragma(inline): 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) +{ + rd.ui_vertex_buf[rd.ui_count].p0.x = p0_x; + rd.ui_vertex_buf[rd.ui_count].p0.y = p0_y; + rd.ui_vertex_buf[rd.ui_count].p1.x = p1_x; + rd.ui_vertex_buf[rd.ui_count].p1.y = p1_y; + rd.ui_vertex_buf[rd.ui_count].col = col; + + u32 index_count = rd.ui_count * 6; + + rd.ui_index_buf[index_count+0] = index_count+0; + rd.ui_index_buf[index_count+1] = index_count+1; + rd.ui_index_buf[index_count+2] = index_count+2; + rd.ui_index_buf[index_count+3] = index_count+1; + rd.ui_index_buf[index_count+4] = index_count+2; + rd.ui_index_buf[index_count+5] = index_count+3; + + rd.ui_count += 1; +} + +pragma(inline): Pipeline +BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) +{ + return CreateGraphicsPipeline(&rd.vk, info); +} + +pragma(inline): Pipeline +BuildCompPipeline(Renderer* rd, string compute) +{ + return CreateComputePipeline(&rd.vk, compute); +} + Model LoadModel(Renderer* rd, string name) { @@ -298,7 +441,7 @@ LoadModel(Renderer* rd, string name) { if (last == u64.max) { - model.parts[index].mat = mat_lookup[m3d.face[i].materialid]; + model.parts[index].mat = m3d.face[i].materialid != u32.max ? mat_lookup[m3d.face[i].materialid] : 0; model.parts[index].offset = 0; last = m3d.face[i].materialid; } @@ -369,111 +512,6 @@ LoadModel(Renderer* rd, string name) return model; } -pragma(inline): void -CopyVertex(Vec4* dst, m3dv_t* src) -{ - asm - { - mov R8, src; - mov R9, dst; - movups XMM0, src.x.offsetof[R8]; - movups dst.x.offsetof[R9], XMM0; - } -} - -pragma(inline): bool -BeginFrame(Renderer* rd) -{ - return BeginFrame(&rd.vk); -} - -pragma(inline): bool -FinishFrame(Renderer* rd) -{ - return FinishFrame(&rd.vk); -} - -pragma(inline): void -Dispatch(Renderer* rd) -{ - Dispatch(&rd.vk); -} - -pragma(inline): void -PrepCompute(Renderer* rd) -{ - PrepCompute(&rd.vk); -} - -pragma(inline): void -SetUniform(Renderer* rd, GlobalUniforms* uniforms) -{ - SetUniform(&rd.vk, uniforms); -} - -pragma(inline): void -BeginRender(Renderer* rd) -{ - BeginRender(&rd.vk); -} - -pragma(inline): void -BindUIBuffers(Renderer* rd) -{ - BindUIBuffers(&rd.vk); -} - -pragma(inline): void -DrawIndexed(Renderer* rd, u32 index_count, u32 instance_count) -{ - DrawIndexed(&rd.vk, index_count, instance_count); -} - -pragma(inline): void -Draw(Renderer* rd, u32 index_count, u32 instance_count) -{ - Draw(&rd.vk, index_count, instance_count); -} - -pragma(inline): 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) -{ - rd.ui_vertex_buf[rd.ui_count].p0.x = p0_x; - rd.ui_vertex_buf[rd.ui_count].p0.y = p0_y; - rd.ui_vertex_buf[rd.ui_count].p1.x = p1_x; - rd.ui_vertex_buf[rd.ui_count].p1.y = p1_y; - rd.ui_vertex_buf[rd.ui_count].col = col; - - u32 index_count = rd.ui_count * 6; - - rd.ui_index_buf[index_count+0] = index_count+0; - rd.ui_index_buf[index_count+1] = index_count+1; - rd.ui_index_buf[index_count+2] = index_count+2; - rd.ui_index_buf[index_count+3] = index_count+1; - rd.ui_index_buf[index_count+4] = index_count+2; - rd.ui_index_buf[index_count+5] = index_count+3; - - rd.ui_count += 1; -} - -pragma(inline): Pipeline -BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) -{ - return CreateGraphicsPipeline(&rd.vk, info); -} - -pragma(inline): Pipeline -BuildCompPipeline(Renderer* rd, string compute) -{ - return CreateComputePipeline(&rd.vk, compute); -} - void Destroy(Renderer* rd) { diff --git a/src/gears/vulkan.d b/src/gears/vulkan.d index 745476c..3ab09cf 100644 --- a/src/gears/vulkan.d +++ b/src/gears/vulkan.d @@ -316,6 +316,15 @@ BindUIBuffers(Vulkan* vk) vkCmdBindVertexBuffers(vk.cmds[vk.frame_index], 0, 1, &vk.ui_vert_buf.buffer, &offset); } +void +BindBuffers(Vulkan* vk, Buffer* index_buffer, Buffer* vertex_buffer) +{ + VkDeviceSize offset = 0; + + vkCmdBindIndexBuffer(vk.cmds[vk.frame_index], index_buffer.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindVertexBuffers(vk.cmds[vk.frame_index], 0, 1, &vertex_buffer.buffer, &offset); +} + MappedBuffer!(T) CreateMappedBuffer(T)(Vulkan* vk, BufferType type, u64 count) { @@ -541,9 +550,9 @@ Draw(Vulkan* vk, u32 index_count, u32 instance_count) } void -DrawIndexed(Vulkan* vk, u32 index_count, u32 instance_count) +DrawIndexed(Vulkan* vk, u32 index_count, u32 instance_count, u32 index_offset) { - vkCmdDrawIndexed(vk.cmds[vk.frame_index], index_count, instance_count, 0, 0, 0); + vkCmdDrawIndexed(vk.cmds[vk.frame_index], index_count, instance_count, index_offset, 0, 0); } bool diff --git a/src/generated/assets_codegen.d b/src/generated/assets_codegen.d index 5469113..b3f00e5 100644 --- a/src/generated/assets_codegen.d +++ b/src/generated/assets_codegen.d @@ -11,16 +11,19 @@ enum AssetType : u32 alias AT = AssetType; static immutable string[] MODEL_FILES = [ + "models/cube.m3d", "models/test_char.m3d", "models/yoda.m3d", ]; static immutable string[] MODEL_NAMES = [ + "models/cube", "models/test_char", "models/yoda", ]; static immutable u64[] MODEL_HASHES = [ + 16487010975852376380, 13826959199295087925, 4559395153940738542, ]; @@ -28,25 +31,31 @@ static immutable u64[] MODEL_HASHES = [ static immutable string[] SHADER_FILES = [ "shaders/gui.frag.spv", "shaders/triangle.vert.spv", + "shaders/pbr.frag.spv", "shaders/gui.vert.spv", "shaders/gradient.comp.spv", "shaders/triangle.frag.spv", + "shaders/pbr.vert.spv", ]; static immutable string[] SHADER_NAMES = [ "shaders/gui.frag", "shaders/triangle.vert", + "shaders/pbr.frag", "shaders/gui.vert", "shaders/gradient.comp", "shaders/triangle.frag", + "shaders/pbr.vert", ]; static immutable u64[] SHADER_HASHES = [ 15780387719315455808, 8769314645675479020, + 2230071466542309169, 14797956403837654625, 16130483095684998267, 6282520872716708711, + 8518761701216801634, ]; static immutable string[] TEXTURE_FILES = [ diff --git a/src/shaders/gradient.comp.glsl b/src/shaders/gradient.comp.glsl index ce38a5b..8fd4a55 100644 --- a/src/shaders/gradient.comp.glsl +++ b/src/shaders/gradient.comp.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #include "structures.layout" diff --git a/src/shaders/gui.frag.glsl b/src/shaders/gui.frag.glsl index 500f07f..5907081 100644 --- a/src/shaders/gui.frag.glsl +++ b/src/shaders/gui.frag.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require diff --git a/src/shaders/gui.vert.glsl b/src/shaders/gui.vert.glsl index 6e4c839..8a1828b 100644 --- a/src/shaders/gui.vert.glsl +++ b/src/shaders/gui.vert.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require diff --git a/src/shaders/pbr.frag.glsl b/src/shaders/pbr.frag.glsl new file mode 100644 index 0000000..776ab70 --- /dev/null +++ b/src/shaders/pbr.frag.glsl @@ -0,0 +1,16 @@ +#version 460 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_nonuniform_qualifier : require + +#include "structures.layout" + +layout (location = 0) in vec4 in_col; +layout (location = 1) in vec2 in_uv; + +layout (location = 0) out vec4 FragColor; + +void main() +{ + FragColor = in_col; +} diff --git a/src/shaders/pbr.vert.glsl b/src/shaders/pbr.vert.glsl new file mode 100644 index 0000000..ea0519a --- /dev/null +++ b/src/shaders/pbr.vert.glsl @@ -0,0 +1,20 @@ +#version 460 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_nonuniform_qualifier : require + +#include "structures.layout" + +layout (location = 0) in vec4 in_pos; +layout (location = 1) in vec4 in_normal; +layout (location = 2) in vec2 in_uv; +layout (location = 3) in vec4 in_col; + +layout (location = 0) out vec4 out_col; +layout (location = 1) out vec2 out_uv; + +void main() +{ + gl_Position = in_pos; + out_col = in_col; +} diff --git a/src/shaders/triangle.frag.glsl b/src/shaders/triangle.frag.glsl index e752f65..99b6836 100644 --- a/src/shaders/triangle.frag.glsl +++ b/src/shaders/triangle.frag.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require diff --git a/src/shaders/triangle.vert.glsl b/src/shaders/triangle.vert.glsl index cc359d2..d7372ae 100644 --- a/src/shaders/triangle.vert.glsl +++ b/src/shaders/triangle.vert.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require