Drawing a textured quad
Added new assets Loaded all texture assets into game state Loaded the basic pipeline Setup a hard-coded quad to test drawing Created a very jank vertex struct Added ReadEntireFile for filesystem Added getting file size from file handle Added a descriptor pool to each in flight frame Changed Vk_BufferCreate to handle multiple uses Added shader building to the windows.bat build script
This commit is contained in:
@@ -354,6 +354,23 @@ bool Vk_Setup(SDL_Window *window) {
|
||||
err = Min(vk.CreateFence(vk.device, &fence, 0, &frame->scratch[s].fence), err);
|
||||
}
|
||||
|
||||
// Descriptor pool
|
||||
VkDescriptorPoolSize pool_sizes[2] = { 0 };
|
||||
|
||||
pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
pool_sizes[0].descriptorCount = 2048;
|
||||
|
||||
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
pool_sizes[1].descriptorCount = 2048;
|
||||
|
||||
VkDescriptorPoolCreateInfo descriptor_pool = { 0 };
|
||||
descriptor_pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
descriptor_pool.maxSets = 1024;
|
||||
descriptor_pool.poolSizeCount = 2;
|
||||
descriptor_pool.pPoolSizes = pool_sizes;
|
||||
|
||||
vk.CreateDescriptorPool(vk.device, &descriptor_pool, 0, &frame->descriptors);
|
||||
|
||||
VkSemaphoreCreateInfo semaphore = { 0 };
|
||||
semaphore.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
||||
@@ -364,6 +381,16 @@ bool Vk_Setup(SDL_Window *window) {
|
||||
vk.err = err;
|
||||
}
|
||||
|
||||
{
|
||||
VkSamplerCreateInfo create_info = { 0 };
|
||||
create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
create_info.magFilter = VK_FILTER_NEAREST;
|
||||
create_info.minFilter = VK_FILTER_NEAREST;
|
||||
create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
|
||||
vk.CreateSampler(vk.device, &create_info, 0, &vk.sampler);
|
||||
}
|
||||
|
||||
result = (vk.err == VK_SUCCESS);
|
||||
return result;
|
||||
}
|
||||
@@ -376,6 +403,7 @@ Vk_Frame *Vk_FrameBegin(SDL_Window *window) {
|
||||
|
||||
vk.ResetFences(vk.device, 1, &frame->fence);
|
||||
vk.ResetCommandPool(vk.device, frame->pool, 0);
|
||||
vk.ResetDescriptorPool(vk.device, frame->descriptors, 0);
|
||||
|
||||
VkResult res = vk.AcquireNextImageKHR(vk.device, vk.swapchain.handle, UINT64_MAX, frame->acquire, 0, &frame->image);
|
||||
(void) res; // @Todo: check res to see if swapchain is out of date and rebuild
|
||||
@@ -492,9 +520,7 @@ void Vk_CommandBufferSubmit(Vk_CommandBuffer *cmds, B32 wait) {
|
||||
|
||||
vk.QueueSubmit(vk.queue.handle, 1, &submit_info, cmds->fence);
|
||||
|
||||
if (wait) {
|
||||
vk.DeviceWaitIdle(vk.device);
|
||||
}
|
||||
if (wait) { vk.DeviceWaitIdle(vk.device); }
|
||||
}
|
||||
|
||||
#define VK_HOST_VISIBLE_FLAGS (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||
@@ -532,31 +558,27 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty
|
||||
return result;
|
||||
}
|
||||
|
||||
Vk_Buffer Vk_BufferCreate(U64 size, B32 host_visible) {
|
||||
Vk_Buffer result = { 0 };
|
||||
|
||||
void Vk_BufferCreate(Vk_Buffer *buffer) {
|
||||
VkBufferCreateInfo create_info = { 0 };
|
||||
create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
create_info.size = size;
|
||||
create_info.usage = buffer->usage;
|
||||
create_info.size = buffer->size;
|
||||
|
||||
vk.CreateBuffer(vk.device, &create_info, 0, &result.handle);
|
||||
vk.CreateBuffer(vk.device, &create_info, 0, &buffer->handle);
|
||||
|
||||
VkMemoryRequirements req;
|
||||
vk.GetBufferMemoryRequirements(vk.device, result.handle, &req);
|
||||
vk.GetBufferMemoryRequirements(vk.device, buffer->handle, &req);
|
||||
|
||||
VkMemoryPropertyFlags usage = host_visible ? VK_HOST_VISIBLE_FLAGS : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
VkMemoryPropertyFlags usage = buffer->host_visible ? VK_HOST_VISIBLE_FLAGS : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
|
||||
result.size = req.size;
|
||||
result.memory = Vk_Allocate(&req, usage);
|
||||
buffer->size = req.size;
|
||||
buffer->memory = Vk_Allocate(&req, usage);
|
||||
|
||||
vk.BindBufferMemory(vk.device, result.handle, result.memory, 0);
|
||||
vk.BindBufferMemory(vk.device, buffer->handle, buffer->memory, 0);
|
||||
|
||||
if (host_visible) {
|
||||
vk.MapMemory(vk.device, result.memory, 0, result.size, 0, &result.data);
|
||||
if (buffer->host_visible) {
|
||||
vk.MapMemory(vk.device, buffer->memory, 0, buffer->size, 0, &buffer->data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Vk_ImageCreate(Vk_Image *image) {
|
||||
@@ -595,3 +617,95 @@ void Vk_ImageCreate(Vk_Image *image) {
|
||||
|
||||
vk.CreateImageView(vk.device, &view_info, 0, &image->view);
|
||||
}
|
||||
|
||||
void Vk_PipelineCreate(Vk_Pipeline *pipeline) {
|
||||
VkPipelineInputAssemblyStateCreateInfo ia = { 0 };
|
||||
ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaders[8] = { 0 };
|
||||
for (U32 it = 0; it < pipeline->shaders.count; ++it) {
|
||||
shaders[it].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shaders[it].stage = pipeline->shaders.items[it].stage;
|
||||
shaders[it].module = pipeline->shaders.items[it].handle;
|
||||
shaders[it].pName = "main";
|
||||
}
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vi = { 0 };
|
||||
vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
|
||||
// This will be updated later using dynamic commands but we still need to supply one here for
|
||||
// some reason
|
||||
VkViewport viewport = { 0, 0, 10, 10, 0, 1 };
|
||||
VkRect2D scissor = { 0, 0, 10, 10 };
|
||||
|
||||
VkPipelineViewportStateCreateInfo vp = { 0 };
|
||||
vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
vp.viewportCount = 1;
|
||||
vp.pViewports = &viewport;
|
||||
vp.scissorCount = 1;
|
||||
vp.pScissors = &scissor;
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo rs = { 0 };
|
||||
rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rs.lineWidth = 1.0f;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo ms = { 0 };
|
||||
ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo ds = { 0 };
|
||||
ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
|
||||
VkPipelineColorBlendAttachmentState blend = { 0 };
|
||||
blend.blendEnable = VK_TRUE;
|
||||
blend.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blend.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blend.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blend.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
blend.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo om = { 0 };
|
||||
om.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
om.attachmentCount = 1;
|
||||
om.pAttachments = &blend;
|
||||
|
||||
VkDynamicState dynamic_state[] = {
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR
|
||||
};
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dyn = { 0 };
|
||||
dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dyn.dynamicStateCount = ArraySize(dynamic_state);
|
||||
dyn.pDynamicStates = dynamic_state;
|
||||
|
||||
VkFormat formats[8];
|
||||
for (U32 it = 0; it < pipeline->targets.count; ++it) {
|
||||
formats[it] = pipeline->targets.items[it];
|
||||
}
|
||||
|
||||
VkPipelineRenderingCreateInfo rendering_info = { 0 };
|
||||
rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
|
||||
rendering_info.colorAttachmentCount = pipeline->targets.count;
|
||||
rendering_info.pColorAttachmentFormats = formats;
|
||||
|
||||
VkGraphicsPipelineCreateInfo create_info = { 0 };
|
||||
create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
create_info.pNext = &rendering_info;
|
||||
create_info.stageCount = pipeline->shaders.count;
|
||||
create_info.pStages = shaders;
|
||||
create_info.pVertexInputState = &vi;
|
||||
create_info.pInputAssemblyState = &ia;
|
||||
create_info.pViewportState = &vp;
|
||||
create_info.pRasterizationState = &rs;
|
||||
create_info.pMultisampleState = &ms;
|
||||
create_info.pDepthStencilState = &ds;
|
||||
create_info.pColorBlendState = &om;
|
||||
create_info.pDynamicState = &dyn;
|
||||
create_info.layout = pipeline->layout.pipeline;
|
||||
|
||||
vk.CreateGraphicsPipelines(vk.device, 0, 1, &create_info, 0, &pipeline->handle);
|
||||
}
|
||||
|
||||
@@ -25,26 +25,6 @@
|
||||
#define VK_MAX_FRAMES_IN_FLIGHT 8
|
||||
#define VK_NUM_SCRATCH 8
|
||||
|
||||
typedef struct Vk_CommandBuffer Vk_CommandBuffer;
|
||||
struct Vk_CommandBuffer {
|
||||
VkCommandBuffer handle;
|
||||
VkFence fence;
|
||||
};
|
||||
|
||||
typedef struct Vk_Frame Vk_Frame;
|
||||
struct Vk_Frame {
|
||||
VkCommandPool pool;
|
||||
VkCommandBuffer cmd;
|
||||
|
||||
VkSemaphore acquire, complete;
|
||||
VkFence fence;
|
||||
|
||||
U32 next_scratch;
|
||||
Vk_CommandBuffer scratch[VK_NUM_SCRATCH];
|
||||
|
||||
U32 image; // swapchain image index
|
||||
};
|
||||
|
||||
typedef struct Vk_Image Vk_Image;
|
||||
struct Vk_Image {
|
||||
VkDeviceMemory memory;
|
||||
@@ -60,14 +40,65 @@ struct Vk_Image {
|
||||
|
||||
typedef struct Vk_Buffer Vk_Buffer;
|
||||
struct Vk_Buffer {
|
||||
VkBuffer handle;
|
||||
|
||||
VkDeviceMemory memory;
|
||||
VkDeviceSize size;
|
||||
|
||||
VkBuffer handle;
|
||||
VkBufferUsageFlags usage;
|
||||
|
||||
B32 host_visible;
|
||||
void *data; // if mapped host visible memory
|
||||
};
|
||||
|
||||
typedef struct Vk_Shader Vk_Shader;
|
||||
struct Vk_Shader {
|
||||
VkShaderModule handle;
|
||||
VkShaderStageFlags stage;
|
||||
};
|
||||
|
||||
typedef struct Vk_Pipeline Vk_Pipeline;
|
||||
struct Vk_Pipeline {
|
||||
VkPipeline handle;
|
||||
|
||||
struct {
|
||||
VkPipelineLayout pipeline;
|
||||
VkDescriptorSetLayout set;
|
||||
} layout;
|
||||
|
||||
struct {
|
||||
VkFormat items[8];
|
||||
U32 count;
|
||||
} targets;
|
||||
|
||||
struct {
|
||||
Vk_Shader items[8];
|
||||
U32 count;
|
||||
} shaders;
|
||||
};
|
||||
|
||||
typedef struct Vk_CommandBuffer Vk_CommandBuffer;
|
||||
struct Vk_CommandBuffer {
|
||||
VkCommandBuffer handle;
|
||||
VkFence fence;
|
||||
};
|
||||
|
||||
typedef struct Vk_Frame Vk_Frame;
|
||||
struct Vk_Frame {
|
||||
VkCommandPool pool;
|
||||
VkCommandBuffer cmd;
|
||||
|
||||
VkDescriptorPool descriptors;
|
||||
|
||||
VkSemaphore acquire, complete;
|
||||
VkFence fence;
|
||||
|
||||
U32 next_scratch;
|
||||
Vk_CommandBuffer scratch[VK_NUM_SCRATCH];
|
||||
|
||||
U32 image; // swapchain image index
|
||||
};
|
||||
|
||||
typedef struct Vk_Context Vk_Context;
|
||||
struct Vk_Context {
|
||||
void *lib;
|
||||
@@ -110,6 +141,8 @@ struct Vk_Context {
|
||||
U32 width;
|
||||
U32 height;
|
||||
} swapchain;
|
||||
|
||||
VkSampler sampler;
|
||||
};
|
||||
|
||||
extern Vk_Context vk;
|
||||
@@ -122,6 +155,7 @@ function void Vk_FrameEnd();
|
||||
function Vk_CommandBuffer *Vk_CommandBufferPush();
|
||||
function void Vk_CommandBufferSubmit(Vk_CommandBuffer *cmds, B32 wait);
|
||||
|
||||
function Vk_Buffer Vk_BufferCreate(U64 size, B32 host_visible);
|
||||
function void Vk_BufferCreate(Vk_Buffer *buffer);
|
||||
function void Vk_ImageCreate(Vk_Image *image);
|
||||
|
||||
#endif // LD_VULKAN_CORE_H_
|
||||
|
||||
@@ -48,6 +48,20 @@
|
||||
VK_FUNC(GetImageMemoryRequirements);
|
||||
VK_FUNC(BindImageMemory);
|
||||
VK_FUNC(MapMemory);
|
||||
VK_FUNC(CreateGraphicsPipelines);
|
||||
VK_FUNC(CreateShaderModule);
|
||||
VK_FUNC(CreateDescriptorSetLayout);
|
||||
VK_FUNC(CreatePipelineLayout);
|
||||
VK_FUNC(CmdBindPipeline);
|
||||
VK_FUNC(CreateDescriptorPool);
|
||||
VK_FUNC(ResetDescriptorPool);
|
||||
VK_FUNC(AllocateDescriptorSets);
|
||||
VK_FUNC(CmdBindDescriptorSets);
|
||||
VK_FUNC(UpdateDescriptorSets);
|
||||
VK_FUNC(CreateSampler);
|
||||
VK_FUNC(CmdDraw);
|
||||
VK_FUNC(CmdSetViewport);
|
||||
VK_FUNC(CmdSetScissor);
|
||||
|
||||
VK_FUNC(CmdCopyBufferToImage);
|
||||
VK_FUNC(CmdPipelineBarrier2);
|
||||
|
||||
12
code/vulkan/shaders/basic.frag
Normal file
12
code/vulkan/shaders/basic.frag
Normal file
@@ -0,0 +1,12 @@
|
||||
#version 460 core
|
||||
|
||||
layout(location = 0) in vec2 frag_uv;
|
||||
layout(location = 1) in vec4 frag_c;
|
||||
|
||||
layout(location = 0) out vec4 framebuffer;
|
||||
|
||||
layout(binding = 1) uniform sampler2D u_image;
|
||||
|
||||
void main() {
|
||||
framebuffer = frag_c * texture(u_image, frag_uv);
|
||||
}
|
||||
28
code/vulkan/shaders/basic.vert
Normal file
28
code/vulkan/shaders/basic.vert
Normal file
@@ -0,0 +1,28 @@
|
||||
#version 460 core
|
||||
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
struct Vertex {
|
||||
vec4 p;
|
||||
vec2 uv;
|
||||
uint c;
|
||||
uint pad;
|
||||
};
|
||||
|
||||
layout(binding = 0, scalar)
|
||||
readonly buffer Vertices {
|
||||
Vertex vtx[];
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 frag_uv;
|
||||
layout(location = 1) out vec4 frag_c;
|
||||
|
||||
void main() {
|
||||
Vertex v = vtx[gl_VertexIndex];
|
||||
|
||||
gl_Position = v.p;
|
||||
|
||||
frag_uv = v.uv;
|
||||
frag_c = vec4((v.c >> 24) & 0xFF, (v.c >> 16) & 0xFF, (v.c >> 8) & 0xFF, (v.c >> 0) & 0xFF) / 255.0f;
|
||||
frag_c = frag_c.abgr;
|
||||
}
|
||||
Reference in New Issue
Block a user