commit before deleting shaders
This commit is contained in:
parent
194149f8dd
commit
92980fba0d
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
131
src/gears/game.d
131
src/gears/game.d
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
@ -1422,6 +1418,7 @@ Bind(Vulkan* vk, PipelineHandle* pipeline)
|
||||
|
||||
vkCmdSetScissor(vk.cmds[vk.frame_index], 0, 1, &scissor);
|
||||
}
|
||||
}
|
||||
|
||||
pragma(inline): void
|
||||
Transition(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout)
|
||||
@ -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;
|
||||
|
||||
@ -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
5
src/shaders/gui.layout
Normal file
@ -0,0 +1,5 @@
|
||||
layout (set = 1, binding = 0) uniform texture2D SpriteAtlas;
|
||||
|
||||
layout (push_constant) uniform Constants {
|
||||
vec2 res;
|
||||
} PC;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user