commit before deleting shaders

This commit is contained in:
matthew 2025-08-09 14:11:18 +10:00
parent 194149f8dd
commit 92980fba0d
13 changed files with 346 additions and 451 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -61,33 +61,18 @@ struct Game
PlatformWindow* window;
Pipeline pbr_pipeline;
Pipeline triangle_pipeline;
Pipeline compute_pipeline;
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;
GlobalUniforms globals;
PushConst pc;
Timer timer;
Camera camera;
Model tree;
Model rock;
Model magic_rock;
Model log;
Model stump;
SLList!(Model) models;
}
Game
@ -110,11 +95,6 @@ InitGame(PlatformWindow* window)
CreateImageView(&g.rd, &g.aux_image, ext.x, ext.y, FMT.R_U32, IU.Storage);
GfxPipelineInfo triangle_info = {
vertex_shader: "shaders/triangle.vert.spv",
frag_shader: "shaders/triangle.frag.spv",
};
GfxPipelineInfo ui_info = {
vertex_shader: "shaders/gui.vert.spv",
frag_shader: "shaders/gui.frag.spv",
@ -128,39 +108,7 @@ InitGame(PlatformWindow* window)
],
};
GfxPipelineInfo pbr_info = {
vertex_shader: "shaders/pbr.vert.spv",
frag_shader: "shaders/pbr.frag.spv",
input_rate_stride: Vertex.sizeof,
vertex_attributes: [
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 },
{ binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.tangent.offsetof },
{ binding: 0, location: 2, format: FMT.RGB_F32, offset: Vertex.pos.offsetof },
{ binding: 0, location: 3, format: FMT.RGB_F32, offset: Vertex.normal.offsetof },
{ binding: 0, location: 4, format: FMT.RG_F32, offset: Vertex.uv.offsetof },
]
};
GfxPipelineInfo oit_info = {
vertex_shader: "shaders/full_screen_triangle.vert.spv",
frag_shader: "shaders/oit.frag.spv",
};
CompPipelineInfo gradient_info = {
shader: "shaders/gradient.comp.spv",
};
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);
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);
@ -184,50 +132,6 @@ Copy(Model* dst, Model* src)
void
ProcessInputs(Game* g, Camera* cam)
{
foreach(i; 0 .. g.window.inputs.count)
{
InputEvent event = g.window.inputs.events[i];
switch(event.key)
{
case Input.One:
{
Node!(Model)* node = Alloc!(Node!(Model));
Copy(&node.value, &g.tree);
node.value.pos = cam.pos;
PushFront(&g.models, node, null);
} break;
case Input.Two:
{
Node!(Model)* node = Alloc!(Node!(Model));
Copy(&node.value, &g.rock);
node.value.pos = cam.pos;
PushFront(&g.models, node, null);
} break;
case Input.Three:
{
Node!(Model)* node = Alloc!(Node!(Model));
Copy(&node.value, &g.magic_rock);
node.value.pos = cam.pos;
PushFront(&g.models, node, null);
} break;
case Input.Four:
{
Node!(Model)* node = Alloc!(Node!(Model));
Copy(&node.value, &g.log);
node.value.pos = cam.pos;
PushFront(&g.models, node, null);
} break;
case Input.Five:
{
Node!(Model)* node = Alloc!(Node!(Model));
Copy(&node.value, &g.stump);
node.value.pos = cam.pos;
PushFront(&g.models, node, null);
} break;
default: break;
}
}
HandleInputs(cam, &g.window.inputs);
}
@ -276,30 +180,6 @@ Cycle(Game* g)
BindUIBuffers(&g.rd);
Bind(&g.rd, &g.triangle_pipeline);
Bind(&g.rd, &g.pbr_pipeline);
g.pc.model_matrix = Mat4Identity();
Node!(Model)* model = g.models.first;
for(;;)
{
if (model == null)
{
break;
}
DrawModel(g, &model.value);
model = model.next;
}
ImageBarrier(&g.rd);
Bind(&g.rd, &g.oit_pipeline);
Draw(&g.rd, 3, 1);
FinishRendering(&g.rd);
//ImageBarrier(&g.rd);
@ -330,17 +210,8 @@ void
Destroy(Game* g)
{
WaitIdle(&g.rd);
Destroy(&g.rd, &g.pbr_pipeline);
Destroy(&g.rd, &g.triangle_pipeline);
Destroy(&g.rd, &g.ui_pipeline);
Destroy(&g.rd, &g.compute_pipeline);
Destroy(&g.rd, &g.rock);
Destroy(&g.rd, &g.tree);
Destroy(&g.rd, &g.magic_rock);
Destroy(&g.rd, &g.log);
Destroy(&g.rd, &g.stump);
Destroy(&g.rd);
}

