triangle drawn
This commit is contained in:
parent
9c5ad29f78
commit
42bef67206
3
dub.json
3
dub.json
@ -13,7 +13,7 @@
|
|||||||
"sourcePaths": ["src/gears", "src/shared", "src/generated", "external/xxhash"],
|
"sourcePaths": ["src/gears", "src/shared", "src/generated", "external/xxhash"],
|
||||||
"libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++"],
|
"libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++"],
|
||||||
"libs-windows": [],
|
"libs-windows": [],
|
||||||
"preGenerateCommands-linux": ["./build-vma.sh", "build/Codegen", "dub main:packer", "build/Packer"],
|
"preGenerateCommands-linux": ["./build-vma.sh", "build/Codegen", "dub main:packer"],
|
||||||
"preGenerateCommands-windows": [],
|
"preGenerateCommands-windows": [],
|
||||||
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
||||||
},
|
},
|
||||||
@ -26,6 +26,7 @@
|
|||||||
"sourcePaths": ["src/packer", "src/shared", "src/generated", "external/xxhash"],
|
"sourcePaths": ["src/packer", "src/shared", "src/generated", "external/xxhash"],
|
||||||
"sourceFiles-linux": ["build/libstb_image.a", "build/libm3d.a"],
|
"sourceFiles-linux": ["build/libstb_image.a", "build/libm3d.a"],
|
||||||
"preGenerateCommands-linux": ["./build-vma.sh"],
|
"preGenerateCommands-linux": ["./build-vma.sh"],
|
||||||
|
"postGenerateCommands-linux": ["build/Packer"],
|
||||||
"preGenerateCommands-windows": [],
|
"preGenerateCommands-windows": [],
|
||||||
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"],
|
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,54 +2,19 @@ public import includes;
|
|||||||
import std.stdio;
|
import std.stdio;
|
||||||
import aliases;
|
import aliases;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
import u = util : Result;
|
|
||||||
import p = platform;
|
import p = platform;
|
||||||
import a = alloc;
|
|
||||||
import vk = vulkan : Vulkan;
|
|
||||||
import ap = assets;
|
|
||||||
import r = renderer;
|
import r = renderer;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
p.Window window = p.CreateWindow("Video Game", 1920, 1080);
|
p.Window window = p.CreateWindow("Video Game", 1920, 1080);
|
||||||
|
|
||||||
assert(ap.OpenAssetPack(), "OpenAssetPack failure");
|
r.Renderer rd = r.Init(&window);
|
||||||
|
scope(exit) r.Destroy(&rd);
|
||||||
|
|
||||||
Result!(Vulkan) result = vk.Init(&window, u.MB(24), u.MB(32));
|
while (true)
|
||||||
Vulkan vulkan = result.value;
|
{
|
||||||
|
r.Cycle(&rd);
|
||||||
u8[] vert_bytes = ap.LoadAssetData("shaders/triangle.vert");
|
}
|
||||||
u8[] frag_bytes = ap.LoadAssetData("shaders/triangle.frag");
|
|
||||||
|
|
||||||
assert(vert_bytes != null && frag_bytes != null, "Unable to load shader data");
|
|
||||||
|
|
||||||
auto vert_module = vk.BuildShader(&vulkan, vert_bytes);
|
|
||||||
auto frag_module = vk.BuildShader(&vulkan, frag_bytes);
|
|
||||||
|
|
||||||
assert(vert_module.ok && frag_module.ok, "Unable to build vulkan shaders");
|
|
||||||
|
|
||||||
r.GfxPipelineInfo pipeline_info = {
|
|
||||||
vertex_shader: vert_module.value,
|
|
||||||
frag_shader: frag_module.value,
|
|
||||||
};
|
|
||||||
|
|
||||||
auto pipeline = vk.CreateGraphicsPipeline(&vulkan, &pipeline_info);
|
|
||||||
|
|
||||||
u8[] comp_bytes = ap.LoadAssetData("shaders/gradient.comp");
|
|
||||||
assert(comp_bytes != null, "Unable to load compute shader data");
|
|
||||||
|
|
||||||
auto comp_module = vk.BuildShader(&vulkan, comp_bytes);
|
|
||||||
assert(comp_module.ok, "Unable to build compute shader");
|
|
||||||
|
|
||||||
auto comp_pipeline = vk.CreateComputePipeline(&vulkan, comp_module.value);
|
|
||||||
|
|
||||||
vk.Destroy(&vulkan, comp_module.value);
|
|
||||||
vk.Destroy(&vulkan, comp_pipeline);
|
|
||||||
|
|
||||||
vk.Destroy(&vulkan, vert_module.value);
|
|
||||||
vk.Destroy(&vulkan, frag_module.value);
|
|
||||||
vk.Destroy(&vulkan, pipeline);
|
|
||||||
|
|
||||||
vk.Destroy(&vulkan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
import aliases;
|
import aliases;
|
||||||
import includes;
|
import includes;
|
||||||
|
import assets;
|
||||||
|
import util;
|
||||||
|
import ap = assets;
|
||||||
|
import vk = vulkan;
|
||||||
|
import u = util;
|
||||||
|
import p = platform;
|
||||||
|
|
||||||
alias Shader = VkShaderModule;
|
alias Shader = VkShaderModule;
|
||||||
alias Pipeline = VkPipeline;
|
alias Pipeline = vk.PipelineHandle;
|
||||||
alias Attribute = VkVertexInputAttributeDescription;
|
alias Attribute = VkVertexInputAttributeDescription;
|
||||||
|
|
||||||
enum InputRate : int
|
enum InputRate : int
|
||||||
@ -20,6 +26,14 @@ enum Format: int
|
|||||||
RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT,
|
RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PipelineType : int
|
||||||
|
{
|
||||||
|
Graphics,
|
||||||
|
Compute,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias PT = PipelineType;
|
||||||
|
|
||||||
struct GfxPipelineInfo
|
struct GfxPipelineInfo
|
||||||
{
|
{
|
||||||
Shader vertex_shader;
|
Shader vertex_shader;
|
||||||
@ -29,4 +43,99 @@ struct GfxPipelineInfo
|
|||||||
Attribute[] vertex_attributes;
|
Attribute[] vertex_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Renderer
|
||||||
|
{
|
||||||
|
vk.Vulkan vulkan;
|
||||||
|
p.Window* window;
|
||||||
|
Pipeline triangle_pipeline;
|
||||||
|
Pipeline compute_pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer
|
||||||
|
Init(p.Window* window)
|
||||||
|
{
|
||||||
|
u.Result!(vk.Vulkan) vk_result = vk.Init(window, u.MB(24), u.MB(32));
|
||||||
|
assert(vk_result.ok, "Init failure: Unable to initialize Vulkan");
|
||||||
|
|
||||||
|
Renderer rd = {
|
||||||
|
vulkan: vk_result.value,
|
||||||
|
window: window,
|
||||||
|
};
|
||||||
|
|
||||||
|
rd.triangle_pipeline = BuildGfxPipeline(&rd, "shaders/triangle.vert", "shaders/triangle.frag");
|
||||||
|
rd.compute_pipeline = BuildCompPipeline(&rd, "shaders/gradient.comp");
|
||||||
|
|
||||||
|
return rd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Cycle(Renderer* rd)
|
||||||
|
{
|
||||||
|
bool success = vk.BeginFrame(&rd.vulkan);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
vk.Bind(&rd.vulkan, rd.triangle_pipeline);
|
||||||
|
|
||||||
|
vk.Draw(&rd.vulkan, 3, 1);
|
||||||
|
|
||||||
|
success = vk.FinishFrame(&rd.vulkan);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pipeline
|
||||||
|
BuildGfxPipeline(Renderer* rd, string vertex, string fragment)
|
||||||
|
{
|
||||||
|
u8[] vert_bytes = ap.LoadAssetData(vertex);
|
||||||
|
u8[] frag_bytes = ap.LoadAssetData(fragment);
|
||||||
|
|
||||||
|
scope(exit)
|
||||||
|
{
|
||||||
|
ap.UnloadAssetData(vertex);
|
||||||
|
ap.UnloadAssetData(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(vert_bytes && frag_bytes, "Unable to load shaders");
|
||||||
|
|
||||||
|
Result!(Shader) vert_module = vk.BuildShader(&rd.vulkan, vert_bytes);
|
||||||
|
Result!(Shader) frag_module = vk.BuildShader(&rd.vulkan, frag_bytes);
|
||||||
|
|
||||||
|
assert(vert_module.ok && frag_module.ok, "Unable to build vulkan shaders");
|
||||||
|
|
||||||
|
scope(exit)
|
||||||
|
{
|
||||||
|
vk.Destroy(&rd.vulkan, vert_module.value);
|
||||||
|
vk.Destroy(&rd.vulkan, frag_module.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GfxPipelineInfo pipeline_info = {
|
||||||
|
vertex_shader: vert_module.value,
|
||||||
|
frag_shader: frag_module.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
return vk.CreateGraphicsPipeline(&rd.vulkan, &pipeline_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pipeline
|
||||||
|
BuildCompPipeline(Renderer* rd, string compute)
|
||||||
|
{
|
||||||
|
u8[] comp_bytes = ap.LoadAssetData(compute);
|
||||||
|
assert(comp_bytes != null, "Unable to load compute shader data");
|
||||||
|
scope(exit) ap.UnloadAssetData(compute);
|
||||||
|
|
||||||
|
Result!(Shader) comp_module = vk.BuildShader(&rd.vulkan, comp_bytes);
|
||||||
|
assert(comp_module.ok, "Unable to build compute shader");
|
||||||
|
scope(exit) vk.Destroy(&rd.vulkan, comp_module.value);
|
||||||
|
|
||||||
|
return vk.CreateComputePipeline(&rd.vulkan, comp_module.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Destroy(Renderer* rd)
|
||||||
|
{
|
||||||
|
vk.Destroy(&rd.vulkan, rd.triangle_pipeline);
|
||||||
|
vk.Destroy(&rd.vulkan, rd.compute_pipeline);
|
||||||
|
vk.Destroy(&rd.vulkan);
|
||||||
|
}
|
||||||
|
|||||||
@ -119,6 +119,8 @@ struct Vulkan
|
|||||||
a.Arena arena;
|
a.Arena arena;
|
||||||
a.Arena[FRAME_OVERLAP] frame_arenas;
|
a.Arena[FRAME_OVERLAP] frame_arenas;
|
||||||
|
|
||||||
|
u64 frame_no;
|
||||||
|
|
||||||
u.SLList!(SI) cleanup_list;
|
u.SLList!(SI) cleanup_list;
|
||||||
|
|
||||||
p.Window* window;
|
p.Window* window;
|
||||||
@ -136,6 +138,8 @@ struct Vulkan
|
|||||||
VkExtent3D swapchain_extent;
|
VkExtent3D swapchain_extent;
|
||||||
|
|
||||||
ImageView[] present_images;
|
ImageView[] present_images;
|
||||||
|
u32 image_index;
|
||||||
|
|
||||||
ImageView draw_image;
|
ImageView draw_image;
|
||||||
ImageView depth_image;
|
ImageView depth_image;
|
||||||
|
|
||||||
@ -162,6 +166,12 @@ struct Vulkan
|
|||||||
QueueInfo queues;
|
QueueInfo queues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PipelineHandle
|
||||||
|
{
|
||||||
|
VkPipeline handle;
|
||||||
|
VkPipelineBindPoint type;
|
||||||
|
}
|
||||||
|
|
||||||
struct QueueInfo
|
struct QueueInfo
|
||||||
{
|
{
|
||||||
i32 gfx_index, tfer_index;
|
i32 gfx_index, tfer_index;
|
||||||
@ -211,6 +221,338 @@ Init(p.Window* window, u64 permanent_mem, u64 frame_mem)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64
|
||||||
|
FrameIndex(Vulkan* vk)
|
||||||
|
{
|
||||||
|
return vk.frame_no % FRAME_OVERLAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64
|
||||||
|
SemIndex(Vulkan* vk)
|
||||||
|
{
|
||||||
|
return vk.frame_no % vk.present_images.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImage
|
||||||
|
CurrentImage(Vulkan* vk)
|
||||||
|
{
|
||||||
|
return vk.present_images[vk.image_index].base.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BeginFrame(Vulkan* vk)
|
||||||
|
{
|
||||||
|
u64 index = FrameIndex(vk);
|
||||||
|
u64 sem_index = SemIndex(vk);
|
||||||
|
|
||||||
|
// TODO: move vkWaitForFences so it no longer holds up the frame, will need to change how fences are handled in regards to images though
|
||||||
|
VkResult result = vkWaitForFences(vk.device, 1, vk.render_fences.ptr + index, VK_TRUE, 1000000000);
|
||||||
|
bool success = VkCheck("BeginFrame failure: vkWaitForFences error", result);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
result = vkResetFences(vk.device, 1, vk.render_fences.ptr + index);
|
||||||
|
success = VkCheck("BeginFrame failure: vkResetFences error", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
result = vkAcquireNextImageKHR(vk.device, vk.swapchain, 1000000000, vk.swapchain_sems[sem_index], null, &vk.image_index);
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR)
|
||||||
|
{
|
||||||
|
RecreateSwapchain(vk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = VkCheck("BeginFrame failure: vkAcquireNextImageKHR error", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
result = vkResetCommandBuffer(vk.cmds[index], 0);
|
||||||
|
success = VkCheck("BeginFrame failure: vkResetCommandBuffer failure", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
VkCommandBufferBeginInfo cmd_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
flags: VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
result = vkBeginCommandBuffer(vk.cmds[index], &cmd_info);
|
||||||
|
success = VkCheck("BeginFrame failure: vkBeginCommandBuffer error", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Transition(vk.cmds[index], &vk.draw_image.base, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
Transition(vk.cmds[index], &vk.depth_image.base, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
|
VkImage image = CurrentImage(vk);
|
||||||
|
Transition(vk.cmds[index], image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
|
f32[4] clear_col;
|
||||||
|
clear_col[] = 0.2;
|
||||||
|
|
||||||
|
VkRenderingAttachmentInfo col_attach = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||||
|
imageView: vk.draw_image.view,
|
||||||
|
imageLayout: vk.draw_image.base.layout,
|
||||||
|
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||||
|
storeOp: VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
clearValue: { color: { clear_col } },
|
||||||
|
};
|
||||||
|
|
||||||
|
VkRenderingAttachmentInfo depth_attach = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||||
|
imageView: vk.depth_image.view,
|
||||||
|
imageLayout: vk.depth_image.base.layout,
|
||||||
|
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||||
|
storeOp: VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkRenderingInfo render_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||||
|
layerCount: 1,
|
||||||
|
colorAttachmentCount: 1,
|
||||||
|
pColorAttachments: &col_attach,
|
||||||
|
pDepthAttachment: &depth_attach,
|
||||||
|
renderArea: {
|
||||||
|
extent: {
|
||||||
|
width: vk.swapchain_extent.width,
|
||||||
|
height: vk.swapchain_extent.height,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdBeginRendering(vk.cmds[index], &render_info);
|
||||||
|
vkCmdBindDescriptorSets(
|
||||||
|
vk.cmds[index],
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
vk.pipeline_layout,
|
||||||
|
0,
|
||||||
|
cast(u32)vk.desc_sets.length,
|
||||||
|
vk.desc_sets.ptr,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FinishFrame(Vulkan* vk)
|
||||||
|
{
|
||||||
|
scope(exit) vk.frame_no += 1;
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
u64 index = FrameIndex(vk);
|
||||||
|
u64 sem_index = SemIndex(vk);
|
||||||
|
VkImage image = CurrentImage(vk);
|
||||||
|
|
||||||
|
vkCmdEndRendering(vk.cmds[index]);
|
||||||
|
|
||||||
|
Transition(vk.cmds[index], &vk.draw_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
|
||||||
|
VkExtent2D extent = {
|
||||||
|
width: vk.swapchain_extent.width,
|
||||||
|
height: vk.swapchain_extent.height,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Find out how to copy from same dimension images
|
||||||
|
Copy(vk.cmds[index], vk.draw_image.base.image, image, extent, extent);
|
||||||
|
|
||||||
|
Transition(vk.cmds[index], image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
|
|
||||||
|
VkResult result = vkEndCommandBuffer(vk.cmds[index]);
|
||||||
|
success = VkCheck("FinishFrame failure: vkEndCommandBuffer error", result);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
VkCommandBufferSubmitInfo cmd_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
|
||||||
|
commandBuffer: vk.cmds[index],
|
||||||
|
};
|
||||||
|
|
||||||
|
VkSemaphoreSubmitInfo wait_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
|
||||||
|
semaphore: vk.swapchain_sems[sem_index],
|
||||||
|
stageMask: VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
value: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkSemaphoreSubmitInfo signal_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
|
||||||
|
semaphore: vk.render_sems[index],
|
||||||
|
stageMask: VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT,
|
||||||
|
value: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkSubmitInfo2 submit_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
|
||||||
|
waitSemaphoreInfoCount: 1,
|
||||||
|
pWaitSemaphoreInfos: &wait_info,
|
||||||
|
signalSemaphoreInfoCount: 1,
|
||||||
|
pSignalSemaphoreInfos: &signal_info,
|
||||||
|
commandBufferInfoCount: 1,
|
||||||
|
pCommandBufferInfos: &cmd_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
result = vkQueueSubmit2(vk.queues.gfx_queue, 1, &submit_info, vk.render_fences[index]);
|
||||||
|
success = VkCheck("FinishFrame failure: vkQueueSubmit2 error", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
VkPresentInfoKHR present_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
|
swapchainCount: 1,
|
||||||
|
pSwapchains: &vk.swapchain,
|
||||||
|
waitSemaphoreCount: 1,
|
||||||
|
pWaitSemaphores: vk.render_sems.ptr + index,
|
||||||
|
pImageIndices: &vk.image_index,
|
||||||
|
};
|
||||||
|
|
||||||
|
result = vkQueuePresentKHR(vk.queues.gfx_queue, &present_info);
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
|
||||||
|
{
|
||||||
|
RecreateSwapchain(vk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = VkCheck("FinishFrame failure: vkQueuePresentKHR failure", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Draw(Vulkan* vk, u32 index_count, u32 instance_count)
|
||||||
|
{
|
||||||
|
vkCmdDraw(vk.cmds[FrameIndex(vk)], index_count, instance_count, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawIndexed(Vulkan* vk, u32 index_count, u32 instance_count)
|
||||||
|
{
|
||||||
|
vkCmdDrawIndexed(vk.cmds[FrameIndex(vk)], index_count, instance_count, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
Copy(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext)
|
||||||
|
{
|
||||||
|
VkImageBlit2 blit = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
|
||||||
|
srcOffsets: [
|
||||||
|
{},
|
||||||
|
{ x: cast(i32)src_ext.width, y: cast(i32)src_ext.height, z: 1 },
|
||||||
|
],
|
||||||
|
dstOffsets: [
|
||||||
|
{},
|
||||||
|
{ x: cast(i32)dst_ext.width, y: cast(i32)dst_ext.height, z: 1 },
|
||||||
|
],
|
||||||
|
srcSubresource: {
|
||||||
|
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
baseArrayLayer: 0,
|
||||||
|
layerCount: 1,
|
||||||
|
mipLevel: 0,
|
||||||
|
},
|
||||||
|
dstSubresource: {
|
||||||
|
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
baseArrayLayer: 0,
|
||||||
|
layerCount: 1,
|
||||||
|
mipLevel: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
VkBlitImageInfo2 blit_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
|
||||||
|
srcImage: src,
|
||||||
|
srcImageLayout: VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
dstImage: dst,
|
||||||
|
dstImageLayout: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
filter: VK_FILTER_LINEAR,
|
||||||
|
regionCount: 1,
|
||||||
|
pRegions: &blit,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdBlitImage2(cmd, &blit_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Bind(Vulkan* vk, PipelineHandle pipeline)
|
||||||
|
{
|
||||||
|
u64 index = FrameIndex(vk);
|
||||||
|
|
||||||
|
vkCmdBindPipeline(vk.cmds[index], pipeline.type, pipeline.handle);
|
||||||
|
|
||||||
|
VkViewport viewport = {
|
||||||
|
width: cast(f32)vk.swapchain_extent.width,
|
||||||
|
height: cast(f32)vk.swapchain_extent.height,
|
||||||
|
maxDepth: 1.0F,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdSetViewport(vk.cmds[index], 0, 1, &viewport);
|
||||||
|
|
||||||
|
VkRect2D scissor = {
|
||||||
|
extent: {
|
||||||
|
width: vk.swapchain_extent.width,
|
||||||
|
height: vk.swapchain_extent.height,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdSetScissor(vk.cmds[index], 0, 1, &scissor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
Transition(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout)
|
||||||
|
{
|
||||||
|
VkImageMemoryBarrier2 barrier = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||||
|
srcStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
|
||||||
|
srcAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT,
|
||||||
|
dstStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
|
||||||
|
dstAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT,
|
||||||
|
oldLayout: current_layout,
|
||||||
|
newLayout: new_layout,
|
||||||
|
image: image,
|
||||||
|
subresourceRange: {
|
||||||
|
aspectMask: new_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
baseMipLevel: 0,
|
||||||
|
levelCount: VK_REMAINING_MIP_LEVELS,
|
||||||
|
baseArrayLayer: 0,
|
||||||
|
layerCount: VK_REMAINING_ARRAY_LAYERS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDependencyInfo dep_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||||
|
imageMemoryBarrierCount: 1,
|
||||||
|
pImageMemoryBarriers: &barrier,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier2(cmd, &dep_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
Transition(VkCommandBuffer cmd, ImageView* view, VkImageLayout new_layout)
|
||||||
|
{
|
||||||
|
Transition(cmd, view.base.image, view.base.layout, new_layout);
|
||||||
|
view.base.layout = new_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
Transition(VkCommandBuffer cmd, Image* image, VkImageLayout new_layout)
|
||||||
|
{
|
||||||
|
Transition(cmd, image.image, image.layout, new_layout);
|
||||||
|
image.layout = new_layout;
|
||||||
|
}
|
||||||
|
|
||||||
Result!(Shader)
|
Result!(Shader)
|
||||||
BuildShader(Vulkan* vk, u8[] bytes)
|
BuildShader(Vulkan* vk, u8[] bytes)
|
||||||
{
|
{
|
||||||
@ -343,9 +685,9 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
|||||||
layout: vk.pipeline_layout,
|
layout: vk.pipeline_layout,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipeline pipeline;
|
PipelineHandle pipeline = { type: VK_PIPELINE_BIND_POINT_GRAPHICS };
|
||||||
|
|
||||||
VkResult result = vkCreateGraphicsPipelines(vk.device, null, 1, &create_info, null, &pipeline);
|
VkResult result = vkCreateGraphicsPipelines(vk.device, null, 1, &create_info, null, &pipeline.handle);
|
||||||
assert(VkCheck("CreateGraphicsPipeline failure", result), "Unable to build pipeline");
|
assert(VkCheck("CreateGraphicsPipeline failure", result), "Unable to build pipeline");
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
@ -367,8 +709,8 @@ CreateComputePipeline(Vulkan* vk, Shader shader)
|
|||||||
|
|
||||||
__traits(getMember, &info.stage, "module") = shader;
|
__traits(getMember, &info.stage, "module") = shader;
|
||||||
|
|
||||||
VkPipeline pipeline;
|
PipelineHandle pipeline = { type: VK_PIPELINE_BIND_POINT_COMPUTE };
|
||||||
VkResult result = vkCreateComputePipelines(vk.device, null, 1, &info, null, &pipeline);
|
VkResult result = vkCreateComputePipelines(vk.device, null, 1, &info, null, &pipeline.handle);
|
||||||
assert(VkCheck("CreateComputePipeline failure", result), "Unable to build pipeline");
|
assert(VkCheck("CreateComputePipeline failure", result), "Unable to build pipeline");
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
@ -383,7 +725,7 @@ Destroy(Vulkan* vk, Shader shader)
|
|||||||
void
|
void
|
||||||
Destroy(Vulkan* vk, Pipeline pipeline)
|
Destroy(Vulkan* vk, Pipeline pipeline)
|
||||||
{
|
{
|
||||||
vkDestroyPipeline(vk.device, pipeline, null);
|
vkDestroyPipeline(vk.device, pipeline.handle, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -971,6 +1313,16 @@ CreateSwapchain(Vulkan* vk)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RecreateSwapchain(Vulkan* vk)
|
||||||
|
{
|
||||||
|
vkDeviceWaitIdle(vk.device);
|
||||||
|
|
||||||
|
Destroy(vk.swapchain, vk.present_images, vk.device);
|
||||||
|
|
||||||
|
CreateSwapchain(vk);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
InitVMA(Vulkan* vk)
|
InitVMA(Vulkan* vk)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import std.conv;
|
|||||||
import std.string;
|
import std.string;
|
||||||
import core.stdc.string : strlen;
|
import core.stdc.string : strlen;
|
||||||
|
|
||||||
VkBool32
|
extern(System) VkBool32
|
||||||
DebugCallback(
|
DebugCallback(
|
||||||
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||||
VkDebugUtilsMessageTypeFlagsEXT message_type,
|
VkDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
|||||||
@ -61,8 +61,12 @@ struct AssetInfo
|
|||||||
AssetType type;
|
AssetType type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool Asset_Pack_Opened = false;
|
||||||
|
|
||||||
|
void
|
||||||
OpenAssetPack()
|
OpenAssetPack()
|
||||||
|
{
|
||||||
|
if (!Asset_Pack_Opened)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
string file_path = isFile("build/assets.sgp") ? "build/assets.sgp" : "assets.sgp";
|
string file_path = isFile("build/assets.sgp") ? "build/assets.sgp" : "assets.sgp";
|
||||||
@ -74,8 +78,8 @@ OpenAssetPack()
|
|||||||
}
|
}
|
||||||
catch (ErrnoException e)
|
catch (ErrnoException e)
|
||||||
{
|
{
|
||||||
success = false;
|
|
||||||
Logf("OpenAssetPack failure: Unable to open file %s", file_path);
|
Logf("OpenAssetPack failure: Unable to open file %s", file_path);
|
||||||
|
assert(false, "Unable to open asset pack file");
|
||||||
}
|
}
|
||||||
|
|
||||||
FileHeader[1] header_arr;
|
FileHeader[1] header_arr;
|
||||||
@ -89,13 +93,17 @@ OpenAssetPack()
|
|||||||
Asset_File.seek(Asset_Header.asset_info_offset);
|
Asset_File.seek(Asset_Header.asset_info_offset);
|
||||||
|
|
||||||
Asset_File.rawRead(Asset_Info);
|
Asset_File.rawRead(Asset_Info);
|
||||||
|
}
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8[]
|
u8[]
|
||||||
LoadAssetData(string name)
|
LoadAssetData(string name)
|
||||||
{
|
{
|
||||||
|
if (!Asset_Pack_Opened)
|
||||||
|
{
|
||||||
|
OpenAssetPack();
|
||||||
|
}
|
||||||
|
|
||||||
u64 hash = Hash(name);
|
u64 hash = Hash(name);
|
||||||
u8[] data = null;
|
u8[] data = null;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user