split renderer into game and vulkan files

This commit is contained in:
matthew 2025-08-06 04:22:03 +10:00
parent 290fa0d19d
commit 31b0bb79d4
4 changed files with 594 additions and 832 deletions

View File

@ -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)];
}
}

View File

@ -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);
}
}

View File

@ -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)
{

View File

@ -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);