set up nogc
This commit is contained in:
parent
48493f91bb
commit
f601729468
Binary file not shown.
Binary file not shown.
6
dub.json
6
dub.json
@ -9,13 +9,13 @@
|
|||||||
"targetPath": "build",
|
"targetPath": "build",
|
||||||
"sourceFiles-linux": ["build/libvma.a", "build/libstb_image.a", "build/libm3d.a", "build/libcglm.a"],
|
"sourceFiles-linux": ["build/libvma.a", "build/libstb_image.a", "build/libm3d.a", "build/libcglm.a"],
|
||||||
"sourceFiles-windows": [],
|
"sourceFiles-windows": [],
|
||||||
"importPaths": ["src/gears", "src/codegen", "src/shared", "external/xxhash", "external/inteli"],
|
"importPaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli"],
|
||||||
"sourcePaths": ["src/gears", "src/codegen", "src/shared", "external/xxhash", "external/inteli"],
|
"sourcePaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli"],
|
||||||
"libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++", "xcb-xfixes", "freetype"],
|
"libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++", "xcb-xfixes", "freetype"],
|
||||||
"libs-windows": [],
|
"libs-windows": [],
|
||||||
"preGenerateCommands-linux": ["./build.sh"],
|
"preGenerateCommands-linux": ["./build.sh"],
|
||||||
"preGenerateCommands-windows": [],
|
"preGenerateCommands-windows": [],
|
||||||
"dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2"],
|
"dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-vgc"],
|
||||||
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -83,6 +83,12 @@ struct Game
|
|||||||
|
|
||||||
UIPushConst ui_pc;
|
UIPushConst ui_pc;
|
||||||
|
|
||||||
|
u8[] font_data;
|
||||||
|
FontAtlasBuf atlas_buf;
|
||||||
|
FontFace font;
|
||||||
|
|
||||||
|
Buffer temp_buffer;
|
||||||
|
|
||||||
Timer timer;
|
Timer timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +105,9 @@ InitGame(PlatformWindow* window)
|
|||||||
|
|
||||||
UVec2 ext = GetExtent(&g.rd);
|
UVec2 ext = GetExtent(&g.rd);
|
||||||
|
|
||||||
DescLayoutBinding[] layout_bindings = [
|
DescLayoutBinding[2] layout_bindings = [
|
||||||
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
];
|
];
|
||||||
|
|
||||||
g.ui_desc_layout = CreateDescSetLayout(&g.rd, layout_bindings);
|
g.ui_desc_layout = CreateDescSetLayout(&g.rd, layout_bindings);
|
||||||
@ -110,11 +117,13 @@ InitGame(PlatformWindow* window)
|
|||||||
u8[16*16*4] white_tex;
|
u8[16*16*4] white_tex;
|
||||||
white_tex[] = u8.max;
|
white_tex[] = u8.max;
|
||||||
|
|
||||||
CreateImageView(&g.rd, &g.font_tex, FONT_ATLAS_TEST.atlas.width, FONT_ATLAS_TEST.atlas.height, 4, FONT_ATLAS_TEST.data);
|
Attribute[5] attributes = [
|
||||||
// TODO: fix buffer overflow between two textures
|
{ binding: 0, location: 0, format: FMT.RG_F32, offset: UIVertex.dst_start.offsetof },
|
||||||
//CreateImageView(&g.rd, &g.default_tex, 16, 16, 4, white_tex);
|
{ binding: 0, location: 1, format: FMT.RG_F32, offset: UIVertex.dst_end.offsetof },
|
||||||
|
{ binding: 0, location: 2, format: FMT.RG_F32, offset: UIVertex.src_start.offsetof },
|
||||||
WriteGUI(&g.rd, g.ui_desc_set, &g.font_tex);
|
{ binding: 0, location: 3, format: FMT.RG_F32, offset: UIVertex.src_end.offsetof },
|
||||||
|
{ binding: 0, location: 4, format: FMT.RGBA_F32, offset: UIVertex.col.offsetof },
|
||||||
|
];
|
||||||
|
|
||||||
GfxPipelineInfo ui_info = {
|
GfxPipelineInfo ui_info = {
|
||||||
vertex_shader: "shaders/gui.vert.spv",
|
vertex_shader: "shaders/gui.vert.spv",
|
||||||
@ -122,13 +131,7 @@ InitGame(PlatformWindow* window)
|
|||||||
input_rate: IR.Instance,
|
input_rate: IR.Instance,
|
||||||
input_rate_stride: UIVertex.sizeof,
|
input_rate_stride: UIVertex.sizeof,
|
||||||
layout: g.ui_layout,
|
layout: g.ui_layout,
|
||||||
vertex_attributes: [
|
vertex_attributes: attributes,
|
||||||
{ binding: 0, location: 0, format: FMT.RG_F32, offset: UIVertex.dst_start.offsetof },
|
|
||||||
{ binding: 0, location: 1, format: FMT.RG_F32, offset: UIVertex.dst_end.offsetof },
|
|
||||||
{ binding: 0, location: 2, format: FMT.RG_F32, offset: UIVertex.src_start.offsetof },
|
|
||||||
{ binding: 0, location: 3, format: FMT.RG_F32, offset: UIVertex.src_end.offsetof },
|
|
||||||
{ binding: 0, location: 4, format: FMT.RGBA_F32, offset: UIVertex.col.offsetof },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
g.ui_pipeline = CreateGraphicsPipeline(&g.rd, &ui_info);
|
g.ui_pipeline = CreateGraphicsPipeline(&g.rd, &ui_info);
|
||||||
@ -139,7 +142,16 @@ InitGame(PlatformWindow* window)
|
|||||||
g.ui_vertex_buf = GetUIVertexBuffer(&g.rd);
|
g.ui_vertex_buf = GetUIVertexBuffer(&g.rd);
|
||||||
g.ui_index_buf = GetUIIndexBuffer(&g.rd);
|
g.ui_index_buf = GetUIIndexBuffer(&g.rd);
|
||||||
|
|
||||||
WaitForTransfers(&g.rd);
|
u8[] font_data = LoadAssetData(&g.arena, "fonts/NuberNextCondensed-DemiBold.otf");
|
||||||
|
g.font = OpenFont(font_data);
|
||||||
|
g.atlas_buf = CreateAtlas(&g.arena, g.font, 32, 256);
|
||||||
|
|
||||||
|
CreateImageView(&g.rd, &g.font_tex, g.atlas_buf.atlas.width, g.atlas_buf.atlas.height, 4, g.atlas_buf.data);
|
||||||
|
CreateImageView(&g.rd, &g.default_tex, 16, 16, 4, white_tex);
|
||||||
|
|
||||||
|
CreateBuffer(&g.rd, &g.temp_buffer, BT.Uniform, f32.sizeof*2, false, false);
|
||||||
|
|
||||||
|
WriteGUI(&g.rd, g.ui_desc_set, &g.font_tex, &g.temp_buffer);
|
||||||
|
|
||||||
Reset(&g.frame_arena);
|
Reset(&g.frame_arena);
|
||||||
|
|
||||||
@ -171,8 +183,22 @@ Cycle(Game* g)
|
|||||||
|
|
||||||
Reset(&g.frame_arena);
|
Reset(&g.frame_arena);
|
||||||
|
|
||||||
|
static bool alt = false;
|
||||||
|
if (alt)
|
||||||
|
{
|
||||||
|
f32[2] scale = [2.0, 2.0];
|
||||||
|
assert(Transfer(&g.rd, &g.temp_buffer, scale), "Cycle Transfer failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f32[2] scale = [1.0, 1.0];
|
||||||
|
assert(Transfer(&g.rd, &g.temp_buffer, scale), "Cycle Transfer failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
alt = !alt;
|
||||||
|
|
||||||
DrawRect(g, 500.0, 500.0, 800.0, 800.0, Vec4(0.2, 0.3, 0.7, 1.0));
|
DrawRect(g, 500.0, 500.0, 800.0, 800.0, Vec4(0.2, 0.3, 0.7, 1.0));
|
||||||
DrawText(g, 200.0, 200.0, 128.0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
DrawText(g, 200.0, 200.0, 16.0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
|
||||||
BeginFrame(&g.rd);
|
BeginFrame(&g.rd);
|
||||||
|
|
||||||
@ -318,10 +344,10 @@ void
|
|||||||
DrawText(Game* g, f32 x, f32 y, f32 px, string str)
|
DrawText(Game* g, f32 x, f32 y, f32 px, string str)
|
||||||
{
|
{
|
||||||
f32 x_pos = x;
|
f32 x_pos = x;
|
||||||
f32 scale = px / FONT_ATLAS_TEST.atlas.size;
|
f32 scale = px / g.atlas_buf.atlas.size;
|
||||||
foreach(ch; str)
|
foreach(ch; str)
|
||||||
{
|
{
|
||||||
foreach(glyph; FONT_ATLAS_TEST.atlas.glyphs)
|
foreach(glyph; g.atlas_buf.atlas.glyphs)
|
||||||
{
|
{
|
||||||
if (ch == glyph.ch)
|
if (ch == glyph.ch)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import util;
|
|||||||
import core.simd;
|
import core.simd;
|
||||||
import math;
|
import math;
|
||||||
import core.stdc.string : memcpy;
|
import core.stdc.string : memcpy;
|
||||||
|
import fonts;
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// 1. Determine how to better handle inputs
|
// 1. Determine how to better handle inputs
|
||||||
@ -16,11 +17,7 @@ import core.stdc.string : memcpy;
|
|||||||
|
|
||||||
void main(string[] argv)
|
void main(string[] argv)
|
||||||
{
|
{
|
||||||
Arena arena = CreateArena(MB(32));
|
|
||||||
InitFreeType();
|
InitFreeType();
|
||||||
u8[] font_data = LoadAssetData(&arena, "fonts/NuberNextCondensed-DemiBold.otf");
|
|
||||||
FontFace font = OpenFont(font_data);
|
|
||||||
FONT_ATLAS_TEST = CreateAtlas(&arena, font, 128.0, 2048);
|
|
||||||
|
|
||||||
PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
|
PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
|
||||||
Game g = InitGame(&window);
|
Game g = InitGame(&window);
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import core.memory;
|
|||||||
import core.thread.osthread;
|
import core.thread.osthread;
|
||||||
import core.time;
|
import core.time;
|
||||||
|
|
||||||
|
@nogc:
|
||||||
|
|
||||||
const WINDOW_EDGE_BUFFER = 50;
|
const WINDOW_EDGE_BUFFER = 50;
|
||||||
|
|
||||||
enum Input
|
enum Input
|
||||||
@ -40,6 +42,7 @@ alias KBI = Input;
|
|||||||
version(linux)
|
version(linux)
|
||||||
{
|
{
|
||||||
import core.sys.posix.dlfcn;
|
import core.sys.posix.dlfcn;
|
||||||
|
import core.sys.posix.sys.mman;
|
||||||
|
|
||||||
struct InputEvent
|
struct InputEvent
|
||||||
{
|
{
|
||||||
@ -130,7 +133,7 @@ CreateWindow(string name, u16 width, u16 height)
|
|||||||
XCB_EVENT_MASK_POINTER_MOTION |
|
XCB_EVENT_MASK_POINTER_MOTION |
|
||||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY;
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY;
|
||||||
|
|
||||||
i32[] val_win = [window.screen.black_pixel, event_mask];
|
i32[2] val_win = [window.screen.black_pixel, event_mask];
|
||||||
i32 val_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
i32 val_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
||||||
|
|
||||||
window.window = xcb_generate_id(window.conn);
|
window.window = xcb_generate_id(window.conn);
|
||||||
@ -599,6 +602,18 @@ case XK_g:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
MemAlloc(u64 size)
|
||||||
|
{
|
||||||
|
return mmap(null, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MemFree(void* ptr, u64 size)
|
||||||
|
{
|
||||||
|
assert(munmap(ptr, size) == 0, "MemFree failure");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
|||||||
@ -535,7 +535,7 @@ InitConversionPipeline(Vulkan* vk)
|
|||||||
{
|
{
|
||||||
Push(vk, SI.Pipelines);
|
Push(vk, SI.Pipelines);
|
||||||
|
|
||||||
VkDescriptorSetLayoutBinding[] layout_bindings = [
|
VkDescriptorSetLayoutBinding[2] layout_bindings = [
|
||||||
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT },
|
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT },
|
||||||
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT },
|
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT },
|
||||||
];
|
];
|
||||||
@ -545,19 +545,20 @@ InitConversionPipeline(Vulkan* vk)
|
|||||||
vk.conv_pipeline_layout = CreatePipelineLayout(vk, vk.conv_desc_layout, ConvPushConst.sizeof, true);
|
vk.conv_pipeline_layout = CreatePipelineLayout(vk, vk.conv_desc_layout, ConvPushConst.sizeof, true);
|
||||||
|
|
||||||
u32 channels = 1;
|
u32 channels = 1;
|
||||||
|
SpecEntry[1] entries = [
|
||||||
|
{
|
||||||
|
constantID: 0,
|
||||||
|
size: u32.sizeof,
|
||||||
|
offset: 0,
|
||||||
|
}
|
||||||
|
];
|
||||||
CompPipelineInfo conv_info = {
|
CompPipelineInfo conv_info = {
|
||||||
shader: "shaders/convert.comp.spv",
|
shader: "shaders/convert.comp.spv",
|
||||||
layout: vk.conv_pipeline_layout,
|
layout: vk.conv_pipeline_layout,
|
||||||
spec: {
|
spec: {
|
||||||
data: &channels,
|
data: &channels,
|
||||||
size: u32.sizeof,
|
size: u32.sizeof,
|
||||||
entries: [
|
entries: entries,
|
||||||
{
|
|
||||||
constantID: 0,
|
|
||||||
size: u32.sizeof,
|
|
||||||
offset: 0,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -599,11 +600,12 @@ CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visib
|
|||||||
alloc_info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
alloc_info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32[2] indices = [vk.queues.gfx_index, vk.queues.tfer_index];
|
||||||
if (vk.queues.gfx_index != vk.queues.tfer_index)
|
if (vk.queues.gfx_index != vk.queues.tfer_index)
|
||||||
{
|
{
|
||||||
buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
buffer_info.queueFamilyIndexCount = 2;
|
buffer_info.queueFamilyIndexCount = 2;
|
||||||
buffer_info.pQueueFamilyIndices = cast(const u32*)[vk.queues.gfx_index, vk.queues.tfer_index];
|
buffer_info.pQueueFamilyIndices = indices.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VmaAllocationInfo vma_info;
|
VmaAllocationInfo vma_info;
|
||||||
@ -731,7 +733,7 @@ BeginRendering(Vulkan* vk)
|
|||||||
VkImage image = CurrentImage(vk);
|
VkImage image = CurrentImage(vk);
|
||||||
Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
VkClearValue[] clear_color = [
|
VkClearValue[2] clear_color = [
|
||||||
{
|
{
|
||||||
color: {
|
color: {
|
||||||
float32: [0.0, 0.0, 0.0, 1.0],
|
float32: [0.0, 0.0, 0.0, 1.0],
|
||||||
@ -900,7 +902,7 @@ DrawIndexed(Vulkan* vk, u32 index_count, u32 instance_count, u32 index_offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ImmSubmit(Vulkan* vk, void delegate() fn)
|
ImmSubmitStart(Vulkan* vk)
|
||||||
{
|
{
|
||||||
VkResult result = vkWaitForFences(vk.device, 1, &vk.imm_fence, true, 999999999);
|
VkResult result = vkWaitForFences(vk.device, 1, &vk.imm_fence, true, 999999999);
|
||||||
bool success = VkCheck("ImmSubmit failure: vkWaitForFences error", result);
|
bool success = VkCheck("ImmSubmit failure: vkWaitForFences error", result);
|
||||||
@ -917,7 +919,6 @@ ImmSubmit(Vulkan* vk, void delegate() fn)
|
|||||||
success = VkCheck("ImmSubmit failure: vkResetCommandBuffer error", result);
|
success = VkCheck("ImmSubmit failure: vkResetCommandBuffer error", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool imm_started;
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
VkCommandBufferBeginInfo cmd_info = {
|
VkCommandBufferBeginInfo cmd_info = {
|
||||||
@ -926,37 +927,74 @@ ImmSubmit(Vulkan* vk, void delegate() fn)
|
|||||||
};
|
};
|
||||||
|
|
||||||
result = vkBeginCommandBuffer(vk.imm_cmd, &cmd_info);
|
result = vkBeginCommandBuffer(vk.imm_cmd, &cmd_info);
|
||||||
imm_started = success = VkCheck("ImmSubmit failure: vkBeginCommandBuffer error", result);
|
success = VkCheck("ImmSubmit failure: vkBeginCommandBuffer error", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ImmSubmitFinish(Vulkan* vk)
|
||||||
|
{
|
||||||
|
VkCommandBufferSubmitInfo cmd_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
|
||||||
|
commandBuffer: vk.imm_cmd,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkSubmitInfo2 submit_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
|
||||||
|
commandBufferInfoCount: 1,
|
||||||
|
pCommandBufferInfos: &cmd_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkResult result = vkQueueSubmit2(vk.tfer_queue, 1, &submit_info, vk.imm_fence);
|
||||||
|
return VkCheck("ImmSubmit failure: vkQueueSubmit2 error", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ImmSubmit(Vulkan* vk, Image* image, VkBufferImageCopy copy, void function(Vulkan*, Image*, VkBufferImageCopy) fn)
|
||||||
|
{
|
||||||
|
bool success = ImmSubmitStart(vk);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
fn();
|
fn(vk, image, copy);
|
||||||
|
|
||||||
result = vkEndCommandBuffer(vk.imm_cmd);
|
VkResult result = vkEndCommandBuffer(vk.imm_cmd);
|
||||||
success = VkCheck("ImmSubmit failure: vkEndCommandBuffer error", result);
|
success = VkCheck("ImmSubmit failure: vkEndCommandBuffer error", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
VkCommandBufferSubmitInfo cmd_info = {
|
success = ImmSubmitFinish(vk);
|
||||||
sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
|
|
||||||
commandBuffer: vk.imm_cmd,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkSubmitInfo2 submit_info = {
|
|
||||||
sType: VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
|
|
||||||
commandBufferInfoCount: 1,
|
|
||||||
pCommandBufferInfos: &cmd_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
result = vkQueueSubmit2(vk.tfer_queue, 1, &submit_info, vk.imm_fence);
|
|
||||||
success = VkCheck("ImmSubmit failure: vkQueueSubmit2 error", result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ImmSubmit(Vulkan* vk, Buffer* buf, VkBufferCopy copy, void function(Vulkan*, Buffer*, VkBufferCopy) fn)
|
||||||
|
{
|
||||||
|
bool success = ImmSubmitStart(vk);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
fn(vk, buf, copy);
|
||||||
|
|
||||||
|
VkResult result = vkEndCommandBuffer(vk.imm_cmd);
|
||||||
|
success = VkCheck("ImmSubmit failure: vkEndCommandBuffer error", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
success = ImmSubmitFinish(vk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TransferAssets(Vulkan* vk)
|
TransferAssets(Vulkan* vk)
|
||||||
{
|
{
|
||||||
@ -1120,11 +1158,12 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageU
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
u32[2] indices = [vk.gfx_index, vk.tfer_index];
|
||||||
if (vk.gfx_index != vk.tfer_index)
|
if (vk.gfx_index != vk.tfer_index)
|
||||||
{
|
{
|
||||||
image_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
image_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
image_info.queueFamilyIndexCount = 2;
|
image_info.queueFamilyIndexCount = 2;
|
||||||
image_info.pQueueFamilyIndices = cast(const u32*)[vk.gfx_index, vk.tfer_index];
|
image_info.pQueueFamilyIndices = indices.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -1225,22 +1264,24 @@ Transfer(Vulkan* vk, Buffer* buf, u8[] data)
|
|||||||
|
|
||||||
vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length];
|
vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length];
|
||||||
|
|
||||||
auto fn = delegate()
|
auto fn = function(Vulkan* vk, Buffer* buf, VkBufferCopy copy)
|
||||||
{
|
{
|
||||||
VkBufferCopy copy = {
|
|
||||||
srcOffset: 0,
|
|
||||||
dstOffset: copied,
|
|
||||||
size: copy_length,
|
|
||||||
};
|
|
||||||
|
|
||||||
vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©);
|
vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©);
|
||||||
};
|
};
|
||||||
|
|
||||||
success = ImmSubmit(vk, fn);
|
VkBufferCopy copy = {
|
||||||
|
srcOffset: 0,
|
||||||
|
dstOffset: copied,
|
||||||
|
size: copy_length,
|
||||||
|
};
|
||||||
|
|
||||||
|
success = ImmSubmit(vk, buf, copy, fn);
|
||||||
|
|
||||||
copied += copy_length;
|
copied += copy_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WaitForTransfers(vk);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1254,20 +1295,22 @@ Transfer(T)(Vulkan* vk, Buffer* buf, T* ptr)
|
|||||||
{
|
{
|
||||||
memcpy(vk.transfer_buf.data.ptr, ptr, T.sizeof);
|
memcpy(vk.transfer_buf.data.ptr, ptr, T.sizeof);
|
||||||
|
|
||||||
auto fn = delegate()
|
auto fn = function(Vulkan* vk, Buffer* buf, VkBufferCopy copy)
|
||||||
{
|
{
|
||||||
VkBufferCopy copy = {
|
|
||||||
srcOffset: 0,
|
|
||||||
dstOffset: 0,
|
|
||||||
size: T.sizeof,
|
|
||||||
};
|
|
||||||
|
|
||||||
vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©);
|
vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©);
|
||||||
};
|
};
|
||||||
|
|
||||||
success = ImmSubmit(vk, fn);
|
VkBufferCopy copy = {
|
||||||
|
srcOffset: 0,
|
||||||
|
dstOffset: 0,
|
||||||
|
size: T.sizeof,
|
||||||
|
};
|
||||||
|
|
||||||
|
success = ImmSubmit(vk, buf, copy, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WaitForTransfers(vk);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1299,23 +1342,8 @@ Transfer(Vulkan* vk, Image* image, u8[] data, u32 w, u32 h)
|
|||||||
|
|
||||||
vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length];
|
vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length];
|
||||||
|
|
||||||
auto fn = delegate()
|
auto fn = function(Vulkan* vk, Image* image, VkBufferImageCopy copy)
|
||||||
{
|
{
|
||||||
VkBufferImageCopy copy = {
|
|
||||||
bufferRowLength: w,
|
|
||||||
bufferImageHeight: h,
|
|
||||||
imageSubresource: {
|
|
||||||
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
layerCount: 1,
|
|
||||||
},
|
|
||||||
imageExtent: {
|
|
||||||
width: w,
|
|
||||||
height: h,
|
|
||||||
depth: 1,
|
|
||||||
},
|
|
||||||
bufferOffset: copied,
|
|
||||||
};
|
|
||||||
|
|
||||||
Transition(vk.imm_cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
Transition(vk.imm_cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
vkCmdCopyBufferToImage(vk.imm_cmd, vk.transfer_buf.buffer, image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
|
vkCmdCopyBufferToImage(vk.imm_cmd, vk.transfer_buf.buffer, image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
|
||||||
@ -1323,11 +1351,28 @@ Transfer(Vulkan* vk, Image* image, u8[] data, u32 w, u32 h)
|
|||||||
Transition(vk.imm_cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
Transition(vk.imm_cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
};
|
};
|
||||||
|
|
||||||
success = ImmSubmit(vk, fn);
|
VkBufferImageCopy copy = {
|
||||||
|
bufferRowLength: w,
|
||||||
|
bufferImageHeight: h,
|
||||||
|
imageSubresource: {
|
||||||
|
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
layerCount: 1,
|
||||||
|
},
|
||||||
|
imageExtent: {
|
||||||
|
width: w,
|
||||||
|
height: h,
|
||||||
|
depth: 1,
|
||||||
|
},
|
||||||
|
bufferOffset: copied,
|
||||||
|
};
|
||||||
|
|
||||||
|
success = ImmSubmit(vk, image, copy, fn);
|
||||||
|
|
||||||
copied += copy_length;
|
copied += copy_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WaitForTransfers(vk);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1577,7 +1622,7 @@ BuildShader(Vulkan* vk, u8[] bytes)
|
|||||||
void
|
void
|
||||||
InitFramebufferAndRenderPass(Vulkan* vk)
|
InitFramebufferAndRenderPass(Vulkan* vk)
|
||||||
{
|
{
|
||||||
VkAttachmentDescription[] attach_descriptions = [
|
VkAttachmentDescription[2] attach_descriptions = [
|
||||||
{
|
{
|
||||||
format: vk.draw_image.format,
|
format: vk.draw_image.format,
|
||||||
samples: VK_SAMPLE_COUNT_1_BIT,
|
samples: VK_SAMPLE_COUNT_1_BIT,
|
||||||
@ -1666,7 +1711,7 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
|||||||
pipeline.type = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
pipeline.type = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
pipeline.layout = build_info.layout;
|
pipeline.layout = build_info.layout;
|
||||||
|
|
||||||
VkDynamicState[] dyn_state = [ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR ];
|
VkDynamicState[2] dyn_state = [ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR ];
|
||||||
|
|
||||||
VkPipelineDynamicStateCreateInfo dyn_info = {
|
VkPipelineDynamicStateCreateInfo dyn_info = {
|
||||||
sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||||
@ -1753,7 +1798,7 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
|||||||
scissorCount: 1,
|
scissorCount: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo[] shader_info = [
|
VkPipelineShaderStageCreateInfo[2] shader_info = [
|
||||||
{
|
{
|
||||||
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
stage: VK_SHADER_STAGE_FRAGMENT_BIT,
|
stage: VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
@ -2047,7 +2092,7 @@ InitDescriptors(Vulkan* vk)
|
|||||||
void
|
void
|
||||||
PushDescriptorPool(Vulkan* vk)
|
PushDescriptorPool(Vulkan* vk)
|
||||||
{
|
{
|
||||||
VkDescriptorPoolSize[] pool_sizes = [
|
VkDescriptorPoolSize[7] pool_sizes = [
|
||||||
{ type: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 4096 },
|
{ type: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 4096 },
|
||||||
{ type: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 4096 },
|
{ type: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 4096 },
|
||||||
{ type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, descriptorCount: 4096 },
|
{ type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, descriptorCount: 4096 },
|
||||||
@ -2104,7 +2149,7 @@ InitGlobalDescSet(Vulkan* vk)
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
DescLayoutBinding[] layout_bindings = [
|
DescLayoutBinding[2] layout_bindings = [
|
||||||
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
];
|
];
|
||||||
@ -2135,14 +2180,20 @@ InitGlobalDescSet(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WriteGUI(Vulkan* vk, DescSet set, ImageView* atlas)
|
WriteGUI(Vulkan* vk, DescSet set, ImageView* atlas, Buffer* buf)
|
||||||
{
|
{
|
||||||
VkDescriptorImageInfo image_info = {
|
VkDescriptorImageInfo image_info = {
|
||||||
imageView: atlas.view,
|
imageView: atlas.view,
|
||||||
imageLayout: atlas.layout,
|
imageLayout: atlas.layout,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkWriteDescriptorSet[] writes = [
|
VkDescriptorBufferInfo buf_info = {
|
||||||
|
buffer: buf.buffer,
|
||||||
|
range: buf.size,
|
||||||
|
offset: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkWriteDescriptorSet[2] writes = [
|
||||||
{
|
{
|
||||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
dstSet: set.handle,
|
dstSet: set.handle,
|
||||||
@ -2150,6 +2201,14 @@ WriteGUI(Vulkan* vk, DescSet set, ImageView* atlas)
|
|||||||
descriptorCount: 1,
|
descriptorCount: 1,
|
||||||
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
pImageInfo: &image_info,
|
pImageInfo: &image_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
dstSet: set.handle,
|
||||||
|
dstBinding: 1,
|
||||||
|
descriptorCount: 1,
|
||||||
|
descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
pBufferInfo: &buf_info,
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@ public import includes;
|
|||||||
import platform;
|
import platform;
|
||||||
import vulkan : Vulkan, VULKAN_LIBS;
|
import vulkan : Vulkan, VULKAN_LIBS;
|
||||||
|
|
||||||
|
@nogc:
|
||||||
|
|
||||||
// Global Functions
|
// Global Functions
|
||||||
|
|
||||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = null;
|
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = null;
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
layout (set = 1, binding = 0) uniform texture2D SpriteAtlas;
|
layout (set = 1, binding = 0) uniform texture2D SpriteAtlas;
|
||||||
|
|
||||||
|
layout (set = 1, binding = 1) uniform Scale {
|
||||||
|
vec2 factor;
|
||||||
|
} S;
|
||||||
|
|
||||||
layout (push_constant) uniform Constants {
|
layout (push_constant) uniform Constants {
|
||||||
vec2 res;
|
vec2 res;
|
||||||
} PC;
|
} PC;
|
||||||
|
|||||||
@ -50,8 +50,8 @@ void main()
|
|||||||
FragData.color = in_col;
|
FragData.color = in_col;
|
||||||
FragData.uv = uvs[gl_VertexIndex] / tex_size;
|
FragData.uv = uvs[gl_VertexIndex] / tex_size;
|
||||||
|
|
||||||
gl_Position = vec4(2 * dst_pos.x / PC.res.x - 1,
|
gl_Position = vec4((2 * dst_pos.x / PC.res.x - 1) * S.factor.x,
|
||||||
2 * dst_pos.y / PC.res.y - 1,
|
(2 * dst_pos.y / PC.res.y - 1) * S.factor.y,
|
||||||
0,
|
0,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import math;
|
|||||||
import std.stdio;
|
import std.stdio;
|
||||||
import core.stdc.string : memset;
|
import core.stdc.string : memset;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
|
import platform;
|
||||||
|
|
||||||
const DEFAULT_ALIGNMENT = (void *).sizeof * 2;
|
const DEFAULT_ALIGNMENT = (void *).sizeof * 2;
|
||||||
|
|
||||||
@ -13,6 +14,32 @@ struct Arena
|
|||||||
u64 pos;
|
u64 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
T*
|
||||||
|
MAlloc(T)()
|
||||||
|
{
|
||||||
|
void* mem = MemAlloc(T.sizeof);
|
||||||
|
return cast(T*)mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
T[]
|
||||||
|
MAllocArray(T)(u64 count)
|
||||||
|
{
|
||||||
|
void* mem = MemAlloc(T.sizeof * count);
|
||||||
|
return cast(T*)(mem)[0 .. count];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MFree(T)(T* ptr)
|
||||||
|
{
|
||||||
|
MemFree(cast(void*)ptr, T.sizeof);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MFreeArray(T)(T[] slice)
|
||||||
|
{
|
||||||
|
MemFree(cast(void*)slice.ptr, cast(u64)slice.length);
|
||||||
|
}
|
||||||
|
|
||||||
T*
|
T*
|
||||||
Alloc(T)()
|
Alloc(T)()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
#pragma attribute(push, nogc, nothrow)
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include <xcb/xcb.h>
|
# include <xcb/xcb.h>
|
||||||
# include <xcb/xfixes.h>
|
# include <xcb/xfixes.h>
|
||||||
|
|||||||
@ -8,63 +8,38 @@ import core.simd;
|
|||||||
import std.conv;
|
import std.conv;
|
||||||
import std.string;
|
import std.string;
|
||||||
|
|
||||||
enum AtlasType
|
struct DynSlice(T)
|
||||||
{
|
{
|
||||||
None = 0,
|
T[][] slices;
|
||||||
SoftMask,
|
u32 length;
|
||||||
|
u32 capacity;
|
||||||
|
u32 grow_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum YOrigin
|
DynSlice!(T)
|
||||||
|
CreateDynSlice(T)(u32 size)
|
||||||
{
|
{
|
||||||
None = 0,
|
DynSlice!(T) dslice = {
|
||||||
Bottom,
|
slices: MAllocArray!(T[])(size),
|
||||||
|
length: 0,
|
||||||
|
capacity: size,
|
||||||
|
grow_size: size,
|
||||||
|
};
|
||||||
|
|
||||||
|
dslice.slices[0] = MAllocArray!(T)(size);
|
||||||
|
|
||||||
|
return dslice;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FontAtlas
|
u32
|
||||||
|
Next(T)(DynSlice!(T)* slice)
|
||||||
{
|
{
|
||||||
AtlasType type;
|
if (slice.length < slice.capacity)
|
||||||
f32 size;
|
{
|
||||||
u32 width;
|
|
||||||
u32 height;
|
}
|
||||||
YOrigin y_origin;
|
|
||||||
f32 em_size;
|
|
||||||
f32 line_height;
|
|
||||||
f32 ascender;
|
|
||||||
f32 descender;
|
|
||||||
f32 underline_y;
|
|
||||||
f32 underline_thickness;
|
|
||||||
Glyph[] glyphs;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Glyph
|
return 0;
|
||||||
{
|
|
||||||
dchar ch;
|
|
||||||
f32 advance;
|
|
||||||
f32 plane_left;
|
|
||||||
f32 plane_bottom;
|
|
||||||
f32 plane_right;
|
|
||||||
f32 plane_top;
|
|
||||||
f32 atlas_left;
|
|
||||||
f32 atlas_bottom;
|
|
||||||
f32 atlas_right;
|
|
||||||
f32 atlas_top;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TrackedSlice(T)
|
|
||||||
{
|
|
||||||
T[] slice;
|
|
||||||
u32 free_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
alias TSlice = TrackedSlice;
|
|
||||||
|
|
||||||
TSlice!(T)
|
|
||||||
InitTrackedSlice(T)(u32 length)
|
|
||||||
{
|
|
||||||
TSlice!(T) tslice;
|
|
||||||
tslice.slice = AllocArray!(T[])(length);
|
|
||||||
|
|
||||||
return tslice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user