added model loading
This commit is contained in:
parent
ad08d31f6a
commit
d737e1feb1
2
dub.json
2
dub.json
@ -7,7 +7,7 @@
|
|||||||
"targetType": "executable",
|
"targetType": "executable",
|
||||||
"targetName": "Gears",
|
"targetName": "Gears",
|
||||||
"targetPath": "build",
|
"targetPath": "build",
|
||||||
"sourceFiles-linux": ["build/libvma.a", "build/libstb_image.a"],
|
"sourceFiles-linux": ["build/libvma.a", "build/libstb_image.a", "build/libm3d.a"],
|
||||||
"sourceFiles-windows": [],
|
"sourceFiles-windows": [],
|
||||||
"importPaths": ["src/gears", "src/shared", "src/generated", "external/xxhash"],
|
"importPaths": ["src/gears", "src/shared", "src/generated", "external/xxhash"],
|
||||||
"sourcePaths": ["src/gears", "src/shared", "src/generated", "external/xxhash"],
|
"sourcePaths": ["src/gears", "src/shared", "src/generated", "external/xxhash"],
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import p = platform;
|
|||||||
alias Shader = VkShaderModule;
|
alias Shader = VkShaderModule;
|
||||||
alias Pipeline = PipelineHandle;
|
alias Pipeline = PipelineHandle;
|
||||||
alias Attribute = VkVertexInputAttributeDescription;
|
alias Attribute = VkVertexInputAttributeDescription;
|
||||||
alias Buffer = VkBuffer;
|
|
||||||
|
|
||||||
enum InputRate : int
|
enum InputRate : int
|
||||||
{
|
{
|
||||||
@ -78,6 +77,8 @@ struct Renderer
|
|||||||
Pipeline triangle_pipeline;
|
Pipeline triangle_pipeline;
|
||||||
Pipeline compute_pipeline;
|
Pipeline compute_pipeline;
|
||||||
Pipeline ui_pipeline;
|
Pipeline ui_pipeline;
|
||||||
|
|
||||||
|
Model yoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GlobalUniforms
|
struct GlobalUniforms
|
||||||
@ -90,6 +91,20 @@ struct ShaderUniforms
|
|||||||
f32 placeholder;
|
f32 placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Material
|
||||||
|
{
|
||||||
|
u32 albedo_texture;
|
||||||
|
u32 ambient_texture;
|
||||||
|
u32 specular_texture;
|
||||||
|
b32 albedo_has_texture;
|
||||||
|
b32 ambient_has_texture;
|
||||||
|
b32 specular_has_texture;
|
||||||
|
Vec4 ambient;
|
||||||
|
Vec4 diffuse;
|
||||||
|
Vec4 specular;
|
||||||
|
f32 shininess = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
struct UIVertex
|
struct UIVertex
|
||||||
{
|
{
|
||||||
Vec2 p0;
|
Vec2 p0;
|
||||||
@ -100,8 +115,8 @@ struct UIVertex
|
|||||||
|
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
Vec3 pos;
|
Vec4 pos;
|
||||||
Vec3 n;
|
Vec4 n;
|
||||||
Vec2 uv;
|
Vec2 uv;
|
||||||
u32 col;
|
u32 col;
|
||||||
}
|
}
|
||||||
@ -122,10 +137,7 @@ struct Model
|
|||||||
string name;
|
string name;
|
||||||
|
|
||||||
Buffer[] materials;
|
Buffer[] materials;
|
||||||
u32[] m_indices;
|
|
||||||
|
|
||||||
ImageView[] textures;
|
ImageView[] textures;
|
||||||
u32[] t_indices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer
|
Renderer
|
||||||
@ -165,6 +177,8 @@ Init(p.Window* window)
|
|||||||
rd.ui_pipeline = BuildGfxPipeline(&rd, &ui_info);
|
rd.ui_pipeline = BuildGfxPipeline(&rd, &ui_info);
|
||||||
rd.compute_pipeline = BuildCompPipeline(&rd, "shaders/gradient.comp");
|
rd.compute_pipeline = BuildCompPipeline(&rd, "shaders/gradient.comp");
|
||||||
|
|
||||||
|
rd.yoder = LoadModel(&rd, "models/yoda");
|
||||||
|
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,64 +229,216 @@ LoadModel(Renderer* rd, string name)
|
|||||||
u8[] data = LoadAssetData(&rd.temp_arena, name);
|
u8[] data = LoadAssetData(&rd.temp_arena, name);
|
||||||
m3d_t* m3d = m3d_load(data.ptr, null, null, null);
|
m3d_t* m3d = m3d_load(data.ptr, null, null, null);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
model.textures[i] = CreateImageView(&rd.vk, w, h, ch);
|
||||||
|
u8[] texture_data = m3d.texture[i].d[0 .. w * h * ch];
|
||||||
|
assert(Transfer(&rd.vk, &model.textures[i], texture_data, w, h), "LoadModel failure: Texture transfer error");
|
||||||
|
|
||||||
|
tex_lookup[i] = Pop(&rd.vk, DT.SampledImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32[] mat_lookup = AllocArray!(u32)(&rd.temp_arena, m3d.nummaterial);
|
||||||
|
model.materials = AllocArray!(Buffer)(&rd.arena, m3d.nummaterial);
|
||||||
|
foreach(i; 0 .. m3d.nummaterial)
|
||||||
|
{
|
||||||
|
Material mat;
|
||||||
|
|
||||||
|
foreach(j; 0 .. m3d.material[i].numprop)
|
||||||
|
{
|
||||||
|
switch (m3d.material[i].prop[j].type)
|
||||||
|
{
|
||||||
|
case m3dp_Ka: ConvertColor(&mat.ambient, m3d.material[i].prop[j].value.color); break;
|
||||||
|
case m3dp_Ks: ConvertColor(&mat.specular, m3d.material[i].prop[j].value.color); break;
|
||||||
|
case m3dp_Ns: mat.shininess = m3d.material[i].prop[j].value.fnum; break;
|
||||||
|
case m3dp_map_Kd:
|
||||||
|
{
|
||||||
|
mat.albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||||
|
mat.albedo_has_texture = true;
|
||||||
|
} break;
|
||||||
|
case m3dp_map_Ka:
|
||||||
|
{
|
||||||
|
mat.ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||||
|
mat.ambient_has_texture = true;
|
||||||
|
} break;
|
||||||
|
case m3dp_map_Ks:
|
||||||
|
{
|
||||||
|
mat.specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||||
|
mat.specular_has_texture = true;
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model.materials[i] = CreateBuffer(&rd.vk, BT.Uniform, Material.sizeof, false);
|
||||||
|
assert(Transfer(&rd.vk, &model.materials[i], &mat), "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 = mat_lookup[m3d.face[i].materialid];
|
||||||
|
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.temp_arena, m3d.numface * 3);
|
||||||
|
Vertex[] vertices = AllocArray!(Vertex)(&rd.temp_arena, m3d.numface * 3);
|
||||||
|
|
||||||
|
foreach(i; 0 .. m3d.numface)
|
||||||
|
{
|
||||||
|
u32 vi = (i * 3);
|
||||||
|
|
||||||
|
CopyVertex(&vertices[vi+0].pos, &m3d.vertex[m3d.face[i].vertex[0]]);
|
||||||
|
CopyVertex(&vertices[vi+1].pos, &m3d.vertex[m3d.face[i].vertex[1]]);
|
||||||
|
CopyVertex(&vertices[vi+2].pos, &m3d.vertex[m3d.face[i].vertex[2]]);
|
||||||
|
|
||||||
|
CopyVertex(&vertices[vi+0].n, &m3d.vertex[m3d.face[i].vertex[0]]);
|
||||||
|
CopyVertex(&vertices[vi+1].n, &m3d.vertex[m3d.face[i].vertex[1]]);
|
||||||
|
CopyVertex(&vertices[vi+2].n, &m3d.vertex[m3d.face[i].vertex[2]]);
|
||||||
|
|
||||||
|
vertices[vi+0].col = m3d.vertex[m3d.face[i].vertex[0]].color;
|
||||||
|
vertices[vi+1].col = m3d.vertex[m3d.face[i].vertex[1]].color;
|
||||||
|
vertices[vi+2].col = m3d.vertex[m3d.face[i].vertex[2]].color;
|
||||||
|
|
||||||
|
if (m3d.numtmap)
|
||||||
|
{
|
||||||
|
vertices[vi+0].uv.x = m3d.tmap[m3d.face[i].texcoord[0]].u;
|
||||||
|
vertices[vi+0].uv.y = m3d.tmap[m3d.face[i].texcoord[0]].v;
|
||||||
|
|
||||||
|
vertices[vi+1].uv.x = m3d.tmap[m3d.face[i].texcoord[1]].u;
|
||||||
|
vertices[vi+1].uv.y = m3d.tmap[m3d.face[i].texcoord[1]].v;
|
||||||
|
|
||||||
|
vertices[vi+2].uv.x = m3d.tmap[m3d.face[i].texcoord[2]].u;
|
||||||
|
vertices[vi+2].uv.y = m3d.tmap[m3d.face[i].texcoord[2]].v;
|
||||||
|
}
|
||||||
|
|
||||||
|
indices[vi+0] = vi+0;
|
||||||
|
indices[vi+1] = vi+1;
|
||||||
|
indices[vi+2] = vi+2;
|
||||||
|
}
|
||||||
|
|
||||||
|
model.vertex_buffer = CreateBuffer(&rd.vk, BT.Vertex, vertices.length * Vertex.sizeof, false);
|
||||||
|
model.index_buffer = CreateBuffer(&rd.vk, 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");
|
||||||
|
|
||||||
|
Reset(&rd.temp_arena);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(dst.x == src.x && dst.y == src.y && dst.z == src.z && dst.w == src.w, "CopyVertex failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): bool
|
||||||
BeginFrame(Renderer* rd)
|
BeginFrame(Renderer* rd)
|
||||||
{
|
{
|
||||||
return BeginFrame(&rd.vk);
|
return BeginFrame(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
pragma(inline): bool
|
||||||
FinishFrame(Renderer* rd)
|
FinishFrame(Renderer* rd)
|
||||||
{
|
{
|
||||||
return FinishFrame(&rd.vk);
|
return FinishFrame(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline): void
|
||||||
Dispatch(Renderer* rd)
|
Dispatch(Renderer* rd)
|
||||||
{
|
{
|
||||||
Dispatch(&rd.vk);
|
Dispatch(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline): void
|
||||||
PrepCompute(Renderer* rd)
|
PrepCompute(Renderer* rd)
|
||||||
{
|
{
|
||||||
PrepCompute(&rd.vk);
|
PrepCompute(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline): void
|
||||||
SetUniform(Renderer* rd, GlobalUniforms* uniforms)
|
SetUniform(Renderer* rd, GlobalUniforms* uniforms)
|
||||||
{
|
{
|
||||||
SetUniform(&rd.vk, uniforms);
|
SetUniform(&rd.vk, uniforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline): void
|
||||||
BeginRender(Renderer* rd)
|
BeginRender(Renderer* rd)
|
||||||
{
|
{
|
||||||
BeginRender(&rd.vk);
|
BeginRender(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline): void
|
||||||
BindUIBuffers(Renderer* rd)
|
BindUIBuffers(Renderer* rd)
|
||||||
{
|
{
|
||||||
BindUIBuffers(&rd.vk);
|
BindUIBuffers(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline): void
|
||||||
DrawIndexed(Renderer* rd, u32 index_count, u32 instance_count)
|
DrawIndexed(Renderer* rd, u32 index_count, u32 instance_count)
|
||||||
{
|
{
|
||||||
DrawIndexed(&rd.vk, index_count, instance_count);
|
DrawIndexed(&rd.vk, index_count, instance_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline): void
|
||||||
Draw(Renderer* rd, u32 index_count, u32 instance_count)
|
Draw(Renderer* rd, u32 index_count, u32 instance_count)
|
||||||
{
|
{
|
||||||
Draw(&rd.vk, index_count, instance_count);
|
Draw(&rd.vk, index_count, instance_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bind(Renderer* rd, Pipeline* pipeline)
|
pragma(inline): void
|
||||||
|
Bind(Renderer* rd, Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
Bind(&rd.vk, pipeline);
|
Bind(&rd.vk, pipeline);
|
||||||
}
|
}
|
||||||
@ -298,13 +464,13 @@ DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col)
|
|||||||
rd.ui_count += 1;
|
rd.ui_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pipeline
|
pragma(inline): Pipeline
|
||||||
BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info)
|
BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info)
|
||||||
{
|
{
|
||||||
return CreateGraphicsPipeline(&rd.vk, info);
|
return CreateGraphicsPipeline(&rd.vk, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pipeline
|
pragma(inline): Pipeline
|
||||||
BuildCompPipeline(Renderer* rd, string compute)
|
BuildCompPipeline(Renderer* rd, string compute)
|
||||||
{
|
{
|
||||||
return CreateComputePipeline(&rd.vk, compute);
|
return CreateComputePipeline(&rd.vk, compute);
|
||||||
|
|||||||
@ -3,9 +3,9 @@ import vulkan_logging;
|
|||||||
import aliases;
|
import aliases;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
import core.stdc.string : strcmp;
|
import core.stdc.string : strcmp, memcpy;
|
||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
import u = util : HashTable, Result, Logf, Log, MB;
|
import u = util : HashTable, Result, Logf, Log, MB, Delete;
|
||||||
import alloc;
|
import alloc;
|
||||||
import p = platform;
|
import p = platform;
|
||||||
import ap = assets;
|
import ap = assets;
|
||||||
@ -643,10 +643,12 @@ CreateImageView(Vulkan* vk, u32 w, u32 h, u32 ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImageView view = {
|
ImageView view = {
|
||||||
format: VK_IMAGE_LAYOUT_UNDEFINED,
|
base: {
|
||||||
|
layout: VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
VkResult result = vmaCreateImage(vk.vma, &image_info, &alloc_info, &view.image, *view.alloc, null);
|
VkResult result = vmaCreateImage(vk.vma, &image_info, &alloc_info, &view.image, &view.alloc, null);
|
||||||
// TODO: handle errors and realloc
|
// TODO: handle errors and realloc
|
||||||
assert(VkCheck("CreateImageView failure: vmaCreateImage error", result), "CreateImageView failure");
|
assert(VkCheck("CreateImageView failure: vmaCreateImage error", result), "CreateImageView failure");
|
||||||
|
|
||||||
@ -670,9 +672,66 @@ CreateImageView(Vulkan* vk, u32 w, u32 h, u32 ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32
|
u32
|
||||||
Push(Vulkan* vk, ImageView* view)
|
Pop(Vulkan* vk, DescType type)
|
||||||
{
|
{
|
||||||
|
DescBindings* bindings = vk.desc_bindings.ptr + type;
|
||||||
|
|
||||||
|
assert(bindings.count > 0, "Pop failure: no free bindings remaining");
|
||||||
|
bindings.count -= 1;
|
||||||
|
|
||||||
|
return bindings.free[bindings.count];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Push(Vulkan* vk, u32 index, DescType type)
|
||||||
|
{
|
||||||
|
DescBindings* bindings = vk.desc_bindings.ptr + type;
|
||||||
|
|
||||||
|
bindings.free[bindings.count] = index;
|
||||||
|
bindings.count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32
|
||||||
|
Pop(Vulkan* vk, string name, DescType type)
|
||||||
|
{
|
||||||
|
DescBindings* bindings = vk.desc_bindings.ptr + type;
|
||||||
|
|
||||||
|
u32 index;
|
||||||
|
auto result = bindings.lookup_table[name];
|
||||||
|
if (!result.ok)
|
||||||
|
{
|
||||||
|
// TODO: handle unbinding assets (maybe)
|
||||||
|
assert(bindings.count > 0, "Pop failure: no free bindings remaining");
|
||||||
|
bindings.count -= 1;
|
||||||
|
index = bindings.free[bindings.count];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = result.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Push(Vulkan* vk, string name, DescType type)
|
||||||
|
{
|
||||||
|
DescBindings* bindings = vk.desc_bindings.ptr + type;
|
||||||
|
auto result = Delete(&bindings.lookup_table, name);
|
||||||
|
if (result.ok)
|
||||||
|
{
|
||||||
|
assert(bindings.count < bindings.free.length, "Push failure: attempt to push a binding into a full stack");
|
||||||
|
|
||||||
|
bindings.free[bindings.count] = result.value;
|
||||||
|
bindings.count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Transfer(T)(Vulkan* vk, Buffer* buf, T[] data)
|
||||||
|
{
|
||||||
|
u8[] u8_data = (cast(u8*)(data.ptr))[0 .. T.sizeof * data.length];
|
||||||
|
return Transfer(vk, buf, u8_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -708,6 +767,33 @@ Transfer(Vulkan* vk, Buffer* buf, u8[] data)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Transfer(T)(Vulkan* vk, Buffer* buf, T* ptr)
|
||||||
|
{
|
||||||
|
assert(T.sizeof < vk.transfer_buf.data.length, "Transfer failure: structure size is too large");
|
||||||
|
|
||||||
|
memcpy(vk.transfer_buf.data.ptr, ptr, T.sizeof);
|
||||||
|
|
||||||
|
auto fn = delegate()
|
||||||
|
{
|
||||||
|
VkBufferCopy copy = {
|
||||||
|
srcOffset: 0,
|
||||||
|
dstOffset: 0,
|
||||||
|
size: T.sizeof,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©);
|
||||||
|
};
|
||||||
|
|
||||||
|
return ImmSubmit(vk, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): bool
|
||||||
|
Transfer(Vulkan* vk, ImageView* view, u8[] data, u32 w, u32 h)
|
||||||
|
{
|
||||||
|
return Transfer(vk, &view.base, data, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Transfer(Vulkan* vk, Image* image, u8[] data, u32 w, u32 h)
|
Transfer(Vulkan* vk, Image* image, u8[] data, u32 w, u32 h)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -42,6 +42,29 @@ GB(u64 v)
|
|||||||
return MB(v) * 1024;
|
return MB(v) * 1024;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
ConvertColor(Vec4 *dst, u32 src)
|
||||||
|
{
|
||||||
|
if (src == 0)
|
||||||
|
{
|
||||||
|
dst.v[] = 0.0;
|
||||||
|
dst.a = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Convert(dst, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
Convert(Vec4* dst, u32 src)
|
||||||
|
{
|
||||||
|
dst.r = cast(f32)((src >> 0) & 0xFF) / 255.0;
|
||||||
|
dst.g = cast(f32)((src >> 8) & 0xFF) / 255.0;
|
||||||
|
dst.b = cast(f32)((src >> 16) & 0xFF) / 255.0;
|
||||||
|
dst.a = cast(f32)((src >> 24) & 0xFF) / 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BitEq(u64 l, u64 r)
|
BitEq(u64 l, u64 r)
|
||||||
{
|
{
|
||||||
@ -103,6 +126,30 @@ Pop(T)(SLList!(T)*list, Node!(T)* nil)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
Remove(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* prev, Node!(T)* nil)
|
||||||
|
{
|
||||||
|
node.next = nil;
|
||||||
|
|
||||||
|
if (list.first == list.last)
|
||||||
|
{
|
||||||
|
list.first = list.last = nil;
|
||||||
|
}
|
||||||
|
else if (list.first == node)
|
||||||
|
{
|
||||||
|
list.first = node.next;
|
||||||
|
}
|
||||||
|
else if (list.last == node)
|
||||||
|
{
|
||||||
|
list.last = prev;
|
||||||
|
prev.next = nil;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev.next = node.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
PushFront(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* nil)
|
PushFront(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* nil)
|
||||||
{
|
{
|
||||||
@ -282,10 +329,7 @@ Delete(K, V)(HashTable!(K, V)* ht, K key)
|
|||||||
{
|
{
|
||||||
if (node.value.key == key)
|
if (node.value.key == key)
|
||||||
{
|
{
|
||||||
if (prev != ht.nil)
|
Remove(list, node, prev, ht.nil);
|
||||||
{
|
|
||||||
prev.next = node.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.ok = true;
|
result.ok = true;
|
||||||
result.value = node.value.value;
|
result.value = node.value.value;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user