580 lines
23 KiB
C
580 lines
23 KiB
C
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <vulkan/vulkan.h>
|
||
|
#include <vulkan/vulkan_core.h>
|
||
|
|
||
|
#include "dynarray.h"
|
||
|
#include "image.h"
|
||
|
#include "io.h"
|
||
|
#include "vulkan.h"
|
||
|
#include "vulkan_helpers.c"
|
||
|
|
||
|
enum AttatchType {
|
||
|
CAT_ATTATCH_IMAGE,
|
||
|
CAT_ATTATCH_UBO,
|
||
|
};
|
||
|
|
||
|
struct Attatchment {
|
||
|
enum AttatchType type;
|
||
|
union {
|
||
|
struct {
|
||
|
const char *path;
|
||
|
uchar *pixels;
|
||
|
struct IVec2 dims;
|
||
|
VkDeviceSize size;
|
||
|
VkImage image;
|
||
|
VkImageView view;
|
||
|
VkSampler sampler;
|
||
|
VkDeviceMemory memory;
|
||
|
} image;
|
||
|
struct {
|
||
|
uint32_t size;
|
||
|
void *mapped[MAX_FRAMES_IN_FLIGHT];
|
||
|
VkBuffer buffer[MAX_FRAMES_IN_FLIGHT];
|
||
|
VkDeviceMemory memory[MAX_FRAMES_IN_FLIGHT];
|
||
|
} ubo;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
dyn_array_define(da_Attatchment, struct Attatchment);
|
||
|
|
||
|
struct Kitty {
|
||
|
VkPipeline pipeline;
|
||
|
VkPipelineLayout pipeline_layout;
|
||
|
|
||
|
const char *vertex_path;
|
||
|
const char *fragment_path;
|
||
|
|
||
|
struct VertexBuffer vertex_buffer;
|
||
|
struct da_Attatchment attatchments;
|
||
|
|
||
|
uint32_t push_constant_size;
|
||
|
void *next_push_constant;
|
||
|
|
||
|
VkDescriptorPool descriptor_pool;
|
||
|
VkDescriptorSetLayout descriptor_set_layout;
|
||
|
VkDescriptorSet descriptor_sets[MAX_FRAMES_IN_FLIGHT];
|
||
|
};
|
||
|
|
||
|
struct Kitty *kitty_make() {
|
||
|
struct Kitty *thingy = malloc(sizeof(struct Kitty));
|
||
|
memset(thingy, 0, sizeof(struct Kitty));
|
||
|
dyn_array_create_inplace(&thingy->attatchments);
|
||
|
dyn_array_create_inplace(&thingy->vertex_buffer.format);
|
||
|
meow("alloced a thingy at %p", thingy);
|
||
|
return thingy;
|
||
|
}
|
||
|
|
||
|
void kitty_set_push_constant_size(struct Kitty *thingy, uint32_t size) {
|
||
|
thingy->push_constant_size = size;
|
||
|
}
|
||
|
void kitty_set_vertex_shader(struct Kitty *thingy, const char *path) {
|
||
|
thingy->vertex_path = path;
|
||
|
meow("vertex path is %s", path);
|
||
|
}
|
||
|
void kitty_set_fragment_shader(struct Kitty *thingy, const char *path) {
|
||
|
thingy->fragment_path = path;
|
||
|
meow("fragment path is %s", path);
|
||
|
}
|
||
|
void kitty_set_vertex_buffer(struct Kitty *thingy, void *data, uint32_t count,
|
||
|
int vertex_size) {
|
||
|
thingy->vertex_buffer.data = data;
|
||
|
thingy->vertex_buffer.count = count;
|
||
|
thingy->vertex_buffer.vertex_size = vertex_size;
|
||
|
}
|
||
|
void kitty_add_vertex_buffer_format(struct Kitty *thingy,
|
||
|
enum VkFormat format) {
|
||
|
meow("attatched %d to the buffer", format);
|
||
|
dyn_array_append(&thingy->vertex_buffer.format, format);
|
||
|
}
|
||
|
void kitty_attatch_image(struct Kitty *thingy, const char *path) {
|
||
|
struct Attatchment attatchment = {0};
|
||
|
attatchment.type = CAT_ATTATCH_IMAGE;
|
||
|
attatchment.image.path = path;
|
||
|
dyn_array_append(&thingy->attatchments, attatchment);
|
||
|
meow("image was attatched");
|
||
|
}
|
||
|
int kitty_attatch_ubo(struct Kitty *thingy, uint32_t size) {
|
||
|
struct Attatchment attatchment = {0};
|
||
|
attatchment.type = CAT_ATTATCH_UBO;
|
||
|
attatchment.ubo.size = size;
|
||
|
dyn_array_append(&thingy->attatchments, attatchment);
|
||
|
meow("ubo of size %d was attatched", size);
|
||
|
return thingy->attatchments.count - 1;
|
||
|
}
|
||
|
|
||
|
void kitty_finalise(struct Vk *state, struct Kitty *kitty) {
|
||
|
meow("this thingy has %d ubos", kitty->attatchments.count);
|
||
|
|
||
|
if (kitty->vertex_path == NULL) {
|
||
|
meow("a kitty has no vertex shader :c");
|
||
|
return;
|
||
|
}
|
||
|
if (kitty->fragment_path == NULL) {
|
||
|
meow("a kitty has no fragment shader :c");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
VkDescriptorSetLayoutBinding
|
||
|
descriptor_set_layout_binding[kitty->attatchments.count];
|
||
|
memset(descriptor_set_layout_binding, 0,
|
||
|
sizeof(VkDescriptorSetLayoutBinding) * kitty->attatchments.count);
|
||
|
for (int index = 0; index < kitty->attatchments.count; index++) {
|
||
|
if (kitty->attatchments.items[index].type == CAT_ATTATCH_UBO) {
|
||
|
descriptor_set_layout_binding[index].binding = index;
|
||
|
descriptor_set_layout_binding[index].descriptorType =
|
||
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||
|
descriptor_set_layout_binding[index].descriptorCount = 1;
|
||
|
descriptor_set_layout_binding[index].stageFlags = VK_SHADER_STAGE_ALL;
|
||
|
descriptor_set_layout_binding[index].pImmutableSamplers = NULL;
|
||
|
} else {
|
||
|
descriptor_set_layout_binding[index].binding = index;
|
||
|
descriptor_set_layout_binding[index].descriptorType =
|
||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||
|
descriptor_set_layout_binding[index].descriptorCount = 1;
|
||
|
descriptor_set_layout_binding[index].stageFlags = VK_SHADER_STAGE_ALL;
|
||
|
descriptor_set_layout_binding[index].pImmutableSamplers = NULL;
|
||
|
}
|
||
|
}
|
||
|
VkDescriptorSetLayoutCreateInfo layout_info = {0};
|
||
|
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||
|
layout_info.bindingCount = kitty->attatchments.count;
|
||
|
layout_info.pBindings = descriptor_set_layout_binding;
|
||
|
CHECK_VK_RESULT(vkCreateDescriptorSetLayout(state->device, &layout_info, NULL,
|
||
|
&kitty->descriptor_set_layout));
|
||
|
|
||
|
int vert_size, frag_size;
|
||
|
uint32_t *vert_shader =
|
||
|
read_binary_file((char *)kitty->vertex_path, &vert_size);
|
||
|
uint32_t *frag_shader =
|
||
|
read_binary_file((char *)kitty->fragment_path, &frag_size);
|
||
|
|
||
|
VkShaderModule vert_module =
|
||
|
create_shader_module(state, vert_shader, vert_size);
|
||
|
VkShaderModule frag_module =
|
||
|
create_shader_module(state, frag_shader, frag_size);
|
||
|
|
||
|
VkPipelineShaderStageCreateInfo vert_stage_info = {0};
|
||
|
vert_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||
|
vert_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||
|
vert_stage_info.module = vert_module;
|
||
|
vert_stage_info.pName = "main";
|
||
|
|
||
|
VkPipelineShaderStageCreateInfo frag_stage_info = {0};
|
||
|
frag_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||
|
frag_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||
|
frag_stage_info.module = frag_module;
|
||
|
frag_stage_info.pName = "main";
|
||
|
|
||
|
VkPipelineShaderStageCreateInfo shader_stage_info[] = {vert_stage_info,
|
||
|
frag_stage_info};
|
||
|
VkVertexInputBindingDescription vertex_binding_description = {0};
|
||
|
vertex_binding_description.binding = 0;
|
||
|
vertex_binding_description.stride = kitty->vertex_buffer.vertex_size;
|
||
|
vertex_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||
|
|
||
|
VkVertexInputAttributeDescription *vertex_attribute_descriptions =
|
||
|
alloca(sizeof(VkVertexInputAttributeDescription) *
|
||
|
kitty->vertex_buffer.format.count);
|
||
|
int offset = 0;
|
||
|
for (int i = 0; i < kitty->vertex_buffer.format.count; i++) {
|
||
|
vertex_attribute_descriptions[i].binding = 0;
|
||
|
vertex_attribute_descriptions[i].location = i;
|
||
|
vertex_attribute_descriptions[i].format =
|
||
|
kitty->vertex_buffer.format.items[i];
|
||
|
vertex_attribute_descriptions[i].offset = offset;
|
||
|
offset += get_size_of_format(kitty->vertex_buffer.format.items[i]);
|
||
|
}
|
||
|
|
||
|
VkPipelineVertexInputStateCreateInfo vertex_input_info = {0};
|
||
|
vertex_input_info.sType =
|
||
|
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||
|
vertex_input_info.vertexBindingDescriptionCount = 1;
|
||
|
vertex_input_info.pVertexBindingDescriptions = &vertex_binding_description;
|
||
|
vertex_input_info.vertexAttributeDescriptionCount =
|
||
|
kitty->vertex_buffer.format.count;
|
||
|
vertex_input_info.pVertexAttributeDescriptions =
|
||
|
vertex_attribute_descriptions;
|
||
|
|
||
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {0};
|
||
|
input_assembly_info.sType =
|
||
|
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||
|
input_assembly_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||
|
input_assembly_info.primitiveRestartEnable = VK_FALSE;
|
||
|
|
||
|
VkPipelineViewportStateCreateInfo viewport_state_info = {0};
|
||
|
viewport_state_info.sType =
|
||
|
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||
|
viewport_state_info.viewportCount = 1;
|
||
|
viewport_state_info.scissorCount = 1;
|
||
|
|
||
|
VkPipelineRasterizationStateCreateInfo rasterizer_info = {0};
|
||
|
rasterizer_info.sType =
|
||
|
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||
|
rasterizer_info.depthClampEnable = VK_FALSE;
|
||
|
rasterizer_info.rasterizerDiscardEnable = VK_FALSE;
|
||
|
rasterizer_info.polygonMode = VK_POLYGON_MODE_FILL;
|
||
|
rasterizer_info.lineWidth = 1.0f;
|
||
|
rasterizer_info.cullMode = VK_CULL_MODE_BACK_BIT;
|
||
|
rasterizer_info.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||
|
rasterizer_info.depthBiasEnable = VK_FALSE;
|
||
|
|
||
|
VkPipelineMultisampleStateCreateInfo multisampling_info = {0};
|
||
|
multisampling_info.sType =
|
||
|
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||
|
multisampling_info.sampleShadingEnable = VK_FALSE;
|
||
|
multisampling_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||
|
|
||
|
VkPipelineColorBlendAttachmentState color_blend_attachment = {0};
|
||
|
color_blend_attachment.colorWriteMask =
|
||
|
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||
|
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||
|
color_blend_attachment.blendEnable = VK_FALSE;
|
||
|
|
||
|
VkPipelineColorBlendStateCreateInfo color_blend_info = {0};
|
||
|
color_blend_info.sType =
|
||
|
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||
|
color_blend_info.logicOpEnable = VK_FALSE;
|
||
|
color_blend_info.logicOp = VK_LOGIC_OP_COPY;
|
||
|
color_blend_info.attachmentCount = 1;
|
||
|
color_blend_info.pAttachments = &color_blend_attachment;
|
||
|
|
||
|
/* VkPushConstantRange push_constant_range = {0}; */
|
||
|
/* push_constant_range.offset = 0; */
|
||
|
/* push_constant_range.size = thingy->push_constant_size; */
|
||
|
/* push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; */
|
||
|
|
||
|
VkPipelineLayoutCreateInfo pipeline_layout_info = {0};
|
||
|
pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||
|
pipeline_layout_info.setLayoutCount = 1;
|
||
|
pipeline_layout_info.pSetLayouts = &kitty->descriptor_set_layout;
|
||
|
pipeline_layout_info.pushConstantRangeCount = 0; // TODO
|
||
|
pipeline_layout_info.pPushConstantRanges = NULL;
|
||
|
CHECK_VK_RESULT(vkCreatePipelineLayout(state->device, &pipeline_layout_info,
|
||
|
NULL, &kitty->pipeline_layout));
|
||
|
|
||
|
VkDynamicState dynamic_states[] = {VK_DYNAMIC_STATE_VIEWPORT,
|
||
|
VK_DYNAMIC_STATE_SCISSOR};
|
||
|
|
||
|
VkPipelineDynamicStateCreateInfo dynamic_state_info = {0};
|
||
|
dynamic_state_info.sType =
|
||
|
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||
|
dynamic_state_info.pDynamicStates = dynamic_states;
|
||
|
dynamic_state_info.dynamicStateCount =
|
||
|
sizeof(dynamic_states) / sizeof(dynamic_states[0]);
|
||
|
|
||
|
VkGraphicsPipelineCreateInfo pipeline_info = {0};
|
||
|
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||
|
pipeline_info.stageCount = 2;
|
||
|
pipeline_info.pStages = shader_stage_info;
|
||
|
pipeline_info.pVertexInputState = &vertex_input_info;
|
||
|
pipeline_info.pInputAssemblyState = &input_assembly_info;
|
||
|
pipeline_info.pViewportState = &viewport_state_info;
|
||
|
pipeline_info.pRasterizationState = &rasterizer_info;
|
||
|
pipeline_info.pMultisampleState = &multisampling_info;
|
||
|
pipeline_info.pDepthStencilState = NULL;
|
||
|
pipeline_info.pColorBlendState = &color_blend_info;
|
||
|
pipeline_info.pDynamicState = &dynamic_state_info;
|
||
|
pipeline_info.layout = kitty->pipeline_layout;
|
||
|
pipeline_info.renderPass = state->render_pass;
|
||
|
pipeline_info.subpass = 0;
|
||
|
pipeline_info.basePipelineHandle = NULL;
|
||
|
pipeline_info.basePipelineIndex = -1;
|
||
|
|
||
|
CHECK_VK_RESULT(vkCreateGraphicsPipelines(
|
||
|
state->device, NULL, 1, &pipeline_info, NULL, &kitty->pipeline));
|
||
|
|
||
|
int ubo_count = 0;
|
||
|
int image_count = 0;
|
||
|
for (int i = 0; i < kitty->attatchments.count; i++) {
|
||
|
switch (kitty->attatchments.items[i].type) {
|
||
|
case CAT_ATTATCH_UBO:
|
||
|
ubo_count++;
|
||
|
break;
|
||
|
case CAT_ATTATCH_IMAGE:
|
||
|
image_count++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VkDescriptorPoolSize pool_sizes[2] = {0};
|
||
|
pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||
|
pool_sizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT;
|
||
|
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||
|
pool_sizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT;
|
||
|
|
||
|
VkDescriptorPoolCreateInfo pool_info = {0};
|
||
|
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||
|
pool_info.poolSizeCount = 2;
|
||
|
pool_info.pPoolSizes = pool_sizes;
|
||
|
pool_info.maxSets = 10;
|
||
|
|
||
|
CHECK_VK_RESULT(vkCreateDescriptorPool(state->device, &pool_info, NULL,
|
||
|
&kitty->descriptor_pool));
|
||
|
|
||
|
for (int index = 0; index < kitty->attatchments.count; index++) {
|
||
|
if (kitty->attatchments.items[index].type != CAT_ATTATCH_IMAGE) {
|
||
|
continue;
|
||
|
}
|
||
|
struct Attatchment *atch = &kitty->attatchments.items[index];
|
||
|
atch->image.pixels = load_image(atch->image.path, &atch->image.dims);
|
||
|
atch->image.size = atch->image.dims.x * atch->image.dims.y * 4;
|
||
|
|
||
|
VkBuffer staging_buffer;
|
||
|
VkDeviceMemory staging_buffer_memory;
|
||
|
create_buffer(state, atch->image.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||
|
&staging_buffer, &staging_buffer_memory);
|
||
|
|
||
|
void *data;
|
||
|
vkMapMemory(state->device, staging_buffer_memory, 0, atch->image.size, 0,
|
||
|
&data);
|
||
|
memcpy(data, atch->image.pixels, atch->image.size);
|
||
|
vkUnmapMemory(state->device, staging_buffer_memory);
|
||
|
|
||
|
create_image(state, atch->image.dims, VK_FORMAT_R8G8B8A8_SRGB,
|
||
|
VK_IMAGE_TILING_OPTIMAL,
|
||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &atch->image.image,
|
||
|
&atch->image.memory);
|
||
|
|
||
|
transition_image_layout(state, atch->image.image, VK_FORMAT_R8G8B8A8_SRGB,
|
||
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||
|
copy_buffer_to_image(state, staging_buffer, atch->image.image,
|
||
|
atch->image.dims);
|
||
|
transition_image_layout(state, atch->image.image, VK_FORMAT_R8G8B8A8_SRGB,
|
||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||
|
|
||
|
vkDestroyBuffer(state->device, staging_buffer, NULL);
|
||
|
vkFreeMemory(state->device, staging_buffer_memory, NULL);
|
||
|
|
||
|
VkImageViewCreateInfo view_info = {0};
|
||
|
view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||
|
view_info.image = atch->image.image;
|
||
|
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||
|
view_info.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||
|
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||
|
view_info.subresourceRange.baseMipLevel = 0;
|
||
|
view_info.subresourceRange.levelCount = 1;
|
||
|
view_info.subresourceRange.baseArrayLayer = 0;
|
||
|
view_info.subresourceRange.layerCount = 1;
|
||
|
CHECK_VK_RESULT(
|
||
|
vkCreateImageView(state->device, &view_info, NULL, &atch->image.view));
|
||
|
|
||
|
VkSamplerCreateInfo sampler_info = {0};
|
||
|
sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||
|
sampler_info.magFilter = VK_FILTER_NEAREST;
|
||
|
sampler_info.minFilter = VK_FILTER_NEAREST;
|
||
|
sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||
|
sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||
|
sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||
|
sampler_info.anisotropyEnable = VK_FALSE;
|
||
|
sampler_info.maxAnisotropy = 1.0f;
|
||
|
sampler_info.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
|
||
|
sampler_info.unnormalizedCoordinates = VK_FALSE;
|
||
|
sampler_info.compareEnable = VK_FALSE;
|
||
|
sampler_info.compareOp = VK_COMPARE_OP_ALWAYS;
|
||
|
sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||
|
sampler_info.mipLodBias = 0.0f;
|
||
|
sampler_info.minLod = 0.0;
|
||
|
sampler_info.maxLod = 0.0;
|
||
|
CHECK_VK_RESULT(vkCreateSampler(state->device, &sampler_info, NULL,
|
||
|
&atch->image.sampler));
|
||
|
}
|
||
|
|
||
|
for (int index = 0; index < kitty->attatchments.count; index++) {
|
||
|
if (kitty->attatchments.items[index].type != CAT_ATTATCH_UBO) {
|
||
|
continue;
|
||
|
}
|
||
|
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||
|
create_buffer(state, kitty->attatchments.items[index].ubo.size,
|
||
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||
|
&kitty->attatchments.items[index].ubo.buffer[i],
|
||
|
&kitty->attatchments.items[index].ubo.memory[i]);
|
||
|
|
||
|
void *pointer_to_mapped;
|
||
|
vkMapMemory(state->device, kitty->attatchments.items[index].ubo.memory[i],
|
||
|
0, kitty->attatchments.items[index].ubo.size, 0,
|
||
|
&pointer_to_mapped);
|
||
|
kitty->attatchments.items[index].ubo.mapped[i] = pointer_to_mapped;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VkDescriptorSetLayout set_layouts[MAX_FRAMES_IN_FLIGHT];
|
||
|
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||
|
set_layouts[i] = kitty->descriptor_set_layout;
|
||
|
}
|
||
|
|
||
|
VkDescriptorSetAllocateInfo alloc_info = {0};
|
||
|
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||
|
alloc_info.descriptorPool = kitty->descriptor_pool;
|
||
|
alloc_info.descriptorSetCount = MAX_FRAMES_IN_FLIGHT;
|
||
|
meow("allocing %d desc sets", MAX_FRAMES_IN_FLIGHT);
|
||
|
alloc_info.pSetLayouts = set_layouts;
|
||
|
CHECK_VK_RESULT(vkAllocateDescriptorSets(state->device, &alloc_info,
|
||
|
kitty->descriptor_sets));
|
||
|
|
||
|
for (int index = 0; index < kitty->attatchments.count; index++) {
|
||
|
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||
|
switch (kitty->attatchments.items[index].type) {
|
||
|
case CAT_ATTATCH_UBO:;
|
||
|
VkDescriptorBufferInfo buffer_info = {0};
|
||
|
buffer_info.buffer = kitty->attatchments.items[index].ubo.buffer[i];
|
||
|
buffer_info.offset = 0;
|
||
|
buffer_info.range = kitty->attatchments.items[index].ubo.size;
|
||
|
|
||
|
VkWriteDescriptorSet write_buffer = {0};
|
||
|
write_buffer.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||
|
write_buffer.dstSet = kitty->descriptor_sets[i];
|
||
|
write_buffer.dstBinding = index;
|
||
|
write_buffer.dstArrayElement = 0;
|
||
|
write_buffer.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||
|
write_buffer.descriptorCount = 1;
|
||
|
write_buffer.pBufferInfo = &buffer_info;
|
||
|
vkUpdateDescriptorSets(state->device, 1, &write_buffer, 0, NULL);
|
||
|
break;
|
||
|
case CAT_ATTATCH_IMAGE:;
|
||
|
VkDescriptorImageInfo image_info = {0};
|
||
|
image_info.imageLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
|
||
|
image_info.imageView = kitty->attatchments.items[index].image.view;
|
||
|
image_info.sampler = kitty->attatchments.items[index].image.sampler;
|
||
|
|
||
|
VkWriteDescriptorSet write_image = {0};
|
||
|
write_image.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||
|
write_image.dstSet = kitty->descriptor_sets[i];
|
||
|
write_image.dstBinding = index;
|
||
|
write_image.dstArrayElement = 0;
|
||
|
write_image.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||
|
write_image.descriptorCount = 1;
|
||
|
write_image.pImageInfo = &image_info;
|
||
|
vkUpdateDescriptorSets(state->device, 1, &write_image, 0, NULL);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VkDeviceSize size =
|
||
|
kitty->vertex_buffer.count * kitty->vertex_buffer.vertex_size;
|
||
|
VkBuffer staging_buffer;
|
||
|
VkDeviceMemory staging_buffer_memory;
|
||
|
|
||
|
create_buffer(state, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||
|
&staging_buffer, &staging_buffer_memory);
|
||
|
|
||
|
void *data;
|
||
|
vkMapMemory(state->device, staging_buffer_memory, 0, size, 0, &data);
|
||
|
memcpy(data, kitty->vertex_buffer.data, size);
|
||
|
vkUnmapMemory(state->device, staging_buffer_memory);
|
||
|
|
||
|
create_buffer(state, size,
|
||
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||
|
&kitty->vertex_buffer.buffer, &kitty->vertex_buffer.memory);
|
||
|
|
||
|
copy_buffer(state, staging_buffer, kitty->vertex_buffer.buffer, size);
|
||
|
|
||
|
vkDestroyBuffer(state->device, staging_buffer, NULL);
|
||
|
vkFreeMemory(state->device, staging_buffer_memory, NULL);
|
||
|
|
||
|
vkDestroyShaderModule(state->device, vert_module, NULL);
|
||
|
vkDestroyShaderModule(state->device, frag_module, NULL);
|
||
|
|
||
|
free(vert_shader);
|
||
|
free(frag_shader);
|
||
|
|
||
|
dyn_array_append(&state->kitties, kitty);
|
||
|
meow("appended a kitty, len is now %d", state->kitties.count);
|
||
|
}
|
||
|
|
||
|
void free_kitty(struct Vk *state, struct Kitty *kitty) {
|
||
|
vkDeviceWaitIdle(state->device);
|
||
|
vkDestroyBuffer(state->device, kitty->vertex_buffer.buffer, NULL);
|
||
|
vkFreeMemory(state->device, kitty->vertex_buffer.memory, NULL);
|
||
|
vkDestroyDescriptorPool(state->device, kitty->descriptor_pool, NULL);
|
||
|
vkDestroyDescriptorSetLayout(state->device, kitty->descriptor_set_layout,
|
||
|
NULL);
|
||
|
vkDestroyPipelineLayout(state->device, kitty->pipeline_layout, NULL);
|
||
|
vkDestroyPipeline(state->device, kitty->pipeline, NULL);
|
||
|
for (int i = 0; i < kitty->attatchments.count; i++) {
|
||
|
switch (kitty->attatchments.items[i].type) {
|
||
|
case CAT_ATTATCH_UBO:
|
||
|
for (int j = 0; j < MAX_FRAMES_IN_FLIGHT; j++) {
|
||
|
vkDestroyBuffer(state->device,
|
||
|
kitty->attatchments.items[i].ubo.buffer[j], NULL);
|
||
|
vkFreeMemory(state->device, kitty->attatchments.items[i].ubo.memory[j],
|
||
|
NULL);
|
||
|
}
|
||
|
break;
|
||
|
case CAT_ATTATCH_IMAGE:
|
||
|
vkDestroyImage(state->device, kitty->attatchments.items[i].image.image,
|
||
|
NULL);
|
||
|
vkFreeMemory(state->device, kitty->attatchments.items[i].image.memory,
|
||
|
NULL);
|
||
|
vkDestroyImageView(state->device, kitty->attatchments.items[i].image.view,
|
||
|
NULL);
|
||
|
vkDestroySampler(state->device,
|
||
|
kitty->attatchments.items[i].image.sampler, NULL);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dyn_array_destroy(&kitty->vertex_buffer.format);
|
||
|
dyn_array_destroy(&kitty->attatchments);
|
||
|
|
||
|
memset(kitty, 0, sizeof(struct Kitty));
|
||
|
free(kitty);
|
||
|
}
|
||
|
|
||
|
void kitty_set_next_push_constant(struct Kitty *thingy, void *data) {
|
||
|
thingy->next_push_constant = data;
|
||
|
}
|
||
|
|
||
|
void kitty_set_next_ubo(struct Vk *state, struct Kitty *thingy, int index,
|
||
|
void *data) {
|
||
|
void *dst =
|
||
|
thingy->attatchments.items[index].ubo.mapped[state->current_frame];
|
||
|
void *src = data;
|
||
|
int size = thingy->attatchments.items[index].ubo.size;
|
||
|
/* meow("index %d, number %f", index, *(float *)data); */
|
||
|
memcpy(dst, src, size);
|
||
|
}
|
||
|
|
||
|
void kitty_draw(struct Vk *state, uint32_t image_index, struct Kitty *thingy) {
|
||
|
struct InFlightObjects flight = state->flights[state->current_frame];
|
||
|
vkCmdBindPipeline(flight.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||
|
thingy->pipeline);
|
||
|
|
||
|
VkViewport viewport = {0};
|
||
|
viewport.x = 0.0f;
|
||
|
viewport.y = 0.0f;
|
||
|
viewport.width = state->width;
|
||
|
viewport.height = state->heigh;
|
||
|
viewport.minDepth = 0.0f;
|
||
|
viewport.maxDepth = 1.0f;
|
||
|
vkCmdSetViewport(flight.command_buffer, 0, 1, &viewport);
|
||
|
|
||
|
VkRect2D scissor = {0};
|
||
|
scissor.offset = (VkOffset2D){0, 0};
|
||
|
scissor.extent = (VkExtent2D){state->width, state->heigh};
|
||
|
vkCmdSetScissor(flight.command_buffer, 0, 1, &scissor);
|
||
|
|
||
|
VkBuffer vertex_buffer[] = {thingy->vertex_buffer.buffer};
|
||
|
VkDeviceSize offsets[] = {0};
|
||
|
vkCmdBindVertexBuffers(flight.command_buffer, 0, 1, vertex_buffer, offsets);
|
||
|
|
||
|
vkCmdBindDescriptorSets(
|
||
|
flight.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||
|
thingy->pipeline_layout, 0, 1,
|
||
|
&thingy->descriptor_sets[state->current_frame], 0, NULL);
|
||
|
|
||
|
vkCmdDraw(flight.command_buffer, thingy->vertex_buffer.count, 1, 0, 0);
|
||
|
}
|