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 = 0) in vec2 inPosition;
|
||||||
layout(location = 1) in vec3 inColor;
|
layout(location = 1) in vec3 inColor;
|
||||||
|
layout(location = 2) in mat3 offset;
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform UBO {
|
layout(set = 0, binding = 0) uniform UBO {
|
||||||
mat3 model;
|
mat3 model;
|
||||||
|
@ -13,7 +14,7 @@ layout(location = 0) out vec3 fragColor;
|
||||||
layout(location = 1) out vec2 fragUV;
|
layout(location = 1) out vec2 fragUV;
|
||||||
|
|
||||||
void main() {
|
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;
|
fragColor = inColor;
|
||||||
fragUV = inPosition;
|
fragUV = inPosition;
|
||||||
}
|
}
|
||||||
|
|
167
kitty.c
167
kitty.c
|
@ -13,6 +13,7 @@ struct Kitty *kitty_make() {
|
||||||
memset(kitty, 0, sizeof(struct Kitty));
|
memset(kitty, 0, sizeof(struct Kitty));
|
||||||
dyn_array_create_inplace(&kitty->attatchments);
|
dyn_array_create_inplace(&kitty->attatchments);
|
||||||
dyn_array_create_inplace(&kitty->vertex_buffer.format);
|
dyn_array_create_inplace(&kitty->vertex_buffer.format);
|
||||||
|
dyn_array_create_inplace(&kitty->instance_buffer.format);
|
||||||
meow("alloced a kitty at %p", kitty);
|
meow("alloced a kitty at %p", kitty);
|
||||||
return 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;
|
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) {
|
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);
|
dyn_array_append(&kitty->vertex_buffer.format, format);
|
||||||
}
|
}
|
||||||
void kitty_attatch_image(struct Kitty *kitty, const char *path) {
|
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_ubo_attatchments(kitty, state);
|
||||||
kitty_create_descriptor_sets(kitty, state);
|
kitty_create_descriptor_sets(kitty, state);
|
||||||
kitty_create_vertex_buffer(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);
|
dyn_array_append(&state->kitties, kitty);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +90,10 @@ void free_kitty(struct Vk *state, struct Kitty *kitty) {
|
||||||
vkDeviceWaitIdle(state->device);
|
vkDeviceWaitIdle(state->device);
|
||||||
vkDestroyBuffer(state->device, kitty->vertex_buffer.buffer, NULL);
|
vkDestroyBuffer(state->device, kitty->vertex_buffer.buffer, NULL);
|
||||||
vkFreeMemory(state->device, kitty->vertex_buffer.memory, 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);
|
vkDestroyDescriptorPool(state->device, kitty->descriptor_pool, NULL);
|
||||||
vkDestroyDescriptorSetLayout(state->device, kitty->descriptor_set_layout,
|
vkDestroyDescriptorSetLayout(state->device, kitty->descriptor_set_layout,
|
||||||
NULL);
|
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};
|
scissor.extent = (VkExtent2D){state->width, state->heigh};
|
||||||
vkCmdSetScissor(flight.command_buffer, 0, 1, &scissor);
|
vkCmdSetScissor(flight.command_buffer, 0, 1, &scissor);
|
||||||
|
|
||||||
VkBuffer vertex_buffer[] = {kitty->vertex_buffer.buffer};
|
uint64_t offsets[1] = {0};
|
||||||
VkDeviceSize offsets[] = {0};
|
vkCmdBindVertexBuffers(flight.command_buffer, 0, 1,
|
||||||
vkCmdBindVertexBuffers(flight.command_buffer, 0, 1, vertex_buffer, offsets);
|
&kitty->vertex_buffer.buffer, offsets);
|
||||||
|
|
||||||
|
if (kitty->instance_buffer.count != 0) {
|
||||||
|
vkCmdBindVertexBuffers(flight.command_buffer, 1, 1,
|
||||||
|
&kitty->instance_buffer.buffer, offsets);
|
||||||
|
}
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(
|
vkCmdBindDescriptorSets(
|
||||||
flight.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
flight.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
kitty->pipeline_layout, 0, 1,
|
kitty->pipeline_layout, 0, 1,
|
||||||
&kitty->descriptor_sets[state->current_frame], 0, NULL);
|
&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) {
|
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,
|
VkPipelineShaderStageCreateInfo shader_stage_info[] = {vert_stage_info,
|
||||||
frag_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};
|
VkPipelineVertexInputStateCreateInfo vertex_input_info = {0};
|
||||||
vertex_input_info.sType =
|
if (kitty->instance_buffer.count == 0) {
|
||||||
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
meow("single instance kitty");
|
||||||
vertex_input_info.vertexBindingDescriptionCount = 1;
|
VkVertexInputBindingDescription vertex_binding_description = {0};
|
||||||
vertex_input_info.pVertexBindingDescriptions = &vertex_binding_description;
|
vertex_binding_description.binding = 0;
|
||||||
vertex_input_info.vertexAttributeDescriptionCount =
|
vertex_binding_description.stride = kitty->vertex_buffer.vertex_size;
|
||||||
kitty->vertex_buffer.format.count;
|
vertex_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
vertex_input_info.pVertexAttributeDescriptions =
|
|
||||||
vertex_attribute_descriptions;
|
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};
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {0};
|
||||||
input_assembly_info.sType =
|
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);
|
vkFreeMemory(state->device, staging_buffer_memory, NULL);
|
||||||
kitty->vertex_buffer.data = 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;
|
const char *fragment_path;
|
||||||
|
|
||||||
struct VertexBuffer vertex_buffer;
|
struct VertexBuffer vertex_buffer;
|
||||||
|
struct InstanceBuffer instance_buffer;
|
||||||
struct IndexBuffer index_buffer;
|
struct IndexBuffer index_buffer;
|
||||||
|
|
||||||
struct da_Attatchment attatchments;
|
struct da_Attatchment attatchments;
|
||||||
|
@ -68,6 +69,13 @@ void kitty_add_vertex_buffer_format(struct Kitty *thingy, enum VkFormat format);
|
||||||
// transferred
|
// transferred
|
||||||
void kitty_add_index_buffer(struct Kitty *kitty, void *data, uint32_t count);
|
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);
|
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
|
// 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_ubo_attatchments(struct Kitty *kitty, struct Vk *state);
|
||||||
void kitty_create_descriptor_sets(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_vertex_buffer(struct Kitty *kitty, struct Vk *state);
|
||||||
|
void kitty_create_instance_buffer(struct Kitty *kitty, struct Vk *state);
|
||||||
|
|
||||||
#endif // INCLUDE_KITTY
|
#endif // INCLUDE_KITTY
|
||||||
|
|
10
vulkan.h
10
vulkan.h
|
@ -28,7 +28,15 @@ struct VertexBuffer {
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
int vertex_size;
|
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;
|
struct da_VK_FORMAT format;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue