Added example of using the ATTRIBUTE_ID_POSITION to update a UBO for a pipeline. Messy af and need to find a way to organize it so it makes sense.

main
noah metz 2024-01-10 13:19:41 -07:00
parent 9ae776a5e2
commit 9bfd2fab57
2 changed files with 218 additions and 50 deletions

@ -1,9 +1,13 @@
#version 450
layout(binding = 0) uniform UniformBufferObject {
layout(set = 0, binding = 0) uniform SceneUniformBuffer {
mat4 view;
mat4 proj;
} ubo;
} scene_ubo;
layout(set = 2, binding = 1) uniform ObjectUniformBuffer {
mat4 model;
} object_ubo;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
@ -13,7 +17,7 @@ layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTex;
void main() {
gl_Position = ubo.proj * ubo.view * vec4(inPosition, 1.0);
gl_Position = scene_ubo.proj * scene_ubo.view * object_ubo.model * vec4(inPosition, 1.0);
fragColor = inColor;
fragTex = inTex;
}

@ -260,15 +260,30 @@ void map_iterator_free(MapIterator iterator) {
}
typedef struct PositionStruct {
vec4 position;
vec3 position;
vec3 scale;
versor rotation;
} Position;
typedef struct AttributeMappingStruct {
uint32_t attribute_id; // Which attribute to map
typedef void(*MappingFunc)(void*,void*);
void attribute_mapping_position_to_matrix(void* dest, void* source) {
Position* position = source;
glm_translate_make(dest, position->position);
glm_quat_rotate(dest, position->rotation, dest);
glm_scale(dest, position->scale);
}
#define MAPPING_POSITION_TO_MATRIX 0
MappingFunc mapping_functions[] = {
attribute_mapping_position_to_matrix,
};
typedef struct MappingStruct {
uint32_t mapping_type; // What function to use to map it
uint32_t binding; // Which index to use in the ATTRIBUTE_ID_DESCRIPTORS array
} AttributeMapping;
uint32_t index; // Which index to use in the ATTRIBUTE_ID_DESCRIPTORS array
} Mapping;
#define ATTRIBUTE_ID_MESH 0x00000001 // Mesh*
#define ATTRIBUTE_ID_MATERIAL 0x00000002 // Material*
@ -387,23 +402,27 @@ struct Vertex {
vec3 color;
};
struct ModelUBO {
mat4 model;
};
struct SceneUBO {
mat4 view;
mat4 proj;
};
const struct Vertex vertices[] = {
{.pos = {-0.5f, -0.5f, 0.5f}, .color = {1.0f, 0.0f, 0.0f}},
{.pos = { 0.5f, -0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}},
{.pos = { 0.5f, 0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}},
{.pos = {-0.5f, 0.5f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}},
{.pos = {-1.f, -1.f, 0.f}, .color = {1.0f, 0.0f, 0.0f}},
{.pos = { 1.f, -1.f, 0.f}, .color = {0.0f, 1.0f, 0.0f}},
{.pos = { 1.f, 1.f, 0.f}, .color = {0.0f, 0.0f, 1.0f}},
{.pos = {-1.f, 1.f, 0.f}, .color = {1.0f, 1.0f, 1.0f}},
};
const struct TextureVertex texture_vertices[] = {
{.pos = {-0.5f, -0.5f, 0.5f}, .color = {1.0f, 0.0f, 0.0f}, .tex = {1.0f, 1.0f}},
{.pos = { 0.5f, -0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}, .tex = {0.0f, 1.0f}},
{.pos = { 0.5f, 0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}, .tex = {0.0f, 0.0f}},
{.pos = {-0.5f, 0.5f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}, .tex = {1.0f, 0.0f}},
{.pos = {-1.f, -1.f, 0.f}, .color = {1.0f, 0.0f, 0.0f}, .tex = {1.0f, 1.0f}},
{.pos = { 1.f, -1.f, 0.f}, .color = {0.0f, 1.0f, 0.0f}, .tex = {0.0f, 1.0f}},
{.pos = { 1.f, 1.f, 0.f}, .color = {0.0f, 0.0f, 1.0f}, .tex = {0.0f, 0.0f}},
{.pos = {-1.f, 1.f, 0.f}, .color = {1.0f, 1.0f, 1.0f}, .tex = {1.0f, 0.0f}},
};
const uint16_t indices[] = {
@ -447,6 +466,35 @@ GLFWwindow* init_window(int width, int height) {
return window;
}
void object_update_mappings(Material material, Object object, uint32_t frame_num) {
if(material.object_descriptor_mappings.buckets == 0) {
return;
}
MaybeValue maybe_descriptors = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTORS);
if(maybe_descriptors.has_value == false) {
return;
}
void** descriptors = ((void***)(maybe_descriptors.value))[frame_num];
MapIterator mapping_iterator = map_iterator_create(material.object_descriptor_mappings);
for(uint32_t i = 0; i < mapping_iterator.count; i++) {
MaybeValue maybe_attribute = map_lookup(object.attributes, mapping_iterator.keys[i]);
if(maybe_attribute.has_value == true) {
Mapping* mapping = mapping_iterator.vals[i];
if(mapping->mapping_type > sizeof(mapping_functions)/sizeof(MappingFunc)) {
fprintf(stderr, "material requested mapping_function 0x%02x which does not exist\n", mapping->mapping_type);
continue;
}
mapping_functions[mapping->mapping_type](descriptors[mapping->index], maybe_attribute.value);
} else {
fprintf(stderr, "material requested attribute 0x%02x from object, but it does not have it\n", mapping_iterator.keys[i]);
}
}
map_iterator_free(mapping_iterator);
}
VkFormat find_depth_format(VkPhysicalDevice physical_device, uint32_t num_requested, VkFormat* requested, VkImageTiling tiling, VkFormatFeatureFlags features) {
for(uint32_t i = 0; i < num_requested; i++) {
VkFormatProperties properties;
@ -1809,6 +1857,8 @@ void command_draw_object(Material material, Object object, uint32_t frame_num, V
return;
}
object_update_mappings(material, object, frame_num);
Mesh* mesh = maybe_mesh.value;
VkBuffer vertex_buffers[] = {mesh->vertex_buffer.buffer};
@ -1987,7 +2037,7 @@ Mesh load_texture_mesh(VkPhysicalDevice physical_device, VkDevice device, struct
return mesh;
}
Object create_object() {
Object create_object(uint32_t max_frames_in_flight, uint32_t descriptor_count) {
Object ret = {
.attributes = {
.buckets = 0,
@ -1999,50 +2049,72 @@ Object create_object() {
return ret;
}
if(descriptor_count > 0) {
void*** descriptor_arrays = malloc(sizeof(void**)*max_frames_in_flight);
if(descriptor_arrays == 0) {
return ret;
}
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
descriptor_arrays[i] = malloc(sizeof(void*)*descriptor_count);
if(descriptor_arrays[i] == 0) {
for(uint32_t j = 0; j < i; j++) {
free(descriptor_arrays[j]);
}
free(descriptor_arrays);
map_destroy(attributes);
}
}
bool result = map_add(&attributes, ATTRIBUTE_ID_DESCRIPTORS, descriptor_arrays);
if(result == false) {
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
free(descriptor_arrays[i]);
}
free(descriptor_arrays);
map_destroy(attributes);
}
}
ret.attributes = attributes;
return ret;
}
Object create_renderable(Mesh* mesh, Material* material, VkDescriptorSet* descriptor_sets) {
Object create_renderable(Mesh* mesh, Material* material, VkDescriptorSet* descriptor_sets, uint32_t max_frames_in_flight, uint32_t descriptor_count) {
Object zero = {
.attributes = {
.buckets = 0,
},
};
if(mesh == 0 || material == 0) {
Object object = create_object(max_frames_in_flight, descriptor_count);
if(object.attributes.buckets == 0) {
return zero;
}
Map attributes = map_create(8, 2);
if(attributes.buckets == 0) {
if(mesh == 0 || material == 0) {
return zero;
}
bool result = map_add(&attributes, ATTRIBUTE_ID_MESH, mesh);
bool result = map_add(&object.attributes, ATTRIBUTE_ID_MESH, mesh);
if(result == false) {
map_destroy(attributes);
map_destroy(object.attributes);
return zero;
}
result = map_add(&attributes, ATTRIBUTE_ID_MATERIAL, material);
result = map_add(&object.attributes, ATTRIBUTE_ID_MATERIAL, material);
if(result == false) {
map_destroy(attributes);
map_destroy(object.attributes);
return zero;
}
result = map_add(&attributes, ATTRIBUTE_ID_DESCRIPTOR_SETS, descriptor_sets);
result = map_add(&object.attributes, ATTRIBUTE_ID_DESCRIPTOR_SETS, descriptor_sets);
if(result == false) {
map_destroy(attributes);
map_destroy(object.attributes);
return zero;
}
Object ret = {
.attributes = attributes,
};
return ret;
return object;
}
Mesh load_simple_mesh(VkPhysicalDevice physical_device, VkDevice device, struct Vertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) {
@ -2083,7 +2155,8 @@ Material create_material(
VkDescriptorSetLayout scene_ubo_layout,
PipelineLayout pipeline_layout,
MeshType mesh_type,
uint32_t max_frames_in_flight
uint32_t max_frames_in_flight,
Map object_descriptor_mappings
) {
Material zero_material = {
.pipeline = VK_NULL_HANDLE,
@ -2204,6 +2277,7 @@ Material create_material(
.material_descriptors = material_descriptors,
.material_descriptor_pool = material_descriptor_pool,
.material_descriptors_count = max_frames_in_flight,
.object_descriptor_mappings = object_descriptor_mappings,
};
return material;
@ -2257,7 +2331,12 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende
};
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, simple_layout, simple_mesh_type, max_frames_in_flight);
Map empty_map = {
.buckets = 0,
.buckets_count = 0,
};
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, simple_layout, simple_mesh_type, max_frames_in_flight, empty_map);
}
Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) {
@ -2319,6 +2398,13 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
.pImmutableSamplers = 0,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
},
{
.binding = 1,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pImmutableSamplers = 0,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
},
};
MeshType textured_mesh_type = {
@ -2333,7 +2419,30 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
.object_bindings = mesh_set_bindings,
};
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight);
Map object_descriptor_mappings = map_create(8, 2);
if(object_descriptor_mappings.buckets == 0) {
Material tmp = {};
return tmp;
}
Mapping* position_mapping = malloc(sizeof(Mapping));
if(position_mapping == 0) {
map_destroy(object_descriptor_mappings);
Material tmp = {};
return tmp;
}
position_mapping->mapping_type = MAPPING_POSITION_TO_MATRIX;
position_mapping->index = 0;
bool map_result = map_add(&object_descriptor_mappings, ATTRIBUTE_ID_POSITION, position_mapping);
if(map_result != true) {
map_destroy(object_descriptor_mappings);
free(position_mapping);
Material tmp = {};
return tmp;
}
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings);
}
VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
@ -2649,7 +2758,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->triangle_mesh = triangle_mesh;
}
Object triangle_object = create_renderable(&context->triangle_mesh, &context->simple_mesh_material, 0);
Object triangle_object = create_renderable(&context->triangle_mesh, &context->simple_mesh_material, 0, 2, 0);
if(triangle_object.attributes.buckets == 0) {
fprintf(stderr, "failed to create renderable triangle object\n");
return 0;
@ -2678,11 +2787,15 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = max_frames_in_flight,
},
{
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = max_frames_in_flight,
},
};
VkDescriptorPoolCreateInfo TODO_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = 1,
.poolSizeCount = sizeof(TODO_sizes)/sizeof(VkDescriptorPoolSize),
.maxSets = max_frames_in_flight,
.pPoolSizes = TODO_sizes,
};
@ -2723,7 +2836,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
return 0;
}
Object triangle_object_textured = create_renderable(&context->triangle_mesh_textured, &context->texture_mesh_material, TODO_sets);
Object triangle_object_textured = create_renderable(&context->triangle_mesh_textured, &context->texture_mesh_material, TODO_sets, max_frames_in_flight, 1);
if(triangle_object_textured.attributes.buckets == 0) {
fprintf(stderr, "failed to create renderable textured triangle object\n");
return 0;
@ -2731,6 +2844,57 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->triangle_object_textured = triangle_object_textured;
}
Position* position = malloc(sizeof(Position));
if(position == 0) {
return 0;
}
glm_quat_identity(position->rotation);
position->scale[0] = 0.1f;
position->scale[1] = 0.1f;
position->scale[2] = 0.1f;
position->position[2] = 1.0f;
bool map_result = map_add(&triangle_object_textured.attributes, ATTRIBUTE_ID_POSITION, position);
if(map_result == 0) {
return 0;
}
AllocatedBuffer* triangle_ubos = allocate_buffers(context->physical_device, context->device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight);
if(triangle_ubos == 0) {
return 0;
}
MaybeValue maybe_descriptors = map_lookup(triangle_object_textured.attributes, ATTRIBUTE_ID_DESCRIPTORS);
if(maybe_descriptors.has_value == false) {
return 0;
}
void*** descriptors = maybe_descriptors.value;
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
VkResult result = vkMapMemory(device, triangle_ubos[i].memory, 0, sizeof(Position), 0, &descriptors[i][0]);
if(result != VK_SUCCESS) {
return 0;
}
VkDescriptorBufferInfo buffer_info = {
.buffer = triangle_ubos[i].buffer,
.offset = 0,
.range = sizeof(struct ModelUBO),
};
VkWriteDescriptorSet write_info = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = TODO_sets[i],
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.pBufferInfo = &buffer_info,
};
vkUpdateDescriptorSets(context->device, 1, &write_info, 0, 0);
}
VkExtent2D texture_size = {
.width = 10,
.height = 10,
@ -2932,20 +3096,20 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl
movement_sum[2] += 1 * time_delta;
}
if(key_flags.left) {
if(key_flags.right) {
movement_sum[0] += 1 * time_delta;
}
if(key_flags.right) {
if(key_flags.left) {
movement_sum[0] -= 1 * time_delta;
}
if(key_flags.up) {
movement_sum[1] += 1 * time_delta;
movement_sum[1] -= 1 * time_delta;
}
if(key_flags.down) {
movement_sum[1] -= 1 * time_delta;
movement_sum[1] += 1 * time_delta;
}
@ -2959,11 +3123,11 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl
}
if(key_flags.turn_up) {
eular_rotation[1] += 1 * time_delta;
eular_rotation[1] -= 1 * time_delta;
}
if(key_flags.turn_down) {
eular_rotation[1] -= 1 * time_delta;
eular_rotation[1] += 1 * time_delta;
}
if(key_flags.roll_right) {
@ -2974,15 +3138,15 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl
eular_rotation[2] -= 1 * time_delta;
}
vec3 left = {1.0f, 0.0f, 0.0f};
vec3 up = {0.0f, -1.0f, 0.0f};
vec3 right = {1.0f, 0.0f, 0.0f};
vec3 up = {0.0f, 1.0f, 0.0f};
vec3 forward = {0.0f, 0.0f, 1.0f};
glm_quat_rotatev(world_rotation, left, left);
glm_quat_rotatev(world_rotation, right, right);
glm_quat_rotatev(world_rotation, up, up);
glm_quat_rotatev(world_rotation, forward, forward);
versor relative_rotation_y;
glm_quatv(relative_rotation_y, eular_rotation[1], left);
glm_quatv(relative_rotation_y, eular_rotation[1], right);
versor relative_rotation_x;
glm_quatv(relative_rotation_x, eular_rotation[0], up);
@ -3000,7 +3164,7 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl
struct SceneUBO ubo = {};
glm_perspective(100.0f, aspect_ratio, 0.01, 100, ubo.proj);
glm_perspective(1.5708f, aspect_ratio, 0.01, 1000, ubo.proj);
glm_quat_look(world_position, world_rotation, ubo.view);
memcpy(buffers[frame_index], (void*)&ubo, sizeof(ubo));