Add instanced rendering :3
This commit is contained in:
parent
988e00fd2e
commit
95d90bfbd9
4 changed files with 157 additions and 32 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
layout(location = 0) in vec2 inPosition;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
layout(location = 2) in mat3 offset;
|
||||
|
||||
layout(set = 0, binding = 0) uniform UBO {
|
||||
mat3 model;
|
||||
|
@ -13,7 +14,7 @@ layout(location = 0) out vec3 fragColor;
|
|||
layout(location = 1) out vec2 fragUV;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(ubo.proj * ubo.view * ubo.model * vec3(inPosition, 1.0), 1.0);
|
||||
gl_Position = vec4(ubo.proj * ubo.view * offset * ubo.model * vec3(inPosition, 1.0), 1.0);
|
||||
fragColor = inColor;
|
||||
fragUV = inPosition;
|
||||
}
|
||||
|
|
167
kitty.c
167
kitty.c
|
@ -13,6 +13,7 @@ struct Kitty *kitty_make() {
|
|||
memset(kitty, 0, sizeof(struct Kitty));
|
||||
dyn_array_create_inplace(&kitty->attatchments);
|
||||
dyn_array_create_inplace(&kitty->vertex_buffer.format);
|
||||
dyn_array_create_inplace(&kitty->instance_buffer.format);
|
||||
meow("alloced a kitty at %p", kitty);
|
||||
return kitty;
|
||||
}
|
||||
|
@ -40,8 +41,18 @@ void kitty_add_index_buffer(struct Kitty *kitty, void *data, uint32_t count) {
|
|||
kitty->index_buffer.count = count;
|
||||
}
|
||||
|
||||
void kitty_add_instance_buffer(struct Kitty *kitty, void *data, uint32_t count,
|
||||
int element_size) {
|
||||
kitty->instance_buffer.data = data;
|
||||
kitty->instance_buffer.count = count;
|
||||
kitty->instance_buffer.element_size = element_size;
|
||||
}
|
||||
void kitty_add_instance_buffer_format(struct Kitty *kitty,
|
||||
enum VkFormat format) {
|
||||
dyn_array_append(&kitty->instance_buffer.format, format);
|
||||
}
|
||||
|
||||
void kitty_add_vertex_buffer_format(struct Kitty *kitty, enum VkFormat format) {
|
||||
meow("attatched %d to the buffer", format);
|
||||
dyn_array_append(&kitty->vertex_buffer.format, format);
|
||||
}
|
||||
void kitty_attatch_image(struct Kitty *kitty, const char *path) {
|
||||
|
@ -68,6 +79,9 @@ void kitty_finalise(struct Vk *state, struct Kitty *kitty) {
|
|||
kitty_create_ubo_attatchments(kitty, state);
|
||||
kitty_create_descriptor_sets(kitty, state);
|
||||
kitty_create_vertex_buffer(kitty, state);
|
||||
if (kitty->instance_buffer.count != 0) {
|
||||
kitty_create_instance_buffer(kitty, state);
|
||||
}
|
||||
|
||||
dyn_array_append(&state->kitties, kitty);
|
||||
}
|
||||
|
@ -76,6 +90,10 @@ 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);
|
||||
if (kitty->instance_buffer.count != 0) {
|
||||
vkDestroyBuffer(state->device, kitty->instance_buffer.buffer, NULL);
|
||||
vkFreeMemory(state->device, kitty->instance_buffer.memory, NULL);
|
||||
}
|
||||
vkDestroyDescriptorPool(state->device, kitty->descriptor_pool, NULL);
|
||||
vkDestroyDescriptorSetLayout(state->device, kitty->descriptor_set_layout,
|
||||
NULL);
|
||||
|
@ -142,16 +160,26 @@ void kitty_draw(struct Vk *state, uint32_t image_index, struct Kitty *kitty) {
|
|||
scissor.extent = (VkExtent2D){state->width, state->heigh};
|
||||
vkCmdSetScissor(flight.command_buffer, 0, 1, &scissor);
|
||||
|
||||
VkBuffer vertex_buffer[] = {kitty->vertex_buffer.buffer};
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(flight.command_buffer, 0, 1, vertex_buffer, offsets);
|
||||
uint64_t offsets[1] = {0};
|
||||
vkCmdBindVertexBuffers(flight.command_buffer, 0, 1,
|
||||
&kitty->vertex_buffer.buffer, offsets);
|
||||
|
||||
if (kitty->instance_buffer.count != 0) {
|
||||
vkCmdBindVertexBuffers(flight.command_buffer, 1, 1,
|
||||
&kitty->instance_buffer.buffer, offsets);
|
||||
}
|
||||
|
||||
vkCmdBindDescriptorSets(
|
||||
flight.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
kitty->pipeline_layout, 0, 1,
|
||||
&kitty->descriptor_sets[state->current_frame], 0, NULL);
|
||||
|
||||
vkCmdDraw(flight.command_buffer, kitty->vertex_buffer.count, 1, 0, 0);
|
||||
if (kitty->instance_buffer.count == 0) {
|
||||
vkCmdDraw(flight.command_buffer, kitty->vertex_buffer.count, 1, 0, 0);
|
||||
} else {
|
||||
vkCmdDraw(flight.command_buffer, kitty->vertex_buffer.count,
|
||||
kitty->instance_buffer.count, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void kitty_create_layout_bindings(struct Kitty *kitty, struct Vk *state) {
|
||||
|
@ -210,33 +238,79 @@ void kitty_create_pipeline(struct Kitty *kitty, struct Vk *state) {
|
|||
|
||||
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;
|
||||
if (kitty->instance_buffer.count == 0) {
|
||||
meow("single instance kitty");
|
||||
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]);
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
meow("multi instance kitty");
|
||||
VkVertexInputBindingDescription binding_descriptions[2] = {0};
|
||||
binding_descriptions[0].binding = 0;
|
||||
binding_descriptions[0].stride = kitty->vertex_buffer.vertex_size;
|
||||
binding_descriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
binding_descriptions[1].binding = 1;
|
||||
binding_descriptions[1].stride = kitty->instance_buffer.element_size;
|
||||
binding_descriptions[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||
|
||||
VkVertexInputAttributeDescription *attribute_descriptions =
|
||||
alloca(sizeof(VkVertexInputAttributeDescription) *
|
||||
kitty->vertex_buffer.format.count +
|
||||
sizeof(VkVertexInputAttributeDescription) *
|
||||
kitty->instance_buffer.format.count);
|
||||
int offset = 0;
|
||||
for (int i = 0; i < kitty->vertex_buffer.format.count; i++) {
|
||||
attribute_descriptions[i].binding = 0;
|
||||
attribute_descriptions[i].location = i;
|
||||
attribute_descriptions[i].format = kitty->vertex_buffer.format.items[i];
|
||||
attribute_descriptions[i].offset = offset;
|
||||
offset += get_size_of_format(kitty->vertex_buffer.format.items[i]);
|
||||
}
|
||||
offset = 0;
|
||||
for (int i = 0; i < kitty->instance_buffer.format.count; i++) {
|
||||
attribute_descriptions[i + kitty->vertex_buffer.format.count].binding = 1;
|
||||
attribute_descriptions[i + kitty->vertex_buffer.format.count].location =
|
||||
i + kitty->vertex_buffer.format.count;
|
||||
attribute_descriptions[i + kitty->vertex_buffer.format.count].format =
|
||||
kitty->instance_buffer.format.items[i];
|
||||
attribute_descriptions[i + kitty->vertex_buffer.format.count].offset =
|
||||
offset;
|
||||
offset += get_size_of_format(kitty->instance_buffer.format.items[i]);
|
||||
}
|
||||
|
||||
vertex_input_info.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertex_input_info.vertexBindingDescriptionCount = 2;
|
||||
vertex_input_info.pVertexBindingDescriptions = binding_descriptions;
|
||||
vertex_input_info.vertexAttributeDescriptionCount =
|
||||
kitty->vertex_buffer.format.count + kitty->instance_buffer.format.count;
|
||||
vertex_input_info.pVertexAttributeDescriptions = attribute_descriptions;
|
||||
}
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {0};
|
||||
input_assembly_info.sType =
|
||||
|
@ -543,3 +617,36 @@ void kitty_create_vertex_buffer(struct Kitty *kitty, struct Vk *state) {
|
|||
vkFreeMemory(state->device, staging_buffer_memory, NULL);
|
||||
kitty->vertex_buffer.data = NULL;
|
||||
}
|
||||
|
||||
void kitty_create_instance_buffer(struct Kitty *kitty, struct Vk *state) {
|
||||
if (kitty->instance_buffer.count == 0) {
|
||||
crash("trying to create an instance buffer for a kitty that is not "
|
||||
"instanced :o");
|
||||
}
|
||||
VkDeviceSize size =
|
||||
kitty->instance_buffer.count * kitty->instance_buffer.element_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->instance_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->instance_buffer.buffer, &kitty->instance_buffer.memory);
|
||||
|
||||
copy_buffer(state, staging_buffer, kitty->instance_buffer.buffer, size);
|
||||
|
||||
vkDestroyBuffer(state->device, staging_buffer, NULL);
|
||||
vkFreeMemory(state->device, staging_buffer_memory, NULL);
|
||||
kitty->instance_buffer.data = NULL;
|
||||
}
|
||||
|
|
9
kitty.h
9
kitty.h
|
@ -42,6 +42,7 @@ struct Kitty {
|
|||
const char *fragment_path;
|
||||
|
||||
struct VertexBuffer vertex_buffer;
|
||||
struct InstanceBuffer instance_buffer;
|
||||
struct IndexBuffer index_buffer;
|
||||
|
||||
struct da_Attatchment attatchments;
|
||||
|
@ -68,6 +69,13 @@ void kitty_add_vertex_buffer_format(struct Kitty *thingy, enum VkFormat format);
|
|||
// transferred
|
||||
void kitty_add_index_buffer(struct Kitty *kitty, void *data, uint32_t count);
|
||||
|
||||
// 'data' can be freed after 'kitty_finalise' is called, ownership is not
|
||||
// transferred
|
||||
void kitty_add_instance_buffer(struct Kitty *kitty, void *data, uint32_t count,
|
||||
int element_size);
|
||||
void kitty_add_instance_buffer_format(struct Kitty *kitty,
|
||||
enum VkFormat format);
|
||||
|
||||
void kitty_set_push_constant_size(struct Kitty *thingy, uint32_t size);
|
||||
|
||||
// the returned number can be used in 'kitty_set_next_ubo' to update the content
|
||||
|
@ -92,5 +100,6 @@ void kitty_create_image_attatchments(struct Kitty *kitty, struct Vk *state);
|
|||
void kitty_create_ubo_attatchments(struct Kitty *kitty, struct Vk *state);
|
||||
void kitty_create_descriptor_sets(struct Kitty *kitty, struct Vk *state);
|
||||
void kitty_create_vertex_buffer(struct Kitty *kitty, struct Vk *state);
|
||||
void kitty_create_instance_buffer(struct Kitty *kitty, struct Vk *state);
|
||||
|
||||
#endif // INCLUDE_KITTY
|
||||
|
|
10
vulkan.h
10
vulkan.h
|
@ -28,7 +28,15 @@ struct VertexBuffer {
|
|||
VkDeviceMemory memory;
|
||||
uint32_t count;
|
||||
int vertex_size;
|
||||
int binding;
|
||||
struct da_VK_FORMAT format;
|
||||
};
|
||||
|
||||
struct InstanceBuffer {
|
||||
void *data;
|
||||
VkBuffer buffer;
|
||||
VkDeviceMemory memory;
|
||||
uint32_t count;
|
||||
int element_size;
|
||||
struct da_VK_FORMAT format;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue