rework descriptors

This commit is contained in:
Matthew 2026-03-07 16:11:16 +11:00
parent 38f7bcf3d6
commit 64673b1bf4

550
vulkan.d
View File

@ -3,6 +3,8 @@ import vulkan_logging;
import vulkan_util;
import std.stdio;
import std.algorithm.comparison;
import std.algorithm.searching : canFind;
import std.traits : isPointer;
import core.stdc.string : strcmp, memcpy;
import core.stdc.stdio : Printf = printf;
import std.format : sformat;
@ -222,33 +224,27 @@ enum ImageLayout : VkImageLayout
alias IL = ImageLayout;
struct Image
{
VkImage image;
VmaAllocation alloc;
Format format;
VkImageLayout layout;
u32 w;
u32 h;
bool depth_image;
ImageUsage usage;
}
struct BufferView
{
Buffer base;
VkBufferView view;
Format format;
alias base this;
}
struct ImageView
{
Image base;
VkImage image;
VkImageView view;
VmaAllocation alloc;
Format format;
ImageUsage usage;
ImageLayout shader_layout;
alias base this;
ImageLayout layout;
u32 w;
u32 h;
u32 ch;
}
struct Buffer
@ -262,18 +258,46 @@ struct Descriptor
{
union
{
Buffer buf;
Image image;
ImageView view;
BufferView buf_view;
Buffer buffer;
ImageView image;
BufferView buffer_view;
VkSampler sampler;
}
};
DescType type;
u32 binding;
u32 index;
bool array_elem;
}
static assert(Descriptor.buffer.buffer.offsetof == Descriptor.buffer_view.base.buffer.offsetof);
struct DescInfo
{
DescType type;
u32 binding;
u32 index;
Format format;
union
{
struct
{
u32 w, h, ch;
ImageUsage usage;
};
struct
{
u64 size;
BufferType buffer_type;
bool host_visible;
};
struct
{
MipmapMode mipmap_mode;
};
};
}
alias Desc = Descriptor;
enum MipmapMode : VkSamplerMipmapMode
{
Nearest = VK_SAMPLER_MIPMAP_MODE_NEAREST,
@ -434,7 +458,7 @@ struct Vulkan
VkRenderPass render_pass;
VkFramebuffer framebuffer;
ImageView[] present_images;
Descriptor[] present_images;
u32 image_index;
Descriptor draw_image;
@ -535,7 +559,7 @@ struct Vulkan
return this.submit_sems[this.image_index];
}
@property ref ImageView
@property ref Descriptor
present_image()
{
return this.present_images[this.image_index];
@ -662,15 +686,7 @@ CreatePipelineLayout(T)(T layouts, u32 push_const_size, bool compute = false) if
}
void
CreateBuffer(Descriptor* desc, BufferType type, u64 size, bool host_visible, DescType desc_type, u32 binding)
{
desc.type = desc_type;
desc.binding = binding;
CreateBuffer(&desc.buf, type, size, host_visible);
}
void
CreateBuffer(Buffer* buf, BufferType type, u64 size, bool host_visible)
CreateBuffer(Buffer* buffer, BufferType type, u64 size, bool host_visible)
{
assert(type != BT.None, "CreateBuffer failure: type is None");
@ -705,11 +721,11 @@ CreateBuffer(Buffer* buf, BufferType type, u64 size, bool host_visible)
}
VmaAllocationInfo vma_info;
VkResult result = vmaCreateBuffer(g_vk.vma, &buffer_info, &alloc_info, &buf.buffer, &buf.alloc, &vma_info);
VkResult result = vmaCreateBuffer(g_vk.vma, &buffer_info, &alloc_info, &buffer.buffer, &buffer.alloc, &vma_info);
// TODO: handle errors here then reallocate buffer
VkCheck("CreateBuffer failure: vmaCreateBuffer error", result);
buf.size = size;
buffer.size = size;
}
void
@ -805,7 +821,7 @@ BeginRendering()
Transition(g_vk.cmd, &g_vk.draw_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
Transition(g_vk.cmd, &g_vk.depth_image, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
VkImage image = g_vk.present_image.image;
VkImage image = g_vk.present_image.image.image;
Transition(g_vk.cmd, image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkClearValue[2] clear_color = [
@ -846,12 +862,6 @@ GetAspect()
return cast(f32)(g_vk.swapchain_extent.width) / cast(f32)(g_vk.swapchain_extent.height);
}
void
PrepAuxImage(ImageView* view)
{
Transition(g_vk.cmd, view, VK_IMAGE_LAYOUT_GENERAL);
}
void
PrepComputeDrawImage()
{
@ -873,7 +883,7 @@ SubmitAndPresent()
g_vk.frame_index = (g_vk.frame_index + 1) % FRAME_OVERLAP;
}
VkImage image = g_vk.present_image.image;
VkImage image = g_vk.present_image.image.image;
VkSemaphore acquire_sem = g_vk.acquire_sem;
VkSemaphore submit_sem = g_vk.submit_sem;
@ -885,7 +895,7 @@ SubmitAndPresent()
};
// TODO: Find out how to copy from same dimension images (pretty sure its not blitting)
Copy(g_vk.cmd, &g_vk.draw_image.view.base, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, extent, extent);
Copy(g_vk.cmd, &g_vk.draw_image, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, extent, extent);
Transition(g_vk.cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
@ -1007,13 +1017,13 @@ ImmSubmitFinish()
}
bool
ImmSubmit(Image* image, VkBufferImageCopy copy, void function(Image*, VkBufferImageCopy) fn)
ImmSubmit(Descriptor* desc, VkBufferImageCopy copy, void function(Descriptor*, VkBufferImageCopy) fn)
{
bool success = ImmSubmitStart();
if(success)
{
fn(image, copy);
fn(desc, copy);
VkResult result = vkEndCommandBuffer(g_vk.imm_cmd);
success = VkCheck("ImmSubmit failure: vkEndCommandBuffer error", result);
@ -1028,13 +1038,13 @@ ImmSubmit(Image* image, VkBufferImageCopy copy, void function(Image*, VkBufferIm
}
bool
ImmSubmit(Buffer* buf, VkBufferCopy copy, void function(Buffer*, VkBufferCopy) fn)
ImmSubmit(Descriptor* desc, VkBufferCopy copy, void function(Descriptor*, VkBufferCopy) fn)
{
bool success = ImmSubmitStart();
if(success)
{
fn(buf, copy);
fn(desc, copy);
VkResult result = vkEndCommandBuffer(g_vk.imm_cmd);
success = VkCheck("ImmSubmit failure: vkEndCommandBuffer error", result);
@ -1061,70 +1071,111 @@ WaitForTransfers()
}
void
CreateImageView(Descriptor* view, u32 w, u32 h, u32 ch, u8[] data, DescType type = DT.Image, u32 binding, u32 index)
CreateDescriptor(T = u8[])(Descriptor* desc, DescInfo info, T data = null) if(is(T: u8[]) || isPointer!(T))
{
view.array_elem = true;
view.index = index;
CreateImageView(view, w, h, ch, data, type, binding);
enum DescType[] image_types = [DT.CombinedSampler, DT.Image, DT.StorageImage, DT.InputAttach];
enum DescType[] texel_types = [DT.UniformTexelBuf, DT.StorageTexelBuf];
enum DescType[] buffer_types = [DT.Uniform, DT.DynamicUniform, DT.Storage, DT.DynamicStorage];
desc.type = info.type;
desc.binding = info.binding;
desc.index = info.index;
if(canFind(image_types, info.type))
{
desc.image.usage = info.usage;
desc.image.format = info.format;
desc.image.layout = IL.Undefined;
desc.image.w = info.w;
desc.image.h = info.h;
desc.image.ch = info.ch;
static if(is(T: u8[]))
{
if(data.length)
{
CreateImageView(desc, data);
}
else
{
CreateImageView(desc);
}
}
else
{
CreateImageView(desc);
}
}
else if(canFind(texel_types, info.type))
{
desc.buffer_view.size = info.size;
desc.buffer_view.format = info.format;
CreateBufferView(desc);
if(data)
{
Transfer(desc, data);
}
}
else if(canFind(buffer_types, info.type))
{
CreateBuffer(&desc.buffer, info.buffer_type, info.size, info.host_visible);
if(data)
{
Transfer(desc, data);
}
}
else if(info.type == DT.Sampler)
{
CreateSampler(desc, info.mipmap_mode);
}
else assert(false, "Unknown descriptor type in CreateDescriptor");
}
void
CreateImageView(Descriptor* view, u32 w, u32 h, u32 ch, u8[] data, DescType type = DT.Image, u32 binding)
CreateImageView(Descriptor* desc, u8[] data)
{
ImageDescCheck(type);
view.type = type;
view.binding = binding;
CreateImageView(&view.view, w, h, ch, data);
}
CreateImageView(desc);
void
CreateImageViewTex(Descriptor* desc, u32 w, u32 h, DescType type = DT.Image, u32 binding, u32 index)
if(desc.image.ch == 4)
{
desc.array_elem = true;
desc.index = index;
CreateImageViewTex(desc, w, h, type, binding);
}
void
CreateImageViewTex(Descriptor* desc, u32 w, u32 h, DescType type = DT.Image, u32 binding)
{
ImageDescCheck(type);
desc.type = type;
desc.binding = binding;
CreateImageView(&desc.view, w, h, FMT.RGBA_UNORM, IU.Texture);
}
void
CreateImageView(ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
{
CreateImageView(view, w, h, FMT.RGBA_UNORM, IU.Texture);
if(ch == 4)
{
bool result = Transfer(view, data, w, h);
bool result = Transfer!(true)(desc, data);
assert(result);
}
else
{
Descriptor buf;
CreateBuffer(&buf, BT.Storage, w * h * ch, false, DT.Storage, 1);
bool result = Transfer(&buf.buf, data);
CreateDescriptor(&buf, DescInfo(
type: DT.Storage,
buffer_type: BT.Storage,
size: desc.image.w * desc.image.h * desc.image.ch,
binding: 1,
));
bool result = Transfer(&buf.buffer, data);
assert(result, "CreateImageView failure: Buffer Transfer error");
Descriptor conv_view;
CreateImageView(&conv_view, w, h, FMT.RGBA_F32, IU.Convert, DT.StorageImage, 0);
CreateDescriptor(&conv_view, DescInfo(
type: DT.StorageImage,
w: desc.image.w,
h: desc.image.h,
format: FMT.RGBA_F32,
usage: IU.Convert,
));
Write(g_vk.conv_desc_set, [conv_view, buf]);
BeginComputePass();
Pipeline pipeline = ch == 1 ? g_vk.r_to_rgba_pipeline :
ch == 2 ? g_vk.rg_to_rgba_pipeline :
Pipeline pipeline = desc.image.ch == 1 ? g_vk.r_to_rgba_pipeline :
desc.image.ch == 2 ? g_vk.rg_to_rgba_pipeline :
g_vk.rgb_to_rgba_pipeline;
Bind(pipeline, g_vk.conv_desc_set, true);
ConvPushConst pc = { x: w, y: h };
ConvPushConst pc = { x: desc.image.w, y: desc.image.h };
vkCmdPushConstants(
g_vk.comp_cmd,
@ -1139,12 +1190,12 @@ CreateImageView(ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
Dispatch(g_vk.comp_cmd);
Transition(g_vk.comp_cmd, view, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
Transition(g_vk.comp_cmd, desc, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkExtent2D extent = { width: w, height: h };
Copy(g_vk.comp_cmd, &conv_view.view.base, &view.base, extent, extent);
VkExtent2D extent = { width: desc.image.w, height: desc.image.h };
Copy(g_vk.comp_cmd, &conv_view, desc, extent, extent);
Transition(g_vk.comp_cmd, view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
Transition(g_vk.comp_cmd, desc, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
FinishComputePass();
@ -1157,26 +1208,8 @@ CreateImageView(ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
}
}
void
CreateImageView(Descriptor* desc, u32 w, u32 h, Format format, ImageUsage usage, DescType type, u32 binding, u32 index)
{
desc.array_elem = true;
desc.index = index;
CreateImageView(desc, w, h, format, usage, type, binding);
}
void
CreateImageView(Descriptor* desc, u32 w, u32 h, Format format, ImageUsage usage, DescType type, u32 binding)
{
ImageDescCheck(type);
desc.type = type;
desc.binding = binding;
CreateImageView(&desc.view, w, h, format, usage);
}
void
CreateImageView(ImageView* view, u32 w, u32 h, Format format, ImageUsage usage)
CreateImageView(Descriptor* desc)
{
VmaAllocationCreateInfo alloc_info = {
usage: VMA_MEMORY_USAGE_GPU_ONLY,
@ -1188,14 +1221,14 @@ CreateImageView(ImageView* view, u32 w, u32 h, Format format, ImageUsage usage)
imageType: VK_IMAGE_TYPE_2D,
mipLevels: 1,
arrayLayers: 1,
format: format,
format: desc.image.format,
tiling: VK_IMAGE_TILING_OPTIMAL,
initialLayout: VK_IMAGE_LAYOUT_UNDEFINED,
usage: usage,
usage: desc.image.usage,
samples: VK_SAMPLE_COUNT_1_BIT,
extent: {
width: w,
height: h,
width: desc.image.w,
height: desc.image.h,
depth: 1,
},
};
@ -1208,42 +1241,37 @@ CreateImageView(ImageView* view, u32 w, u32 h, Format format, ImageUsage usage)
image_info.pQueueFamilyIndices = indices.ptr;
}
VkResult result = vmaCreateImage(g_vk.vma, &image_info, &alloc_info, &view.image, &view.alloc, null);
VkResult result = vmaCreateImage(g_vk.vma, &image_info, &alloc_info, &desc.image.image, &desc.image.alloc, null);
// TODO: handle errors and realloc
VkCheck("CreateImageView failure: vmaCreateImage error", result);
VkImageViewCreateInfo view_info = {
sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
image: view.image,
image: desc.image.image,
viewType: VK_IMAGE_VIEW_TYPE_2D,
format: format,
format: desc.image.format,
subresourceRange: {
aspectMask: (usage == IU.Depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
aspectMask: (desc.image.usage == IU.Depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
levelCount: 1,
layerCount: 1,
},
};
result = vkCreateImageView(g_vk.device, &view_info, null, &view.view);
result = vkCreateImageView(g_vk.device, &view_info, null, &desc.image.view);
// TODO: also handle here
VkCheck("CreateImageView failure: vkCreateImageView error", result);
view.layout = VK_IMAGE_LAYOUT_UNDEFINED;
view.format = format;
view.w = w;
view.h = h;
view.depth_image = usage == IU.Depth;
view.usage = usage;
if(usage == IU.Draw || usage == IU.Depth || usage == IU.Convert)
if(desc.image.usage == IU.Draw || desc.image.usage == IU.Depth || desc.image.usage == IU.Convert)
{
view.shader_layout = IL.General;
desc.image.shader_layout = IL.General;
}
else if(usage == IU.Texture)
else if(desc.image.usage == IU.Texture)
{
view.shader_layout = IL.ReadOnly;
desc.image.shader_layout = IL.ReadOnly;
}
else assert(false, "Unimplemented usage");
desc.image.layout = IL.Undefined;
}
void
@ -1290,22 +1318,19 @@ FinishComputePass()
}
void
CreateBufferView(Descriptor* desc, u64 size, Format format, DescType type, u32 binding)
CreateBufferView(Descriptor* desc)
{
CreateBuffer(&desc.buf_view.base, BT.BufferView, size, false);
CreateBuffer(&desc.buffer_view.base, BT.BufferView, desc.buffer_view.size, false);
VkBufferViewCreateInfo info = {
sType: VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
buffer: desc.buf_view.buffer,
format: format,
range: size,
buffer: desc.buffer_view.buffer,
format: desc.buffer_view.format,
range: desc.buffer_view.size,
};
VkResult result = vkCreateBufferView(g_vk.device, &info, null, &desc.buf_view.view);
VkResult result = vkCreateBufferView(g_vk.device, &info, null, &desc.buffer_view.view);
VkCheckA("CreateBufferView failure: vkCreateBufferView failed", result);
desc.binding = binding;
desc.buf_view.size = size;
}
void
@ -1349,54 +1374,20 @@ ImageBarrier()
}
bool
Transfer(T)(Buffer* buf, T[] data)
Transfer(T, U)(T* dst, U[] data)
{
static if(is(T: Descriptor))
{
Buffer* buffer = &dst.buffer;
}
else static if(is(T: Buffer))
{
Buffer* buffer = dst;
}
else static assert(false, "Invalid type for transfer target");
u8[] u8_data = (cast(u8*)(data.ptr))[0 .. T.sizeof * data.length];
return Transfer(buf, u8_data);
}
bool
Transfer(Buffer* buf, u8[] data)
{
bool success = TransferReady();
u64 copied = 0;
while(copied != data.length && success)
{
if(copied != 0)
{
success = TransferReady();
if(!success)
{
break;
}
}
u64 transfer_length = cast(u64)g_vk.transfer_buf.data.length;
u64 data_length = cast(u64)data.length - copied;
u64 copy_length = transfer_length > data_length ? data_length : transfer_length;
g_vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length];
auto fn = function(Buffer* buf, VkBufferCopy copy)
{
vkCmdCopyBuffer(g_vk.imm_cmd, g_vk.transfer_buf.buffer, buf.buffer, 1, &copy);
};
VkBufferCopy copy = {
srcOffset: 0,
dstOffset: copied,
size: copy_length,
};
success = ImmSubmit(buf, copy, fn);
copied += copy_length;
}
WaitForTransfers();
return success;
return Transfer(buffer, u8_data);
}
bool
@ -1437,13 +1428,7 @@ TransferReady()
}
bool
Transfer(ImageView* view, u8[] data, u32 w, u32 h)
{
return Transfer(&view.base, data, w, h);
}
bool
Transfer(Image* image, u8[] data, u32 w, u32 h)
Transfer(bool image)(Descriptor* desc, u8[] data)
{
bool success = true;
@ -1456,32 +1441,47 @@ Transfer(Image* image, u8[] data, u32 w, u32 h)
g_vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length];
auto fn = function(Image* image, VkBufferImageCopy copy)
static if(image)
{
Transition(g_vk.imm_cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
auto fn = function(Descriptor* desc, VkBufferImageCopy copy)
{
Transition(g_vk.imm_cmd, desc, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkCmdCopyBufferToImage(g_vk.imm_cmd, g_vk.transfer_buf.buffer, image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
vkCmdCopyBufferToImage(g_vk.imm_cmd, g_vk.transfer_buf.buffer, desc.image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
Transition(g_vk.imm_cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
Transition(g_vk.imm_cmd, desc, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
};
VkBufferImageCopy copy = {
bufferRowLength: w,
bufferImageHeight: h,
bufferRowLength: desc.image.w,
bufferImageHeight: desc.image.h,
imageSubresource: {
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
layerCount: 1,
},
imageExtent: {
width: w,
height: h,
width: desc.image.w,
height: desc.image.h,
depth: 1,
},
bufferOffset: copied,
};
}
else
{
auto fn = function(Descriptor* desc, VkBufferCopy copy)
{
vkCmdCopyBuffer(g_vk.imm_cmd, g_vk.transfer_buf.buffer, desc.buffer.buffer, 1, &copy);
};
success = ImmSubmit(image, copy, fn);
VkBufferCopy copy = {
srcOffset: 0,
dstOffset: copied,
size: copy_length,
};
}
success = ImmSubmit(desc, copy, fn);
copied += copy_length;
}
@ -1491,15 +1491,15 @@ Transfer(Image* image, u8[] data, u32 w, u32 h)
}
void
Copy(VkCommandBuffer cmd, Image* src, Image* dst, VkExtent2D src_ext, VkExtent2D dst_ext)
Copy(VkCommandBuffer cmd, Descriptor* src, Descriptor* dst, VkExtent2D src_ext, VkExtent2D dst_ext)
{
Copy(cmd, src.image, dst.image, src.layout, dst.layout, src_ext, dst_ext);
Copy(cmd, src.image.image, dst.image.image, src.image.layout, dst.image.layout, src_ext, dst_ext);
}
void
Copy(VkCommandBuffer cmd, Image* src, VkImage dst, VkImageLayout dst_layout, VkExtent2D src_ext, VkExtent2D dst_ext)
Copy(VkCommandBuffer cmd, Descriptor* src, VkImage dst, VkImageLayout dst_layout, VkExtent2D src_ext, VkExtent2D dst_ext)
{
Copy(cmd, src.image, dst, src.layout, dst_layout, src_ext, dst_ext);
Copy(cmd, src.image.image, dst, src.image.layout, dst_layout, src_ext, dst_ext);
}
void
@ -1696,6 +1696,12 @@ ResetScissor(VkCommandBuffer cmd = cast(VkCommandBuffer)VK_NULL_HANDLE)
vkCmdSetScissor(cmd, 0, 1, &scissor);
}
void
Transition(VkCommandBuffer cmd, Descriptor* desc, VkImageLayout new_layout)
{
ImageDescCheck(desc);
Transition(cmd, desc.image.image, desc.image.layout, new_layout);
}
void
Transition(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout)
@ -1727,16 +1733,14 @@ Transition(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkI
vkCmdPipelineBarrier2(cmd, &dep_info);
}
void
bool
ImageDescCheck(Descriptor* desc)
{
ImageDescCheck(desc.type);
return ImageDescCheck(desc.type);
}
void
bool
ImageDescCheck(DescType desc_type)
{
debug
{
bool match;
enum types = [DT.CombinedSampler, DT.Image, DT.StorageImage, DT.InputAttach];
@ -1745,29 +1749,7 @@ ImageDescCheck(DescType desc_type)
match |= desc_type == type;
}
assert(match, "Unable to transition non image");
}
}
void
Transition(VkCommandBuffer cmd, Descriptor* desc, VkImageLayout new_layout)
{
ImageDescCheck(desc);
Transition(cmd, &desc.view, new_layout);
}
void
Transition(VkCommandBuffer cmd, ImageView* view, VkImageLayout new_layout)
{
Transition(cmd, view.image, view.layout, new_layout);
view.layout = new_layout;
}
void
Transition(VkCommandBuffer cmd, Image* image, VkImageLayout new_layout)
{
Transition(cmd, image.image, image.layout, new_layout);
image.layout = new_layout;
return match;
}
bool
@ -1787,6 +1769,7 @@ bool
CreateGraphicsPipeline(Pipeline* pipeline_handle, GfxPipelineInfo* build_info)
{
PipelineHandles* pipeline = NewPipeline();
pipeline.type = VK_PIPELINE_BIND_POINT_GRAPHICS;
pipeline.layout = build_info.layout;
@ -1839,8 +1822,8 @@ CreateGraphicsPipeline(Pipeline* pipeline_handle, GfxPipelineInfo* build_info)
VkPipelineRenderingCreateInfo rendering_info = {
sType: VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
colorAttachmentCount: 1,
pColorAttachmentFormats: cast(VkFormat*)&g_vk.draw_image.view.format,
depthAttachmentFormat: g_vk.depth_image.view.format,
pColorAttachmentFormats: cast(VkFormat*)&g_vk.draw_image.image.format,
depthAttachmentFormat: g_vk.depth_image.image.format,
};
VkPipelineColorBlendAttachmentState blend_state = {
@ -2043,24 +2026,17 @@ ClearColor(f32[4] color)
void
ClearColor(Descriptor* desc, f32[4] color)
{
ImageDescCheck(desc);
ClearColor(&desc.view, color);
}
void
ClearColor(ImageView* view, f32[4] color)
{
VkImageSubresourceRange clear_range = {
aspectMask: (view.depth_image ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
aspectMask: (desc.image.usage == IU.Depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
levelCount: 1,
layerCount: 1,
};
vkCmdClearColorImage(
g_vk.cmd,
view.image,
view.layout,
desc.image.image,
desc.image.layout,
cast(VkClearColorValue*)color,
1,
&clear_range
@ -2150,11 +2126,7 @@ PrepareWrite(VkWriteDescriptorSet* write, DescSet set, Descriptor* desc)
write.dstSet = set.handle;
write.dstBinding = desc.binding;
write.descriptorCount = 1;
if(desc.array_elem)
{
write.dstArrayElement = desc.index;
}
switch(desc.type) with(DescType)
{
@ -2162,22 +2134,22 @@ PrepareWrite(VkWriteDescriptorSet* write, DescSet set, Descriptor* desc)
{
VkDescriptorImageInfo* info = Alloc!(VkDescriptorImageInfo)(arena);
info.imageView = desc.view.view;
info.imageLayout = desc.view.shader_layout;
info.imageView = desc.image.view;
info.imageLayout = desc.image.shader_layout;
write.pImageInfo = info;
} break;
case Uniform, Storage:
{
VkDescriptorBufferInfo* info = Alloc!(VkDescriptorBufferInfo)(arena);
info.buffer = desc.buf.buffer;
info.buffer = desc.buffer.buffer;
info.offset = cast(VkDeviceSize)0;
info.range = cast(VkDeviceSize)desc.buf.size;
info.range = cast(VkDeviceSize)desc.buffer.size;
write.pBufferInfo = info;
} break;
case UniformTexelBuf, StorageTexelBuf:
{
write.pTexelBufferView = &desc.buf_view.view;
write.pTexelBufferView = &desc.buffer_view.view;
} break;
case Sampler:
{
@ -2371,8 +2343,8 @@ SelectSwapchainFormats()
g_vk.present_mode = present_mode;
}
Descriptor
CreateSampler(MipmapMode mode, u32 binding)
void
CreateSampler(Descriptor* desc, MipmapMode mode)
{
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(g_vk.physical_device, &props);
@ -2391,15 +2363,8 @@ CreateSampler(MipmapMode mode, u32 binding)
mipmapMode: mode,
};
Descriptor sampler = {
type: DT.Sampler,
binding: binding,
};
VkResult result = vkCreateSampler(g_vk.device, &sampler_info, null, &sampler.sampler);
VkResult result = vkCreateSampler(g_vk.device, &sampler_info, null, &desc.sampler);
VkCheckA("vkCreateSampler failure", result);
return sampler;
}
bool
@ -2413,8 +2378,8 @@ CreateDrawImages()
u32 w = g_vk.swapchain_extent.width;
u32 h = g_vk.swapchain_extent.height;
CreateImageView(&g_vk.draw_image, w, h, draw_format, IU.Draw, DT.StorageImage, 0);
CreateImageView(&g_vk.depth_image, w, h, depth_format, IU.Depth, DT.Image, 0);
CreateDescriptor(&g_vk.draw_image, DescInfo(type: DT.StorageImage, format: draw_format, usage: IU.Draw, w: w, h: h, binding: 0));
CreateDescriptor(&g_vk.depth_image, DescInfo(type: DT.Image, format: depth_format, usage: IU.Depth, w: w, h: h, binding: 0));
return success;
}
@ -2448,12 +2413,12 @@ CreateSwapchain()
surface: g_vk.surface,
imageFormat: g_vk.surface_format.format,
imageColorSpace: g_vk.surface_format.colorSpace,
preTransform: cap.currentTransform,
presentMode: g_vk.present_mode,
imageExtent: {
width: w,
height: h,
},
preTransform: cap.currentTransform,
presentMode: g_vk.present_mode,
};
VkResult result = vkCreateSwapchainKHR(g_vk.device, &info, null, &g_vk.swapchain);
@ -2465,7 +2430,7 @@ CreateSwapchain()
vkGetSwapchainImagesKHR(g_vk.device, g_vk.swapchain, &count, images.ptr);
VkImageView[] views = Alloc!(VkImageView)(arena, count);
g_vk.present_images = Alloc!(ImageView)(&g_vk.arena, count);
g_vk.present_images = Alloc!(Descriptor)(&g_vk.arena, count);
VkImageViewCreateInfo view_info = {
sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@ -2485,18 +2450,17 @@ CreateSwapchain()
},
};
VkFramebufferCreateInfo framebuffer_info = {
sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
};
VkFramebufferCreateInfo framebuffer_info = { sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
foreach(i, image; g_vk.present_images)
foreach(i; 0 .. g_vk.present_images.length)
{
g_vk.present_images[i].image = images[i];
g_vk.present_images[i].format = cast(Format)g_vk.surface_format.format;
g_vk.present_images[i].image.image = images[i];
g_vk.present_images[i].image.format = cast(Format)g_vk.surface_format.format;
view_info.image = images[i];
view_info.format = g_vk.surface_format.format;
result = vkCreateImageView(g_vk.device, &view_info, null, &g_vk.present_images[i].view);
result = vkCreateImageView(g_vk.device, &view_info, null, &g_vk.present_images[i].image.view);
success = VkCheck("vkCreateImageView failure", result);
}
@ -2537,7 +2501,7 @@ CreateFramebuffer()
sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
renderPass: g_vk.render_pass,
attachmentCount: 2,
pAttachments: [g_vk.draw_image.view.view, g_vk.depth_image.view.view],
pAttachments: [g_vk.draw_image.image.view, g_vk.depth_image.image.view],
width: g_vk.swapchain_extent.width,
height: g_vk.swapchain_extent.height,
layers: 1,
@ -2571,33 +2535,33 @@ Destroy(Descriptor* desc)
} break;
case DT.CombinedSampler, DT.Image, DT.StorageImage, DT.InputAttach:
{
if(desc.view.view)
if(desc.image.view)
{
vkDestroyImageView(g_vk.device, desc.view.view, null);
vkDestroyImageView(g_vk.device, desc.image.view, null);
}
if(desc.view.image)
if(desc.image.image)
{
vmaDestroyImage(g_vk.vma, desc.view.image, desc.view.alloc);
vmaDestroyImage(g_vk.vma, desc.image.image, desc.image.alloc);
}
} break;
case DT.UniformTexelBuf, DT.StorageTexelBuf:
{
if(desc.buf_view.view)
if(desc.buffer_view.view)
{
vkDestroyBufferView(g_vk.device, desc.buf_view.view, null);
vkDestroyBufferView(g_vk.device, desc.buffer_view.view, null);
}
if(desc.buf_view.buffer)
if(desc.buffer_view.buffer)
{
vmaDestroyBuffer(g_vk.vma, desc.buf_view.buffer, desc.buf_view.alloc);
vmaDestroyBuffer(g_vk.vma, desc.buffer_view.buffer, desc.buffer_view.alloc);
}
} break;
case DT.Uniform, DT.DynamicUniform, DT.Storage, DT.DynamicStorage:
{
if(desc.buf.buffer)
if(desc.buffer.buffer)
{
vmaDestroyBuffer(g_vk.vma, desc.buf.buffer, desc.buf.alloc);
vmaDestroyBuffer(g_vk.vma, desc.buffer.buffer, desc.buffer.alloc);
}
} break;
default: assert(false, "Unsupported descriptor Destroy call");
@ -2643,13 +2607,13 @@ Destroy(VkSurfaceKHR surface, VkInstance instance)
}
void
Destroy(VkSwapchainKHR swapchain, ImageView[] views, VkDevice device)
Destroy(VkSwapchainKHR swapchain, Descriptor[] images, VkDevice device)
{
foreach(view; views)
foreach(ref image; images)
{
if(view.view)
if(image.image.view)
{
vkDestroyImageView(device, view.view, null);
vkDestroyImageView(device, image.image.view, null);
}
}
@ -3341,7 +3305,7 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem)
VkAttachmentDescription[2] attach_descriptions = [
{
format: g_vk.draw_image.view.format,
format: g_vk.draw_image.image.format,
samples: VK_SAMPLE_COUNT_1_BIT,
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
storeOp: VK_ATTACHMENT_STORE_OP_STORE,
@ -3351,7 +3315,7 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem)
finalLayout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
},
{
format: g_vk.depth_image.view.format,
format: g_vk.depth_image.image.format,
samples: VK_SAMPLE_COUNT_1_BIT,
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
storeOp: VK_ATTACHMENT_STORE_OP_STORE,