diff --git a/src/gears/game.d b/src/gears/game.d index 5441863..dafc018 100644 --- a/src/gears/game.d +++ b/src/gears/game.d @@ -1,8 +1,8 @@ import aliases; import includes; -import renderer : Destroy; -import renderer; +import vulkan : Destroy; import vulkan; +import assets; import util; import alloc; import platform; @@ -12,9 +12,51 @@ import std.algorithm.sorting; f32 g_DELTA; +struct UIVertex +{ + Vec2 p0; + Vec2 p1; + Vec4 col; + u32 texture; +} + +struct Vertex +{ + Vec4 color; + Vec4 tangent; + Vec3 pos; + Vec3 normal; + Vec2 uv; +} + +struct MeshPart +{ + u32 mat; + u32 offset; + u32 length; +} + +struct Model +{ + Vec3 pos = Vec3(0.0); + Buffer vertex_buffer; + Buffer index_buffer; + MeshPart[] parts; + + string name; + + Buffer[] materials; + ImageView[] textures; + + Vec3[] positions; + u32[] pos_indices; + u32[] indices; +} + struct Game { Renderer rd; + Arena arena; Arena frame_arena; PlatformWindow* window; @@ -25,6 +67,10 @@ struct Game Pipeline ui_pipeline; Pipeline oit_pipeline; + UIVertex[] ui_vertex_buf; + u32[] ui_index_buf; + u32 ui_count; + ImageView draw_image, depth_image; ImageView aux_image; @@ -48,7 +94,8 @@ Game InitGame(PlatformWindow* window) { Game g = { - rd: InitRenderer(window), + rd: InitRenderer(window, MB(24), MB(32)), + arena: CreateArena(MB(32)), frame_arena: CreateArena(MB(16)), window: window, timer: CreateTimer(), @@ -59,11 +106,11 @@ InitGame(PlatformWindow* window) }, }; - Extent ext = GetExtent(&g.rd); + UVec2 ext = GetExtent(&g.rd); - CreateImageView(&g.rd, &g.draw_image, ext.w, ext.h, GetDrawImageFormat(&g.rd), IU.Draw, false); - CreateImageView(&g.rd, &g.depth_image, ext.w, ext.h, FMT.D_SF32, IU.Depth, true); - CreateImageView(&g.rd, &g.aux_image, ext.w, ext.h, FMT.R_U32, IU.Storage); + CreateImageView(&g.rd, &g.draw_image, ext.x, ext.y, GetDrawImageFormat(&g.rd), IU.Draw, false); + CreateImageView(&g.rd, &g.depth_image, ext.x, ext.y, FMT.D_SF32, IU.Depth, true); + CreateImageView(&g.rd, &g.aux_image, ext.x, ext.y, FMT.R_U32, IU.Storage); GfxPipelineInfo triangle_info = { vertex_shader: "shaders/triangle.vert.spv", @@ -113,28 +160,24 @@ InitGame(PlatformWindow* window) shader: "shaders/gradient.comp.spv", }; - g.pbr_pipeline = BuildGfxPipeline(&g.rd, &pbr_info); - g.triangle_pipeline = BuildGfxPipeline(&g.rd, &triangle_info); - g.ui_pipeline = BuildGfxPipeline(&g.rd, &ui_info); - g.oit_pipeline = BuildGfxPipeline(&g.rd, &oit_info); - g.compute_pipeline = BuildCompPipeline(&g.rd, &gradient_info); + g.pbr_pipeline = CreateGraphicsPipeline(&g.rd, &pbr_info); + g.triangle_pipeline = CreateGraphicsPipeline(&g.rd, &triangle_info); + g.ui_pipeline = CreateGraphicsPipeline(&g.rd, &ui_info); + g.oit_pipeline = CreateGraphicsPipeline(&g.rd, &oit_info); + g.compute_pipeline = CreateComputePipeline(&g.rd, &gradient_info); - PrintShader(&g.rd, &g.pbr_pipeline, VK_SHADER_STAGE_VERTEX_BIT); - - g.rock = LoadModel(&g.rd, "models/BigRock01.m3d"); - g.tree = LoadModel(&g.rd, "models/Tree01.m3d"); - g.magic_rock = LoadModel(&g.rd, "models/MagicRock01.m3d"); - g.log = LoadModel(&g.rd, "models/Log01.m3d"); - g.stump = LoadModel(&g.rd, "models/Stump01.m3d"); - - SetClearColor(&g.rd, Vec4(0.3, 0.5, 0.9, 1.0)); - - ClearColorEnabled(&g.rd, true); + g.rock = LoadModel(&g, "models/BigRock01.m3d"); + g.tree = LoadModel(&g, "models/Tree01.m3d"); + g.magic_rock = LoadModel(&g, "models/MagicRock01.m3d"); + g.log = LoadModel(&g, "models/Log01.m3d"); + g.stump = LoadModel(&g, "models/Stump01.m3d"); assert(g.aux_image.view != null); UpdateAuxImage(&g.rd, &g.aux_image); + Reset(&g.frame_arena); + return g; } @@ -221,7 +264,7 @@ Cycle(Game* g) BeginFrame(&g.rd); - PrepAuxImage(&g.rd.vk, &g.aux_image); + PrepAuxImage(&g.rd, &g.aux_image); Bind(&g.rd, &g.compute_pipeline); @@ -229,7 +272,7 @@ Cycle(Game* g) ImageBarrier(&g.rd); - Extent ext = GetExtent(&g.rd); + UVec2 ext = GetExtent(&g.rd); f32 aspect = (cast(f32)ext.x) / (cast(f32)ext.y); Mat4 projection = Perspective(90.0, aspect, 10000.0, 0.1); @@ -280,7 +323,7 @@ Cycle(Game* g) //FinishRendering(&g.rd); - Submit(&g.rd, &g.draw_image); + SubmitAndPresent(&g.rd, &g.draw_image); } pragma(inline): void @@ -320,6 +363,23 @@ Destroy(Game* g) Destroy(&g.rd); } +void +Destroy(Renderer* rd, Model* model) +{ + Destroy(rd, &model.vertex_buffer); + Destroy(rd, &model.index_buffer); + + foreach(i, mat; model.materials) + { + Destroy(rd, model.materials.ptr + i); + } + + foreach(i, view; model.textures) + { + Destroy(rd, model.textures.ptr + i); + } +} + struct Camera { Vec3 velocity = Vec3(0.0); @@ -402,3 +462,307 @@ Sort(Game* g, Vec3 pos, Model* model) UpdateIndexBuffer(&g.rd, model); } + +void +DrawRect(Game* g, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col) +{ + g.ui_vertex_buf[g.ui_count].p0.x = p0_x; + g.ui_vertex_buf[g.ui_count].p0.y = p0_y; + g.ui_vertex_buf[g.ui_count].p1.x = p1_x; + g.ui_vertex_buf[g.ui_count].p1.y = p1_y; + g.ui_vertex_buf[g.ui_count].col = col; + + u32 index_count = g.ui_count * 6; + + g.ui_index_buf[index_count+0] = index_count+0; + g.ui_index_buf[index_count+1] = index_count+1; + g.ui_index_buf[index_count+2] = index_count+2; + g.ui_index_buf[index_count+3] = index_count+1; + g.ui_index_buf[index_count+4] = index_count+2; + g.ui_index_buf[index_count+5] = index_count+3; + + g.ui_count += 1; +} + +Model +LoadModel(Game* g, string name) +{ + AssetInfo info = GetAssetInfo(name); + + u8[] data = LoadAssetData(&g.frame_arena, name); + Model model = { + name: name, + }; + + m3d_t* m3d = m3d_load(data.ptr, null, null, null); + scope(exit) m3d_free(m3d); + + u32[] tex_lookup = AllocArray!(u32)(&g.frame_arena, m3d.numtexture); + model.textures = AllocArray!(ImageView)(&g.arena, m3d.numtexture); + foreach(i; 0 .. m3d.numtexture) + { + u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f; + u8[] tex_data = m3d.texture[i].d[0 .. w * h * ch]; + + const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)]; + CreateImageView(&g.rd, &model.textures[i], w, h, ch, tex_data); + + tex_lookup[i] = Pop(&g.rd, DT.SampledImage); + } + + Material[] mats = AllocArray!(Material)(&g.frame_arena, m3d.nummaterial); + u32[] mat_lookup = AllocArray!(u32)(&g.frame_arena, m3d.nummaterial); + model.materials = AllocArray!(Buffer)(&g.arena, m3d.nummaterial); + foreach(i; 0 .. m3d.nummaterial) + { + const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)]; + + foreach(j; 0 .. m3d.material[i].numprop) + { + switch (m3d.material[i].prop[j].type) + { + case m3dp_Kd: ConvertColor(&mats[i].albedo, m3d.material[i].prop[j].value.color); break; + case m3dp_Ka: ConvertColor(&mats[i].ambient, m3d.material[i].prop[j].value.color); break; + case m3dp_Ks: ConvertColor(&mats[i].specular, m3d.material[i].prop[j].value.color); break; + case m3dp_Ns: mats[i].shininess = m3d.material[i].prop[j].value.fnum; break; + case m3dp_d: mats[i].alpha = m3d.material[i].prop[j].value.fnum; break; + case m3dp_map_Kd: + { + mats[i].albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; + mats[i].albedo_has_texture = true; + } break; + case m3dp_map_Ka: + { + mats[i].ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; + mats[i].ambient_has_texture = true; + } break; + case m3dp_map_Ks: + { + mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; + mats[i].specular_has_texture = true; + } break; + case m3dp_map_D: + { + mats[i].alpha_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; + mats[i].alpha_has_texture = true; + } break; + default: Logf("Unsupported property: %s", M3DPropToStr(m3d.material[i].prop[j].type)); break; + } + } + + CreateBuffer(&g.rd, &model.materials[i], BT.Uniform, Material.sizeof, false); + assert(Transfer(&g.rd, &model.materials[i], &mats[i]), "LoadModel failure: Transfer error when transferring material"); + + mat_lookup[i] = Pop(&g.rd, DT.Material); + } + + u32 mesh_count = 0; + u64 last = u64.max; + foreach(i; 0 .. m3d.numface) + { + if (m3d.face[i].materialid != last) + { + last = m3d.face[i].materialid; + mesh_count += 1; + } + } + + model.parts = AllocArray!(MeshPart)(&g.arena, mesh_count); + last = u64.max; + u32 index = 0; + foreach(i; 0 .. m3d.numface) + { + if (last == u64.max) + { + 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; + } + else if (m3d.face[i].materialid != last) + { + u32 vertex_index = i * 3; + + model.parts[index].length = vertex_index - model.parts[index].offset; + index += 1; + + model.parts[index].mat = mat_lookup[m3d.face[i].materialid]; + model.parts[index].offset = vertex_index; + last = m3d.face[i].materialid; + } + else if (i == m3d.numface-1) + { + u32 vertex_index = i * 3; + model.parts[index].length = vertex_index+3 - model.parts[index].offset; + } + } + + m3dv_t* vertex; + + u32[] indices = AllocArray!(u32)(&g.arena, m3d.numface * 3); + Vertex[] vertices = AllocArray!(Vertex)(&g.frame_arena, m3d.numface * 3); + Vec3[] positions = AllocArray!(Vec3)(&g.arena, m3d.numface); + u32[] pos_indices = AllocArray!(u32)(&g.arena, m3d.numface); + + foreach(i; 0 .. m3d.numface) + { + u32 vi = (i * 3); + u32 i0 = vi+0; + u32 i1 = vi+1; + u32 i2 = vi+2; + + CopyVertex(&vertices[i0].pos, &m3d.vertex[m3d.face[i].vertex[0]]); + CopyVertex(&vertices[i1].pos, &m3d.vertex[m3d.face[i].vertex[1]]); + CopyVertex(&vertices[i2].pos, &m3d.vertex[m3d.face[i].vertex[2]]); + + CopyVertex(&vertices[i0].normal, &m3d.vertex[m3d.face[i].normal[0]]); + CopyVertex(&vertices[i1].normal, &m3d.vertex[m3d.face[i].normal[1]]); + CopyVertex(&vertices[i2].normal, &m3d.vertex[m3d.face[i].normal[2]]); + + ConvertColor(&vertices[i0].color, m3d.vertex[m3d.face[i].vertex[0]].color); + ConvertColor(&vertices[i1].color, m3d.vertex[m3d.face[i].vertex[1]].color); + ConvertColor(&vertices[i2].color, m3d.vertex[m3d.face[i].vertex[2]].color); + + if (m3d.numtmap) + { + vertices[i0].uv.x = m3d.tmap[m3d.face[i].texcoord[0]].u; + vertices[i0].uv.y = m3d.tmap[m3d.face[i].texcoord[0]].v; + + vertices[i1].uv.x = m3d.tmap[m3d.face[i].texcoord[1]].u; + vertices[i1].uv.y = m3d.tmap[m3d.face[i].texcoord[1]].v; + + vertices[i2].uv.x = m3d.tmap[m3d.face[i].texcoord[2]].u; + vertices[i2].uv.y = m3d.tmap[m3d.face[i].texcoord[2]].v; + } + + indices[i0] = i0; + indices[i1] = i1; + indices[i2] = i2; + + Vec3 center = (vertices[i0].pos + vertices[i1].pos + vertices[i2].pos) / 3.0; + + positions[i] = center; + pos_indices[i] = i; + } + + for(u64 i = 0; i < indices.length; i += 3) + { + u32 i0 = indices[i+0]; + u32 i1 = indices[i+1]; + u32 i2 = indices[i+2]; + + Vec3 edge1 = vertices[i1].pos - vertices[i0].pos; + Vec3 edge2 = vertices[i2].pos - vertices[i0].pos; + + Vec2 delta_uv1 = vertices[i1].uv - vertices[i0].uv; + Vec2 delta_uv2 = vertices[i2].uv - vertices[i0].uv; + + f32 dividend = delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y; + f32 fc = 1.0 / dividend; + + Vec3 tangent = Vec3( + fc * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x), + fc * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y), + fc * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z) + ); + + Normalize(&tangent); + + f32 handedness = ((delta_uv1.y * delta_uv2.x - delta_uv2.y * delta_uv1.x) < 0.0) ? -1.0 : 1.0; + + Vec3 t = tangent * handedness; + + vertices[i0].tangent = Vec4(t, handedness); + vertices[i1].tangent = Vec4(t, handedness); + vertices[i2].tangent = Vec4(t, handedness); + } + + assert(vertices.length > 0 && indices.length > 0, "Error loading model"); + + CreateBuffer(&g.rd, &model.vertex_buffer, BT.Vertex, vertices.length * Vertex.sizeof, false); + CreateBuffer(&g.rd, &model.index_buffer, BT.Index, indices.length * u32.sizeof, false); + + assert(Transfer(&g.rd, &model.vertex_buffer, vertices), "LoadModel failure: Unable to transfer vertex buffer"); + assert(Transfer(&g.rd, &model.index_buffer, indices), "LoadModel failure: Unable to transfer index buffer"); + + WriteDescriptors(&g.rd, DT.Material, model.materials, mat_lookup); + WriteDescriptors(&g.rd, DT.SampledImage, model.textures, tex_lookup); + + model.positions = positions; + model.indices = indices; + model.pos_indices = pos_indices; + + return model; +} + +string +M3DPropToStr(u8 type) +{ + string result = "Unknown"; + switch(type) + { + case m3dp_Kd: result = "Diffuse"; break; + case m3dp_Ka: result = "Ambient"; break; + case m3dp_Ks: result = "Specular Color"; break; + case m3dp_Ns: result = "Specular Exponent"; break; + case m3dp_Ke: result = "Emissive"; break; + case m3dp_Tf: result = "Transmission"; break; + case m3dp_Km: result = "Bump Strength"; break; + case m3dp_d: result = "Alpha"; break; + case m3dp_il: result = "Illumination"; break; + case m3dp_Pr: result = "Roughness"; break; + case m3dp_Pm: result = "Metallic"; break; + case m3dp_Ps: result = "Sheen"; break; + case m3dp_Ni: result = "Refraction"; break; + case m3dp_Nt: result = "Face Thickness"; break; + case m3dp_map_Kd: result = "Diffuse Texture"; break; + case m3dp_map_Ka: result = "Ambient Texture"; break; + case m3dp_map_Ks: result = "Specular Texture"; break; + case m3dp_map_Ns: result = "Specular Exponent Texture"; break; + case m3dp_map_Ke: result = "Emissive Texture"; break; + case m3dp_map_Tf: result = "Transmission Texture"; break; + case m3dp_map_Km: result = "Bump Map"; break; + case m3dp_map_D: result = "Alpha Map"; break; + case m3dp_map_N: result = "Normal Map"; break; + case m3dp_map_Pr: result = "Roughness Map"; break; + case m3dp_map_Pm: result = "Metallic Map"; break; + case m3dp_map_Ps: result = "Sheen Map"; break; + case m3dp_map_Ni: result = "Refraction Map"; break; + case m3dp_map_Nt: result = "Thickness Map"; break; + default: break; + } + + return result; +} + +pragma(inline): void +CopyVertex(Vec3* dst, m3dv_t* src) +{ + dst.x = src.x; + dst.y = src.y; + dst.z = src.z; +} + +void +ReadModel(Game* g, string name) +{ + AssetInfo info = GetAssetInfo(name); + + u8[] data = LoadAssetData(&g.frame_arena, name); + + m3d_t* m3d = m3d_load(data.ptr, null, null, null); + + foreach(i; 0 .. m3d.numtexture) + { + const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)]; + } + + if (m3d.numtexture == 0) + { + Log("No textures in model"); + } + + foreach(i; 0 .. m3d.nummaterial) + { + const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)]; + } +} diff --git a/src/gears/renderer.d b/src/gears/renderer.d deleted file mode 100644 index 6e8ca45..0000000 --- a/src/gears/renderer.d +++ /dev/null @@ -1,766 +0,0 @@ -import aliases; -import includes; -import assets; -import util; -import alloc; -import vulkan; -import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRendering, SetUniform, PrepComputeDrawImage, Dispatch, SubmitAndPresent, BeginFrame, WaitIdle, PushConstants, BindBuffers, SetClearColor, ImageBarrier, CreateImageView, GetDrawImageFormat, FinishRendering, UpdateAuxImage, ClearColor, SubmitAndPresent; -import assets; -import std.math.traits : isNaN; -import util : Logf; -import util; -import platform; -import math; - -alias Shader = VkShaderModule; -alias Pipeline = PipelineHandle; -alias Attribute = VkVertexInputAttributeDescription; -alias SpecEntry = VkSpecializationMapEntry; - -enum InputRate : int -{ - Vertex = VK_VERTEX_INPUT_RATE_VERTEX, - Instance = VK_VERTEX_INPUT_RATE_INSTANCE, -} - -alias IR = InputRate; - -enum ImageUsage : VkImageUsageFlagBits -{ - None = cast(VkImageUsageFlagBits)0, - Draw = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - Depth = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - Texture = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - Convert = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - Storage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - Swapchain = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, -} - -alias IU = ImageUsage; - -enum Format : VkFormat -{ - UINT = VK_FORMAT_R32_UINT, - R_F32 = VK_FORMAT_R32_SFLOAT, - RG_F32 = VK_FORMAT_R32G32_SFLOAT, - RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT, - RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT, - RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT, - R_U32 = VK_FORMAT_R32_UINT, - RG_U32 = VK_FORMAT_R32G32_UINT, - RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM, - RGBA_SRGB = VK_FORMAT_R8G8B8A8_SRGB, - D_SF32 = VK_FORMAT_D32_SFLOAT, -} - -alias FMT = Format; - -enum BufferType : VkBufferUsageFlagBits -{ - None = cast(VkBufferUsageFlagBits)0, - Vertex = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - Index = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - Uniform = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - Storage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - Staging = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - BufferView = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, -} - -alias BT = BufferType; - -enum ImageLayout : VkImageLayout -{ - Undefined = VK_IMAGE_LAYOUT_UNDEFINED, - General = VK_IMAGE_LAYOUT_GENERAL, - ColorAttach = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, -} - -struct GlobalUniforms -{ - Mat4 view_matrix = Mat4Identity(); - Mat4 projection_matrix = Mat4Identity(); - Mat4 projection_view = Mat4Identity(); - Vec4 light_color; - Vec4 ambient_color; - Vec3 light_direction; - f32 padding; - Vec2 res; -} - -struct ShaderUniforms -{ - f32 placeholder; -} - -enum PipelineType : int -{ - Graphics, - Compute, -} - -alias PT = PipelineType; - -struct Specialization -{ - u64 size; - SpecEntry[] entries; - void* data; -} - -struct GfxPipelineInfo -{ - string vertex_shader; - string frag_shader; - InputRate input_rate; - u32 input_rate_stride; - Attribute[] vertex_attributes; - Specialization vert_spec; - Specialization frag_spec; - ImageView* draw_image; - ImageView* depth_image; -} - -struct CompPipelineInfo -{ - string shader; - Specialization spec; - VkPipelineLayout *layout; -} - -struct PushConst -{ - Mat4 model_matrix; - u32 mat_id; -} - -struct Extent -{ - u32 x; - u32 y; - alias x w; - alias y h; -} - -struct UIVertex -{ - Vec2 p0; - Vec2 p1; - Vec4 col; - u32 texture; -} - -struct Vertex -{ - Vec4 color; - Vec4 tangent; - Vec3 pos; - Vec3 normal; - Vec2 uv; -} - -struct MeshPart -{ - u32 mat; - u32 offset; - u32 length; -} - -struct Model -{ - Vec3 pos = Vec3(0.0); - Buffer vertex_buffer; - Buffer index_buffer; - MeshPart[] parts; - - string name; - - Buffer[] materials; - ImageView[] textures; - - Vec3[] positions; - u32[] pos_indices; - u32[] indices; -} - -struct Image -{ - VkImage image; - VmaAllocation alloc; - Format format; - VkImageLayout layout; - u32 w; - u32 h; - bool depth_image; - ImageUsage usage; -} - -struct BufferView -{ - Buffer base; - VkBufferView view; - - alias base this; -} - -struct ImageView -{ - Image base; - VkImageView view; - - alias base this; -} - -struct Buffer -{ - VkBuffer buffer; - VmaAllocation alloc; - u64 size; -} - -struct Renderer -{ - Arena arena; - Arena temp_arena; - - Vulkan vk; - PlatformWindow* window; - - UIVertex[] ui_vertex_buf; - u32[] ui_index_buf; - u32 ui_count; -} - -Renderer -InitRenderer(PlatformWindow* window) -{ - Result!(Vulkan) vk_result = Init(window, MB(24), MB(32)); - assert(vk_result.ok, "Init failure: Unable to initialize Vulkan"); - - Renderer rd = { - arena: CreateArena(MB(16)), - temp_arena: CreateArena(MB(16)), - vk: vk_result.value, - window: window, - ui_vertex_buf: GetUIVertexBuffer(&vk_result.value), - ui_index_buf: GetUIIndexBuffer(&vk_result.value), - }; - - return rd; -} - -pragma(inline): Extent -GetExtent(Renderer* rd) -{ - return Extent(rd.vk.swapchain_extent.width, rd.vk.swapchain_extent.height); -} - -pragma(inline): f32 -GetAspect(Renderer* rd) -{ - return cast(f32)(rd.vk.swapchain_extent.width) / cast(f32)(rd.vk.swapchain_extent.height); -} - -pragma(inline): void -BeginFrame(Renderer* rd) -{ - rd.ui_count = 0; - BeginFrame(&rd.vk); -} - -pragma(inline): void -DrawUI(Renderer* rd) -{ - DrawIndexed(rd, 6, rd.ui_count, 0); -} - -pragma(inline): void -Dispatch(Renderer* rd) -{ - Dispatch(&rd.vk); -} - -pragma(inline): void -PrepComputeDrawImage(Renderer* rd) -{ - PrepComputeDrawImage(&rd.vk); -} - -pragma(inline): void -SetUniform(Renderer* rd, GlobalUniforms* uniforms) -{ - SetUniform(&rd.vk, uniforms); -} - -pragma(inline): void -BeginRendering(Renderer* rd, ImageView* draw_image, ImageView* depth_image) -{ - BeginRendering(&rd.vk, draw_image, depth_image); -} - -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 -UpdateIndexBuffer(Renderer* rd, Model* model) -{ - assert(Transfer(&rd.vk, &model.index_buffer, model.indices), "UpdateIndexBuffer failure"); -} - -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): void -BindBuffers(Renderer* rd, Buffer* index_buffer, Buffer* vertex_buffer) -{ - BindBuffers(&rd.vk, index_buffer, vertex_buffer); -} - -pragma(inline): void -PushConstants(Renderer* rd, PushConst* pc) -{ - PushConstants(&rd.vk, pc); -} - -pragma(inline): Pipeline -BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) -{ - return CreateGraphicsPipeline(&rd.vk, info); -} - -pragma(inline): Pipeline -BuildCompPipeline(Renderer* rd, CompPipelineInfo* comp_info) -{ - return CreateComputePipeline(&rd.vk, comp_info); -} - -void -ReadModel(Renderer* rd, string name) -{ - AssetInfo info = GetAssetInfo(name); - - u8[] data = LoadAssetData(&rd.temp_arena, name); - - m3d_t* m3d = m3d_load(data.ptr, null, null, null); - - foreach(i; 0 .. m3d.numtexture) - { - const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)]; - } - - if (m3d.numtexture == 0) - { - Log("No textures in model"); - } - - foreach(i; 0 .. m3d.nummaterial) - { - const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)]; - } -} - -Model -LoadModel(Renderer* rd, string name) -{ - AssetInfo info = GetAssetInfo(name); - - u8[] data = LoadAssetData(&rd.temp_arena, name); - Model model = { - name: name, - }; - - m3d_t* m3d = m3d_load(data.ptr, null, null, null); - scope(exit) m3d_free(m3d); - - u32[] tex_lookup = AllocArray!(u32)(&rd.temp_arena, m3d.numtexture); - model.textures = AllocArray!(ImageView)(&rd.arena, m3d.numtexture); - foreach(i; 0 .. m3d.numtexture) - { - u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f; - u8[] tex_data = m3d.texture[i].d[0 .. w * h * ch]; - - const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)]; - CreateImageView(&rd.vk, &model.textures[i], w, h, ch, tex_data); - - tex_lookup[i] = Pop(&rd.vk, DT.SampledImage); - } - - Material[] mats = AllocArray!(Material)(&rd.temp_arena, m3d.nummaterial); - u32[] mat_lookup = AllocArray!(u32)(&rd.temp_arena, m3d.nummaterial); - model.materials = AllocArray!(Buffer)(&rd.arena, m3d.nummaterial); - foreach(i; 0 .. m3d.nummaterial) - { - const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)]; - - foreach(j; 0 .. m3d.material[i].numprop) - { - switch (m3d.material[i].prop[j].type) - { - case m3dp_Kd: ConvertColor(&mats[i].albedo, m3d.material[i].prop[j].value.color); break; - case m3dp_Ka: ConvertColor(&mats[i].ambient, m3d.material[i].prop[j].value.color); break; - case m3dp_Ks: ConvertColor(&mats[i].specular, m3d.material[i].prop[j].value.color); break; - case m3dp_Ns: mats[i].shininess = m3d.material[i].prop[j].value.fnum; break; - case m3dp_d: mats[i].alpha = m3d.material[i].prop[j].value.fnum; break; - case m3dp_map_Kd: - { - mats[i].albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; - mats[i].albedo_has_texture = true; - } break; - case m3dp_map_Ka: - { - mats[i].ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; - mats[i].ambient_has_texture = true; - } break; - case m3dp_map_Ks: - { - mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; - mats[i].specular_has_texture = true; - } break; - case m3dp_map_D: - { - mats[i].alpha_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; - mats[i].alpha_has_texture = true; - } break; - default: Logf("Unsupported property: %s", M3DPropToStr(m3d.material[i].prop[j].type)); break; - } - } - - CreateBuffer(&rd.vk, &model.materials[i], BT.Uniform, Material.sizeof, false); - assert(Transfer(&rd.vk, &model.materials[i], &mats[i]), "LoadModel failure: Transfer error when transferring material"); - - mat_lookup[i] = Pop(&rd.vk, DT.Material); - } - - u32 mesh_count = 0; - u64 last = u64.max; - foreach(i; 0 .. m3d.numface) - { - if (m3d.face[i].materialid != last) - { - last = m3d.face[i].materialid; - mesh_count += 1; - } - } - - model.parts = AllocArray!(MeshPart)(&rd.arena, mesh_count); - last = u64.max; - u32 index = 0; - foreach(i; 0 .. m3d.numface) - { - if (last == u64.max) - { - 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; - } - else if (m3d.face[i].materialid != last) - { - u32 vertex_index = i * 3; - - model.parts[index].length = vertex_index - model.parts[index].offset; - index += 1; - - model.parts[index].mat = mat_lookup[m3d.face[i].materialid]; - model.parts[index].offset = vertex_index; - last = m3d.face[i].materialid; - } - else if (i == m3d.numface-1) - { - u32 vertex_index = i * 3; - model.parts[index].length = vertex_index+3 - model.parts[index].offset; - } - } - - m3dv_t* vertex; - - u32[] indices = AllocArray!(u32)(&rd.arena, m3d.numface * 3); - Vertex[] vertices = AllocArray!(Vertex)(&rd.temp_arena, m3d.numface * 3); - Vec3[] positions = AllocArray!(Vec3)(&rd.arena, m3d.numface); - u32[] pos_indices = AllocArray!(u32)(&rd.arena, m3d.numface); - - foreach(i; 0 .. m3d.numface) - { - u32 vi = (i * 3); - u32 i0 = vi+0; - u32 i1 = vi+1; - u32 i2 = vi+2; - - CopyVertex(&vertices[i0].pos, &m3d.vertex[m3d.face[i].vertex[0]]); - CopyVertex(&vertices[i1].pos, &m3d.vertex[m3d.face[i].vertex[1]]); - CopyVertex(&vertices[i2].pos, &m3d.vertex[m3d.face[i].vertex[2]]); - - CopyVertex(&vertices[i0].normal, &m3d.vertex[m3d.face[i].normal[0]]); - CopyVertex(&vertices[i1].normal, &m3d.vertex[m3d.face[i].normal[1]]); - CopyVertex(&vertices[i2].normal, &m3d.vertex[m3d.face[i].normal[2]]); - - ConvertColor(&vertices[i0].color, m3d.vertex[m3d.face[i].vertex[0]].color); - ConvertColor(&vertices[i1].color, m3d.vertex[m3d.face[i].vertex[1]].color); - ConvertColor(&vertices[i2].color, m3d.vertex[m3d.face[i].vertex[2]].color); - - if (m3d.numtmap) - { - vertices[i0].uv.x = m3d.tmap[m3d.face[i].texcoord[0]].u; - vertices[i0].uv.y = m3d.tmap[m3d.face[i].texcoord[0]].v; - - vertices[i1].uv.x = m3d.tmap[m3d.face[i].texcoord[1]].u; - vertices[i1].uv.y = m3d.tmap[m3d.face[i].texcoord[1]].v; - - vertices[i2].uv.x = m3d.tmap[m3d.face[i].texcoord[2]].u; - vertices[i2].uv.y = m3d.tmap[m3d.face[i].texcoord[2]].v; - } - - indices[i0] = i0; - indices[i1] = i1; - indices[i2] = i2; - - Vec3 center = (vertices[i0].pos + vertices[i1].pos + vertices[i2].pos) / 3.0; - - positions[i] = center; - pos_indices[i] = i; - } - - for(u64 i = 0; i < indices.length; i += 3) - { - u32 i0 = indices[i+0]; - u32 i1 = indices[i+1]; - u32 i2 = indices[i+2]; - - Vec3 edge1 = vertices[i1].pos - vertices[i0].pos; - Vec3 edge2 = vertices[i2].pos - vertices[i0].pos; - - Vec2 delta_uv1 = vertices[i1].uv - vertices[i0].uv; - Vec2 delta_uv2 = vertices[i2].uv - vertices[i0].uv; - - f32 dividend = delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y; - f32 fc = 1.0 / dividend; - - Vec3 tangent = Vec3( - fc * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x), - fc * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y), - fc * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z) - ); - - Normalize(&tangent); - - f32 handedness = ((delta_uv1.y * delta_uv2.x - delta_uv2.y * delta_uv1.x) < 0.0) ? -1.0 : 1.0; - - Vec3 t = tangent * handedness; - - vertices[i0].tangent = Vec4(t, handedness); - vertices[i1].tangent = Vec4(t, handedness); - vertices[i2].tangent = Vec4(t, handedness); - } - - assert(vertices.length > 0 && indices.length > 0, "Error loading model"); - - CreateBuffer(&rd.vk, &model.vertex_buffer, BT.Vertex, vertices.length * Vertex.sizeof, false); - CreateBuffer(&rd.vk, &model.index_buffer, BT.Index, indices.length * u32.sizeof, false); - - assert(Transfer(&rd.vk, &model.vertex_buffer, vertices), "LoadModel failure: Unable to transfer vertex buffer"); - assert(Transfer(&rd.vk, &model.index_buffer, indices), "LoadModel failure: Unable to transfer index buffer"); - - WriteDescriptors(&rd.vk, DT.Material, model.materials, mat_lookup); - WriteDescriptors(&rd.vk, DT.SampledImage, model.textures, tex_lookup); - - model.positions = positions; - model.indices = indices; - model.pos_indices = pos_indices; - - Reset(&rd.temp_arena); - - return model; -} - -string -M3DPropToStr(u8 type) -{ - string result = "Unknown"; - switch(type) - { - case m3dp_Kd: result = "Diffuse"; break; - case m3dp_Ka: result = "Ambient"; break; - case m3dp_Ks: result = "Specular Color"; break; - case m3dp_Ns: result = "Specular Exponent"; break; - case m3dp_Ke: result = "Emissive"; break; - case m3dp_Tf: result = "Transmission"; break; - case m3dp_Km: result = "Bump Strength"; break; - case m3dp_d: result = "Alpha"; break; - case m3dp_il: result = "Illumination"; break; - case m3dp_Pr: result = "Roughness"; break; - case m3dp_Pm: result = "Metallic"; break; - case m3dp_Ps: result = "Sheen"; break; - case m3dp_Ni: result = "Refraction"; break; - case m3dp_Nt: result = "Face Thickness"; break; - case m3dp_map_Kd: result = "Diffuse Texture"; break; - case m3dp_map_Ka: result = "Ambient Texture"; break; - case m3dp_map_Ks: result = "Specular Texture"; break; - case m3dp_map_Ns: result = "Specular Exponent Texture"; break; - case m3dp_map_Ke: result = "Emissive Texture"; break; - case m3dp_map_Tf: result = "Transmission Texture"; break; - case m3dp_map_Km: result = "Bump Map"; break; - case m3dp_map_D: result = "Alpha Map"; break; - case m3dp_map_N: result = "Normal Map"; break; - case m3dp_map_Pr: result = "Roughness Map"; break; - case m3dp_map_Pm: result = "Metallic Map"; break; - case m3dp_map_Ps: result = "Sheen Map"; break; - case m3dp_map_Ni: result = "Refraction Map"; break; - case m3dp_map_Nt: result = "Thickness Map"; break; - default: break; - } - - return result; -} - -pragma(inline): void -CopyVertex(Vec3* dst, m3dv_t* src) -{ - dst.x = src.x; - dst.y = src.y; - dst.z = src.z; -} - -void -Destroy(Renderer* rd) -{ - Destroy(&rd.vk); -} - -void -Destroy(Renderer* rd, Pipeline* pipeline) -{ - Destroy(&rd.vk, pipeline); -} - -void -WaitIdle(Renderer* rd) -{ - WaitIdle(&rd.vk); -} - -void -PrintShader(Renderer* rd, Pipeline* pipeline, VkShaderStageFlagBits stage) -{ - PrintShaderDisassembly(&rd.vk, pipeline, stage); -} - -void -SetClearColor(Renderer* rd, Vec4 color) -{ - SetClearColor(&rd.vk, color); -} - -void -ClearColorEnabled(Renderer* rd, bool enabled) -{ - rd.vk.enable_clear_color = enabled; -} - -void -ImageBarrier(Renderer* rd) -{ - ImageBarrier(&rd.vk); -} - -void -CreateImageView(Renderer* rd, ImageView* view, u32 w, u32 h, Format format, ImageUsage usage, bool depth_image = false) -{ - CreateImageView(&rd.vk, view, w, h, format, usage, depth_image); -} - -Format -GetDrawImageFormat(Renderer* rd) -{ - return cast(Format)GetDrawImageFormat(&rd.vk); -} - -pragma(inline): void -ResizeDrawImageIfNeeded(Renderer* rd, ImageView* view) -{ - Extent ext = GetExtent(rd); - - if (view.w != ext.w || view.h != ext.h) - { - Destroy(view, rd.vk.device, rd.vk.vma); - CreateImageView(&rd.vk, view, ext.w, ext.h, view.format, view.usage, view.depth_image); - } -} - -void -FinishRendering(Renderer* rd) -{ - FinishRendering(&rd.vk); -} - -void -Submit(Renderer* rd, ImageView* view) -{ - SubmitAndPresent(&rd.vk, view); -} - -void -UpdateAuxImage(Renderer* rd, ImageView* view) -{ - UpdateAuxImage(&rd.vk, view); -} - -void -ClearColor(Renderer* rd, ImageView* view, Vec4 color) -{ - ClearColor(&rd.vk, view, color); -} - -void -Destroy(Renderer* rd, Model* model) -{ - Destroy(&rd.vk, &model.vertex_buffer); - Destroy(&rd.vk, &model.index_buffer); - - foreach(i, mat; model.materials) - { - Destroy(&rd.vk, model.materials.ptr + i); - } - - foreach(i, view; model.textures) - { - Destroy(model.textures.ptr + i, rd.vk.device, rd.vk.vma); - } -} diff --git a/src/gears/vulkan.d b/src/gears/vulkan.d index 717d170..8f17cd9 100644 --- a/src/gears/vulkan.d +++ b/src/gears/vulkan.d @@ -10,10 +10,13 @@ import util; import alloc; import platform; import assets; -import renderer; +import game; import std.math.rounding : Ceil = ceil; import math; +alias InitRenderer = Init; +alias Renderer = Vulkan; + bool g_VLAYER_SUPPORT = false; bool g_DEBUG_PRINTF = false; @@ -77,6 +80,163 @@ const VkFormat[] VK_IMAGE_FORMATS = [ VK_FORMAT_R8G8B8A8_UNORM, ]; +alias Shader = VkShaderModule; +alias Pipeline = PipelineHandle; +alias Attribute = VkVertexInputAttributeDescription; +alias SpecEntry = VkSpecializationMapEntry; + +enum InputRate : int +{ + Vertex = VK_VERTEX_INPUT_RATE_VERTEX, + Instance = VK_VERTEX_INPUT_RATE_INSTANCE, +} + +alias IR = InputRate; + +enum ImageUsage : VkImageUsageFlagBits +{ + None = cast(VkImageUsageFlagBits)0, + Draw = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + Depth = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + Texture = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + Convert = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + Storage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + Swapchain = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, +} + +alias IU = ImageUsage; + +enum Format : VkFormat +{ + UINT = VK_FORMAT_R32_UINT, + R_F32 = VK_FORMAT_R32_SFLOAT, + RG_F32 = VK_FORMAT_R32G32_SFLOAT, + RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT, + RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT, + RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT, + R_U32 = VK_FORMAT_R32_UINT, + RG_U32 = VK_FORMAT_R32G32_UINT, + RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM, + RGBA_SRGB = VK_FORMAT_R8G8B8A8_SRGB, + D_SF32 = VK_FORMAT_D32_SFLOAT, +} + +alias FMT = Format; + +enum BufferType : VkBufferUsageFlagBits +{ + None = cast(VkBufferUsageFlagBits)0, + Vertex = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + Index = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + Uniform = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + Storage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + Staging = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + BufferView = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, +} + +alias BT = BufferType; + +enum ImageLayout : VkImageLayout +{ + Undefined = VK_IMAGE_LAYOUT_UNDEFINED, + General = VK_IMAGE_LAYOUT_GENERAL, + ColorAttach = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, +} + +struct GlobalUniforms +{ + Mat4 view_matrix = Mat4Identity(); + Mat4 projection_matrix = Mat4Identity(); + Mat4 projection_view = Mat4Identity(); + Vec4 light_color; + Vec4 ambient_color; + Vec3 light_direction; + f32 padding; + Vec2 res; +} + +struct Image +{ + VkImage image; + VmaAllocation alloc; + Format format; + VkImageLayout layout; + u32 w; + u32 h; + bool depth_image; + ImageUsage usage; +} + +struct BufferView +{ + Buffer base; + VkBufferView view; + + alias base this; +} + +struct ImageView +{ + Image base; + VkImageView view; + + alias base this; +} + +struct Buffer +{ + VkBuffer buffer; + VmaAllocation alloc; + u64 size; +} + +struct ShaderUniforms +{ + f32 placeholder; +} + +enum PipelineType : int +{ + Graphics, + Compute, +} + +alias PT = PipelineType; + +struct Specialization +{ + u64 size; + SpecEntry[] entries; + void* data; +} + +struct GfxPipelineInfo +{ + string vertex_shader; + string frag_shader; + InputRate input_rate; + u32 input_rate_stride; + Attribute[] vertex_attributes; + Specialization vert_spec; + Specialization frag_spec; + ImageView* draw_image; + ImageView* depth_image; +} + +struct CompPipelineInfo +{ + string shader; + Specialization spec; + VkPipelineLayout *layout; +} + +struct PushConst +{ + Mat4 model_matrix; + u32 mat_id; +} + enum StepInitialized : u32 { Renderer = 1, @@ -196,9 +356,6 @@ struct Vulkan VkPipeline last_comp_pipeline; bool compute_pass_started; - bool enable_clear_color; - VkClearColorValue clear_color; - BufferView a_buffer_view; ImageView aux_image; @@ -224,7 +381,7 @@ struct QueueInfo bool single_queue; } -Result!(Vulkan) +Vulkan Init(PlatformWindow* window, u64 permanent_mem, u64 frame_mem) { bool success = true; @@ -260,17 +417,9 @@ Init(PlatformWindow* window, u64 permanent_mem, u64 frame_mem) if (success) InitBuffers(&vk); if (success) success = InitConversionPipeline(&vk); - Result!(Vulkan) result = { - ok: success, - value: vk, - }; + assert(success, "Error initializing vulkan"); - if (!success) - { - Logf("error initializing vulkan"); - } - - return result; + return vk; } bool @@ -410,6 +559,12 @@ CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visib buf.size = size; } +void +UpdateIndexBuffer(Vulkan* vk, Model* model) +{ + assert(Transfer(vk, &model.index_buffer, model.indices), "UpdateIndexBuffer failure"); +} + void InitBuffers(Vulkan* vk) { @@ -525,11 +680,8 @@ BeginRendering(Vulkan* vk, ImageView* draw_image, ImageView* depth_image) sType: VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, imageView: draw_image.view, imageLayout: draw_image.layout, - loadOp: (vk.enable_clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD), // CLEAR instead of LOAD if wanting to clear colors, also clearColor value (or whatever) + loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, // CLEAR instead of LOAD if wanting to clear colors, also clearColor value (or whatever) storeOp: VK_ATTACHMENT_STORE_OP_STORE, - clearValue: { - color: vk.clear_color, - }, }; VkRenderingAttachmentInfo depth_attach = { @@ -557,13 +709,28 @@ BeginRendering(Vulkan* vk, ImageView* draw_image, ImageView* depth_image) vkCmdBeginRendering(vk.cmds[vk.frame_index], &render_info); } -void -SetClearColor(Vulkan* vk, Vec4 color) +pragma(inline): void +ResizeDrawImageIfNeeded(Vulkan* vk, ImageView* view) { - vk.clear_color.float32[0] = color.r; - vk.clear_color.float32[1] = color.g; - vk.clear_color.float32[2] = color.b; - vk.clear_color.float32[3] = color.a; + UVec2 ext = GetExtent(vk); + + if (view.w != ext.x || view.h != ext.y) + { + Destroy(vk, view); + CreateImageView(vk, view, ext.x, ext.y, view.format, view.usage, view.depth_image); + } +} + +pragma(inline): UVec2 +GetExtent(Vulkan* vk) +{ + return UVec2(vk.swapchain_extent.width, vk.swapchain_extent.height); +} + +pragma(inline): f32 +GetAspect(Vulkan* vk) +{ + return cast(f32)(vk.swapchain_extent.width) / cast(f32)(vk.swapchain_extent.height); } void @@ -812,7 +979,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data) vkQueueWaitIdle(vk.tfer_queue); Destroy(vk, &buf); - Destroy(&conv_view, vk.device, vk.vma); + Destroy(vk, &conv_view); } } @@ -1626,7 +1793,8 @@ Destroy(Vulkan* vk) Destroy(vk.swapchain, vk.present_images, vk.device); break; case SI.DrawImages: - Destroy(&vk.draw_image, &vk.depth_image, vk.device, vk.vma); + Destroy(vk, &vk.draw_image); + Destroy(vk, &vk.depth_image); break; case SI.Descriptors: Destroy(vk.desc_pool, vk.desc_layouts, vk.pipeline_layout, vk.nearest_sampler, vk.device); @@ -2242,7 +2410,7 @@ InitFrameStructures(Vulkan* vk) return success; } -VkFormat +Format GetDrawImageFormat(Vulkan* vk) { VkFormat selected_format; @@ -2270,7 +2438,7 @@ GetDrawImageFormat(Vulkan* vk) } } - return selected_format; + return cast(Format)selected_format; } bool @@ -2414,7 +2582,8 @@ RecreateSwapchain(Vulkan* vk) vkDeviceWaitIdle(vk.device); Destroy(vk.swapchain, vk.present_images, vk.device); - Destroy(&vk.draw_image, &vk.depth_image, vk.device, vk.vma); + Destroy(vk, &vk.draw_image); + Destroy(vk, &vk.depth_image); CreateSwapchain(vk); CreateDrawImages(vk); @@ -2851,16 +3020,16 @@ Destroy(VkSwapchainKHR swapchain, ImageView[] views, VkDevice device) } void -Destroy(ImageView* view, VkDevice device, VmaAllocator vma) +Destroy(Vulkan* vk, ImageView* view) { if (view.view) { - vkDestroyImageView(device, view.view, null); + vkDestroyImageView(vk.device, view.view, null); } if (view.image) { - vmaDestroyImage(vma, view.image, view.alloc); + vmaDestroyImage(vk.vma, view.image, view.alloc); } } @@ -2891,13 +3060,6 @@ Destroy(VkDescriptorPool pool, VkDescriptorSetLayout[] layouts, VkPipelineLayout } } -void -Destroy(ImageView* draw, ImageView* depth, VkDevice device, VmaAllocator vma) -{ - Destroy(draw, device, vma); - Destroy(depth, device, vma); -} - void DestroyFS(Vulkan* vk) { diff --git a/src/shared/aliases.d b/src/shared/aliases.d index f3e7345..0582a69 100644 --- a/src/shared/aliases.d +++ b/src/shared/aliases.d @@ -35,6 +35,8 @@ alias Vec2 = Vector!(f32, 2); alias Vec3 = Vector!(f32, 3); alias Vec4 = Vector!(f32, 4); +alias UVec2 = Vector!(u32, 2); + alias Mat2 = Matrix!(f32, 2); alias Mat3 = Matrix!(f32, 3); alias Mat4 = Matrix!(f32, 4);