View File

@ -17,15 +17,26 @@ import math;
alias InitRenderer = Init;
alias Renderer = Vulkan;
alias Shader = VkShaderModule;
alias Pipeline = PipelineHandle;
alias Pipeline = u32;
alias Attribute = VkVertexInputAttributeDescription;
alias SpecEntry = VkSpecializationMapEntry;
alias RenderPass = VkRenderPass;
alias DescSet = VkDescriptorSet;
alias DescSetLayout = VkDescriptorSetLayout;
alias PipelineLayout = VkPipelineLayout;
struct DescLayoutBinding
{
VkDescriptorSetLayoutBinding binding;
bool dynamic;
}
bool g_VLAYER_SUPPORT = false;
bool g_DEBUG_PRINTF = false;
const FRAME_OVERLAP = 2;
const MAX_SETS = 1000;
const DESC_ARRAY_SIZE = 256;
version(linux)
{
@ -189,6 +200,7 @@ struct Buffer
VkBuffer buffer;
VmaAllocation alloc;
u64 size;
bool dynamic;
}
struct ShaderUniforms
@ -227,7 +239,7 @@ struct CompPipelineInfo
{
string shader;
Specialization spec;
VkPipelineLayout *layout;
PipelineLayout layout;
}
struct PushConst
@ -248,7 +260,7 @@ enum StepInitialized : u32
FrameStructures,
Swapchain,
DrawImages,
Descriptors,
DescriptorPools,
Pipelines,
}
@ -328,16 +340,15 @@ struct Vulkan
VkCommandBuffer imm_cmd;
VkFence imm_fence;
VkDescriptorPool desc_pool;
VkDescriptorSet[DT.max] desc_sets;
VkDescriptorSetLayout[DT.max] desc_layouts;
DescBindings[DT.max] desc_bindings;
VkDescriptorPool active_pool;
SLList!(VkDescriptorPool) full_pools;
VkSampler nearest_sampler;
VkSampler oit_sampler;
VkPipeline[FRAME_OVERLAP] last_pipeline;
VkPipelineLayout pipeline_layout;
PipelineHandles[] pipeline_handles;
u32 pipeline_count;
Pipeline[FRAME_OVERLAP] last_pipeline;
MappedBuffer!(u8) transfer_buf;
MappedBuffer!(UIVertex) ui_vert_buf;
@ -347,9 +358,9 @@ struct Vulkan
QueueInfo queues;
PipelineHandle r_to_rgba_pipeline;
PipelineHandle rg_to_rgba_pipeline;
PipelineHandle rgb_to_rgba_pipeline;
Pipeline r_to_rgba_pipeline;
Pipeline rg_to_rgba_pipeline;
Pipeline rgb_to_rgba_pipeline;
VkDescriptorSet conv_desc_set;
VkDescriptorSetLayout conv_desc_layout;
VkPipelineLayout conv_pipeline_layout;
@ -369,10 +380,11 @@ struct ConvPushConst
u32 y;
}
struct PipelineHandle
struct PipelineHandles
{
VkPipeline handle;
VkPipelineBindPoint type;
VkPipelineLayout layout;
}
struct QueueInfo
@ -415,6 +427,7 @@ Init(PlatformWindow* window, u64 permanent_mem, u64 frame_mem)
if (success) success = CreateDrawImages(&vk);
if (success) success = InitFrameStructures(&vk);
if (success) success = InitDescriptors(&vk);
if (success) InitPipelines(&vk);
if (success) InitBuffers(&vk);
if (success) success = InitConversionPipeline(&vk);
if (success) InitFramebufferAndRenderPass(&vk);
@ -424,76 +437,98 @@ Init(PlatformWindow* window, u64 permanent_mem, u64 frame_mem)
return vk;
}
void
InitPipelines(Vulkan* vk)
{
vk.pipeline_handles = AllocArray!(PipelineHandles)(&vk.arena, 128);
vk.pipeline_count += 1;
}
DescSetLayout
CreateDescSetLayout(Vulkan* vk, DescLayoutBinding[] bindings)
{
VkDescriptorSetLayoutCreateInfo layout_info = {
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
bindingCount: cast(u32)bindings.length,
pBindings: bindings.ptr,
};
DescSetLayout layout;
VkResult result = vkCreateDescriptorSetLayout(vk.device, &layout_info, null, &layout);
VkCheckA("vkCreateDescriptorSetLayout failure", result);
return layout;
}
DescSet
AllocDescSet(Vulkan* vk, DescSetLayout layout)
{
VkDescriptorSetAllocateInfo alloc_info = {
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
descriptorSetCount: 1,
pSetLayouts: &layout,
descriptorPool: vk.active_pool,
};
DescSet set;
VkResult result = vkAllocateDescriptorSets(vk.device, &alloc_info, &set);
if (result == VK_ERROR_OUT_OF_POOL_MEMORY || result == VK_ERROR_FRAGMENTED_POOL)
{
PushDescriptorPool(vk);
alloc_info = vk.active_pool;
result = vkAllocateDescriptorSets(vk.device, &alloc_info, &set);
VkCheckA("vkAllocateDescriptorSets failure", result); // TODO: look more into how to handle this
}
return set;
}
PipelineLayout
CreatePipelineLayout(Vulkan* vk, DescSetLayout[] layouts, u64 push_const_size, bool compute = false)
{
VkShaderStageFlagBits stage = (compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
VkPushConstantRange const_range = {
offset: 0,
size: cast(VkDeviceSize)push_const_size,
stageFlags: stage,
};
VkPipelineLayoutCreateInfo layout_info = {
sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
setLayoutCount: cast(u32)layouts.length,
pSetLayouts: layouts.ptr,
pushConstantRangeCount: (push_const_size > 0 ? 1 : 0),
pPushConstantRanges: (push_const_size > 0 ? &const_range : null),
};
PipelineLayout layout;
VkResult result = vkCreatePipelineLayout(vk.device, &layout_info, null, &layout);
VkCheckA("CreatePipelineLayout failure", result);
return layout;
}
bool
InitConversionPipeline(Vulkan* vk)
{
Push(vk, SI.Pipelines);
VkDescriptorBindingFlags[] binding_flags;
binding_flags[] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
VkDescriptorSetLayoutBindingFlagsCreateInfo flag_info = {
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
bindingCount: cast(u32)binding_flags.length,
pBindingFlags: binding_flags.ptr,
};
VkDescriptorSetLayoutBinding[] layout_bindings = [
{ 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 },
];
VkDescriptorSetLayoutCreateInfo set_info = {
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
pNext: &flag_info,
bindingCount: cast(u32)layout_bindings.length,
pBindings: layout_bindings.ptr,
flags: VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
};
vk.conv_desc_layout = CreateDescSetLayout(vk, layout_bindings);
vk.conv_desc_set = AllocDescSet(vk, vk.conv_desc_layout);
vk.conv_pipeline_layout = CreatePipelineLayout(vk, [vk.conv_desc_layout], ConvPushConst.sizeof, true);
VkResult result = vkCreateDescriptorSetLayout(vk.device, &set_info, null, &vk.conv_desc_layout);
bool success = VkCheck("InitConversionPipeline failure: vkCreateDescriptorSetLayout error", result);
if (success)
{
VkDescriptorSetAllocateInfo alloc_info = {
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
descriptorSetCount: 1,
pSetLayouts: &vk.conv_desc_layout,
descriptorPool: vk.desc_pool,
};
result = vkAllocateDescriptorSets(vk.device, &alloc_info, &vk.conv_desc_set);
success = VkCheck("InitConversionPipeline failure: vkAllocateDescriptorSets error", result);
}
if (success)
{
VkPushConstantRange const_range = {
offset: 0,
size: cast(VkDeviceSize)ConvPushConst.sizeof,
stageFlags: VK_SHADER_STAGE_COMPUTE_BIT,
};
VkPipelineLayoutCreateInfo layout_info = {
sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
setLayoutCount: 1,
pSetLayouts: &vk.conv_desc_layout,
pushConstantRangeCount: 1,
pPushConstantRanges: &const_range,
};
result = vkCreatePipelineLayout(vk.device, &layout_info, null, &vk.conv_pipeline_layout);
success = VkCheck("InitConversionPipeline failure: vkCreatePipelineLayout error", result);
}
if (success)
{
u32 channels = 1;
CompPipelineInfo conv_info = {
shader: "shaders/convert.comp.spv",
layout: &vk.conv_pipeline_layout,
layout: vk.conv_pipeline_layout,
spec: {
data: &channels,
size: u32.sizeof,
@ -514,20 +549,21 @@ InitConversionPipeline(Vulkan* vk)
channels = 3;
vk.rgb_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info);
}
return success;
}
void
CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visible)
CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visible, bool dynamic = false)
{
assert(type != BT.None, "CreateBuffer failure: type is None");
u64 buffer_size = (dynamic ? size * FRAME_OVERLAP : size);
VkBufferCreateInfo buffer_info = {
sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
usage: type,
size: size,
size: buffer_size,
};
VmaAllocationCreateInfo alloc_info = {
@ -558,7 +594,8 @@ CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visib
// TODO: handle errors here then reallocate buffer
assert(VkCheck("CreateBuffer failure: vmaCreateBuffer error", result), "CreateBuffer failure");
buf.size = size;
buf.size = buffer_size;
buf.dynamic = dynamic;
}
void
@ -932,22 +969,11 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
BeginComputePass(vk);
vkCmdBindDescriptorSets(
vk.comp_cmd,
VK_PIPELINE_BIND_POINT_COMPUTE,
vk.conv_pipeline_layout,
0,
1,
&vk.conv_desc_set,
0,
null
);
Pipeline pipeline = ch == 1 ? vk.r_to_rgba_pipeline :
ch == 2 ? vk.rg_to_rgba_pipeline :
vk.rgb_to_rgba_pipeline;
VkPipeline pipeline = ch == 1 ? vk.r_to_rgba_pipeline.handle :
ch == 2 ? vk.rg_to_rgba_pipeline.handle :
vk.rgb_to_rgba_pipeline.handle;
vkCmdBindPipeline(vk.comp_cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
Bind(vk, pipeline, vk.conv_desc_set);
ConvPushConst pc = {
x: w,
@ -1106,68 +1132,12 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageU
view.usage = usage;
}
u32
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;
}
}
void
PushConstants(Vulkan* vk, PushConst* pc)
PushConstants(Vulkan* vk, PipelineLayout layout, PushConst* pc)
{
vkCmdPushConstants(
vk.cmds[vk.frame_index],
vk.pipeline_layout,
layout,
VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT|VK_SHADER_STAGE_COMPUTE_BIT,
0,
PushConst.sizeof,
@ -1383,24 +1353,50 @@ Copy(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout src_layout, Vk
}
void
Bind(Vulkan* vk, PipelineHandle* pipeline)
Bind(Vulkan* vk, Pipeline pipeline_handle, DescSet[] sets)
{
if (vk.last_pipeline[vk.frame_index] == null || vk.last_pipeline[vk.frame_index] != pipeline.handle)
{
vkCmdBindPipeline(vk.cmds[vk.frame_index], pipeline.type, pipeline.handle);
vk.last_pipeline[vk.frame_index] = pipeline.handle;
}
assert(pipeline_handle > 0, "Bind failure: pipeline is 0");
PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_handle;
BindPipeline(vk, pipeline);
vkCmdBindDescriptorSets(
vk.cmds[vk.frame_index],
pipeline.type,
vk.pipeline_layout,
pipeline.layout,
0,
cast(u32)vk.desc_sets.length,
vk.desc_sets.ptr,
cast(u32)sets.length,
sets.ptr,
0,
null
);
}
void
Bind(Vulkan* vk, Pipeline pipeline_handle, DescSet set)
{
assert(pipeline_handle > 0, "Bind failure: pipeline is 0");
PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_handle;
BindPipeline(vk, pipeline);
vkCmdBindDescriptorSets(
vk.cmds[vk.frame_index],
pipeline.type,
pipeline.layout,
0,
1,
&set,
0,
null
);
}
pragma(inline): void
BindPipeline(Vulkan* vk, PipelineHandles* pipeline)
{
if (vk.last_pipeline[vk.frame_index] == 0 || vk.last_pipeline[vk.frame_index] != pipeline_handle)
{
vkCmdBindPipeline(vk.cmds[vk.frame_index], pipeline.type, pipeline.handle);
vk.last_pipeline[vk.frame_index] = pipeline_handle;
VkViewport viewport = {
x: 0.0,
@ -1421,6 +1417,7 @@ Bind(Vulkan* vk, PipelineHandle* pipeline)
};
vkCmdSetScissor(vk.cmds[vk.frame_index], 0, 1, &scissor);
}
}
pragma(inline): void
@ -1725,7 +1722,6 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
pDynamicState: &dyn_info,
stageCount: cast(u32)shader_info.length,
pStages: shader_info.ptr,
layout: vk.pipeline_layout,
renderPass: vk.render_pass,
};
@ -1740,7 +1736,7 @@ CreateComputePipeline(Vulkan* vk, CompPipelineInfo* comp_info)
{
VkComputePipelineCreateInfo info = {
sType: VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
layout: comp_info.layout ? *comp_info.layout : vk.pipeline_layout,
layout: comp_info.layout,
stage: {
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
stage: VK_SHADER_STAGE_COMPUTE_BIT,
@ -1769,11 +1765,17 @@ CreateComputePipeline(Vulkan* vk, CompPipelineInfo* comp_info)
info.stage.pSpecializationInfo = &spec_info;
}
PipelineHandle pipeline = { type: VK_PIPELINE_BIND_POINT_COMPUTE };
PipelineHandles* pipeline = vk.pipeline_handles.ptr + vk.pipeline_count;
pipeline.type = VK_PIPELINE_BIND_POINT_COMPUTE;
pipeline.layout = comp_info.layout;
Pipeline pipeline_handle = vk.pipeline_count;
vk.pipeline_count += 1;
VkResult result = vkCreateComputePipelines(vk.device, null, 1, &info, null, &pipeline.handle);
assert(VkCheck("CreateComputePipeline failure", result), "Unable to build pipeline");
return pipeline;
return pipeline_handle;
}
void
@ -1809,7 +1811,7 @@ SetUniform(Vulkan* vk, GlobalUniforms* globals)
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
dstSet: vk.desc_sets[DT.Shared],
dstBinding: 0,
descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
descriptorCount: 1,
pBufferInfo: &buffer_info,
};
@ -1874,8 +1876,8 @@ Destroy(Vulkan* vk)
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);
case SI.DescriptorPools:
DestroyDescriptorPools(vk);
break;
case SI.Buffers:
Destroy(vk, &vk.transfer_buf);
@ -1893,6 +1895,25 @@ Destroy(Vulkan* vk)
}
}
void
DestroyDescriptorPools(Vulkan* vk)
{
vkDestroyDescriptorPool(vk.device, vk.active_pool, null);
Node!(VkDescriptorPool)* node = vk.full_pools.first;
for(;;)
{
if (node == null)
{
break;
}
vkDestroyDescriptorPool(vk.device, node.value, null);
node = node.next;
}
}
void
DestroyPipelines(Vulkan* vk)
{
@ -1938,15 +1959,21 @@ Destroy(Vulkan* vk, Buffer* buf)
bool
InitDescriptors(Vulkan* vk)
{
Push(vk, SI.Descriptors);
Push(vk, SI.DescriptorPools);
bool success = true;
PushDescriptorPool(vk);
}
void
PushDescriptorPool(Vulkan* vk)
{
VkDescriptorPoolSize[] pool_sizes = [
{ type: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 4096 },
{ type: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 4096 },
{ type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 4096 },
{ type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 4096 },
{ type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, descriptorCount: 4096 },
{ type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 4096 },
{ type: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 4096 },
{ type: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 4096 },
];
@ -1955,18 +1982,36 @@ InitDescriptors(Vulkan* vk)
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
poolSizeCount: cast(u32)pool_sizes.length,
pPoolSizes: pool_sizes.ptr,
maxSets: 12,
flags: VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
maxSets: MAX_SETS,
};
VkResult result = vkCreateDescriptorPool(vk.device, &pool_info, null, &vk.desc_pool);
VkDescriptorPool pool;
VkResult result = vkCreateDescriptorPool(vk.device, &pool_info, null, &pool);
success = VkCheck("vkCreateDescriptorPool failure", result);
assert(success, "vkCreateDescriptorPool error");
if (vk.active_pool == null || vk.active_pool == VK_NULL_HANDLE)
{
Node!(VkDescriptorPool)* node = Alloc!(Node!(VkDescriptorPool));
node.value = vk.active_pool;
PushFront(&g.full_pools, node, null);
}
vk.active_pool = pool;
}
bool
InitDescriptors(Vulkan* vk)
{
if (success)
{
VkDescriptorSetLayoutBinding[] shared_bindings = [
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
{ binding: 2, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
{ binding: 3, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
{ binding: 4, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
@ -2069,26 +2114,6 @@ InitDescriptors(Vulkan* vk)
success = VkCheck("vkCreatePipelineLayout failure", result);
}
if (success)
{
foreach(i; cast(u64)DT.min .. cast(u64)DT.max)
{
vk.desc_bindings[i].lookup_table = CreateHashTable!(string, u32)(8);
u32 DESC_MAX_BINDINGS = 512;
vk.desc_bindings[i].free = AllocArray!(u32)(&vk.arena, DESC_MAX_BINDINGS);
u32 free_count = 0;
for(i32 j = DESC_MAX_BINDINGS-1; j >= 0; j -= 1)
{
vk.desc_bindings[i].free[j] = cast(u32)free_count;
free_count += 1;
}
vk.desc_bindings[i].count = free_count;
}
}
if (success)
{
VkPhysicalDeviceProperties props;

View File

@ -1,17 +1,19 @@
#version 460
#extension GL_GOOGLE_include_directive : require
#extension GL_EXT_nonuniform_qualifier : require
#include "structures.layout"
#include "gui.layout"
layout (location = 0) in vec4 in_color;
layout (location = 1) in vec2 in_uv;
layout (location = 2) flat in uint in_image;
layout (location = 0) in struct FragDataIn {
vec4 color;
vec2 uv;
} FragData;
layout (location = 0) out vec4 out_frag_col;
layout (location = 0) out vec4 FragColor;
void main()
{
out_frag_col = in_color;
vec4 tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FragData.uv);
FragColor = FragData.color * tex_color;
}

5
src/shaders/gui.layout Normal file
View File

@ -0,0 +1,5 @@
layout (set = 1, binding = 0) uniform texture2D SpriteAtlas;
layout (push_constant) uniform Constants {
vec2 res;
} PC;

View File

@ -1,25 +1,27 @@
#version 460
#extension GL_GOOGLE_include_directive : require
#extension GL_EXT_nonuniform_qualifier : require
#include "structures.layout"
#include "gui.layout"
layout (location = 0) in vec2 in_gui_pos_0;
layout (location = 1) in vec2 in_gui_pos_1;
layout (location = 2) in vec4 in_col;
layout (location = 3) in uint in_image;
layout (location = 0) in vec2 in_dst_start;
layout (location = 1) in vec2 in_dst_end;
layout (location = 2) in vec2 in_src_start;
layout (location = 3) in vec2 in_src_end;
layout (location = 4) in vec4 in_col;
layout (location = 0) out vec4 out_color;
layout (location = 1) out vec2 out_uv;
layout (location = 2) out uint out_image;
layout (location = 0) out struct FragDataOut {
vec4 color;
vec2 uv;
} FragData;
vec2 uvs[] = {
vec2(0.0, 1.0),
vec2(0.0, 0.0),
vec2(1.0, 1.0),
vec2(1.0, 0.0)
};
vec2 Vertices[4] = vec2[4](
vec2(-1.0, -1.0),
vec2(-1.0, +1.0),
vec2(+1.0, -1.0),
vec2(+1.0, +1.0)
);
vec2 rotate(vec2 coords, float theta)
{
@ -28,18 +30,24 @@ vec2 rotate(vec2 coords, float theta)
void main()
{
// Draw with 6 indices, gl_VertexIndex will use the appropriate index, iterates through 0-3 and not 0-5
vec2 dst_pos = gl_VertexIndex == 0 ? vec2(in_gui_pos_0.x, in_gui_pos_1.y) :
gl_VertexIndex == 1 ? vec2(in_gui_pos_0.x, in_gui_pos_0.y) :
gl_VertexIndex == 2 ? vec2(in_gui_pos_1.x, in_gui_pos_1.y) :
gl_VertexIndex == 3 ? vec2(in_gui_pos_1.x, in_gui_pos_0.y) : vec2(0.0, 0.0);
ivec2 tex_size = textureSize(sampler2D(SpriteAtlas, SamplerNearest), 0);
out_uv = uvs[gl_VertexIndex];
out_color = in_col;
out_image = in_image;
vec2 dst_half_size = (in_dst_end - in_dst_start) / 2;
vec2 dst_center = (in_dst_end + in_dst_start) / 2;
vec2 dst_pos = (Vertices[gl_VertexIndex] * dst_half_size + dst_center);
gl_Position = vec4(2 * dst_pos.x / G.res.x - 1,
2 * dst_pos.y / G.res.y - 1,
vec2 src_half_size = (in_src_end - in_src_start) / 2;
vec2 src_center = (in_src_end + in_src_start) / 2;
vec2 src_pos = (Vertices[gl_VertexIndex] * src_half_size + src_center);
FragData.color = in_col;
FragData.uv = vec2(
in_src_start.x / tex_size.x,
in_src_start
);
gl_Position = vec4(2 * dst_pos.x / PC.res.x - 1,
2 * dst_pos.y / PC.res.y - 1,
0,
1);
}

View File

@ -58,9 +58,8 @@ void main()
out_col.a = alpha_col.a;
}
FragColor = out_col;
//FragColor = out_col;
/*
//TODO: set up OIT again
vec4 srgb_col = out_col;// UnPreMultLinearToSRGB(out_col);
@ -75,7 +74,6 @@ void main()
}
else
{
FragColor = vec4(out_col.rgb * out_col.a, out_col.a); // Change to vec4(0.0) to disable tail blending
FragColor = vec4(0.0); //vec4(out_col.rgb * out_col.a, out_col.a); // Change to vec4(0.0) to disable tail blending
}
*/
}

View File

@ -5,6 +5,31 @@
#include "structures.layout"
layout (set = 1, binding = 0) uniform texture2D AlbedoTexture;
layout (set = 1, binding = 1) uniform texture2D AmbientTexture;
layout (set = 1, binding = 2) uniform texture2D SpecularTexture;
layout (set = 1, binding = 3) uniform texture2D AlphaTexture;
layout (set = 1, binding = 4) uniform Material {
vec4 ambient;
vec4 diffuse;
vec4 specular;
bool albedo_has_texture;
bool ambient_has_texture;
bool specular_has_texture;
bool alpha_has_texture;
float shininess;
float alpha;
} Materials[];
layout (push_constant) uniform Constants {
mat4 model_matrix;
uint mat_id;
} PC;
layout (location = 0) in vec4 in_col;
layout (location = 1) in vec4 in_tangent;
layout (location = 2) in vec3 in_pos;

View File

@ -1,60 +1,4 @@
// ****************************************************************************
// **** STRUCTS MUST BE PACKED IN OPTIMAL PACKING ORDER TO MATCH D STRUCTS ****
// ****************************************************************************
layout (rgba16f, set = 0, binding = 0) uniform image2D DrawImage;
#define OIT_LAYERS 8
layout (set = 0, binding = 1) uniform sampler SamplerNearest;
layout (set = 0, binding = 0) uniform GlobalUniforms {
mat4 view_matrix;
mat4 projection_matrix;
mat4 projection_view;
vec4 light_color;
vec4 ambient_color;
vec3 light_direction;
vec2 res;
} G;
layout (set = 0, binding = 1) uniform ShaderUniforms {
float placeholder;
} S;
layout (rgba16f, set = 0, binding = 2) uniform image2D DrawImage;
layout (set = 0, binding = 3) uniform sampler SamplerNearest;
#ifdef COMPOSITE_PASS
layout (set = 0, binding = 4, rg32ui) uniform restrict readonly uimageBuffer ImageABuffer;
layout (set = 0, binding = 5, r32ui) uniform restrict readonly uimage2D ImageAux;
#else
layout (set = 0, binding = 4, rg32ui) uniform coherent uimageBuffer ImageABuffer;
layout (set = 0, binding = 5, r32ui) uniform coherent uimage2D ImageAux;
#endif
layout (set = 1, binding = 0) uniform texture2D Textures[];
layout (set = 2, binding = 0) uniform Material {
vec4 ambient;
vec4 diffuse;
vec4 specular;
uint albedo_texture;
uint ambient_texture;
uint specular_texture;
uint alpha_texture;
bool albedo_has_texture;
bool ambient_has_texture;
bool specular_has_texture;
bool alpha_has_texture;
float shininess;
float alpha;
} Materials[];
layout (push_constant) uniform Constants {
mat4 model_matrix;
uint mat_id;
} PC;

View File

@ -8,6 +8,23 @@ import core.simd;
import std.conv;
import std.string;
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
Logf(Args...)(string fmt, Args args)
{