|
|
@ -64,6 +64,156 @@ typedef struct TextureStruct {
|
|
|
|
VkSampler sampler;
|
|
|
|
VkSampler sampler;
|
|
|
|
} Texture;
|
|
|
|
} Texture;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct EntryStruct {
|
|
|
|
|
|
|
|
uint32_t key;
|
|
|
|
|
|
|
|
void* value;
|
|
|
|
|
|
|
|
} Entry;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct MapStruct {
|
|
|
|
|
|
|
|
uint32_t buckets_count;
|
|
|
|
|
|
|
|
Entry** buckets;
|
|
|
|
|
|
|
|
uint32_t* bucket_sizes;
|
|
|
|
|
|
|
|
uint32_t* bucket_usage;
|
|
|
|
|
|
|
|
} Map;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map map_create(uint32_t buckets_count, uint32_t initial_bucket_size) {
|
|
|
|
|
|
|
|
Map zero = {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Entry** buckets = malloc(sizeof(Entry*)*buckets_count);
|
|
|
|
|
|
|
|
if(buckets == 0) {
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t* bucket_sizes = malloc(sizeof(uint32_t)*buckets_count);
|
|
|
|
|
|
|
|
if(bucket_sizes == 0) {
|
|
|
|
|
|
|
|
free(buckets);
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t* bucket_usage = malloc(sizeof(uint32_t)*buckets_count);
|
|
|
|
|
|
|
|
if(bucket_usage == 0) {
|
|
|
|
|
|
|
|
free(bucket_usage);
|
|
|
|
|
|
|
|
free(buckets);
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < buckets_count; i++) {
|
|
|
|
|
|
|
|
Entry* bucket = malloc(sizeof(Entry)*initial_bucket_size);
|
|
|
|
|
|
|
|
if(bucket == 0) {
|
|
|
|
|
|
|
|
for(uint32_t j = 0; j < i; j++) {
|
|
|
|
|
|
|
|
free(buckets[j]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
free(bucket_sizes);
|
|
|
|
|
|
|
|
free(buckets);
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
buckets[i] = bucket;
|
|
|
|
|
|
|
|
bucket_sizes[i] = initial_bucket_size;
|
|
|
|
|
|
|
|
bucket_usage[i] = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map ret = {
|
|
|
|
|
|
|
|
.buckets_count = buckets_count,
|
|
|
|
|
|
|
|
.bucket_sizes = bucket_sizes,
|
|
|
|
|
|
|
|
.bucket_usage = bucket_usage,
|
|
|
|
|
|
|
|
.buckets = buckets,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct MaybeValueStruct {
|
|
|
|
|
|
|
|
bool has_value;
|
|
|
|
|
|
|
|
void* value;
|
|
|
|
|
|
|
|
} MaybeValue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MaybeValue map_lookup(Map map, uint32_t key) {
|
|
|
|
|
|
|
|
MaybeValue ret = {
|
|
|
|
|
|
|
|
.has_value = false,
|
|
|
|
|
|
|
|
.value = 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t bucket_index = key % map.buckets_count;
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < map.bucket_usage[bucket_index]; i++) {
|
|
|
|
|
|
|
|
if(map.buckets[bucket_index][i].key == key) {
|
|
|
|
|
|
|
|
ret.has_value = true;
|
|
|
|
|
|
|
|
ret.value = map.buckets[bucket_index][i].value;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool map_add(Map* map, uint32_t key, void* value) {
|
|
|
|
|
|
|
|
uint32_t bucket_index = key % map->buckets_count;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < map->bucket_usage[bucket_index]; i++) {
|
|
|
|
|
|
|
|
if(map->buckets[bucket_index][i].key == key) {
|
|
|
|
|
|
|
|
map->buckets[bucket_index][i].value = value;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(map->bucket_usage[bucket_index] < map->bucket_sizes[bucket_index]) {
|
|
|
|
|
|
|
|
map->buckets[bucket_index][map->bucket_usage[bucket_index]].key = key;
|
|
|
|
|
|
|
|
map->buckets[bucket_index][map->bucket_usage[bucket_index]].value = value;
|
|
|
|
|
|
|
|
map->bucket_usage[bucket_index] += 1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Entry* new_bucket = realloc(map->buckets[bucket_index], 2*map->bucket_sizes[bucket_index]);
|
|
|
|
|
|
|
|
if(new_bucket == 0) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map->bucket_usage[bucket_index] += 1;
|
|
|
|
|
|
|
|
map->bucket_sizes[bucket_index] *= 2;
|
|
|
|
|
|
|
|
map->buckets[bucket_index] = new_bucket;
|
|
|
|
|
|
|
|
map->buckets[bucket_index][map->bucket_usage[bucket_index]].key = key;
|
|
|
|
|
|
|
|
map->buckets[bucket_index][map->bucket_usage[bucket_index]].value = value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MaybeValue map_del(Map* map, uint32_t key) {
|
|
|
|
|
|
|
|
MaybeValue ret = {
|
|
|
|
|
|
|
|
.has_value = false,
|
|
|
|
|
|
|
|
.value = 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t bucket_index = key % map->buckets_count;
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < map->bucket_usage[bucket_index]; i++) {
|
|
|
|
|
|
|
|
if(map->buckets[bucket_index][i].key == key) {
|
|
|
|
|
|
|
|
ret.value = map->buckets[bucket_index][i].value;
|
|
|
|
|
|
|
|
ret.has_value = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(map->bucket_usage[bucket_index] > 1) {
|
|
|
|
|
|
|
|
map->buckets[bucket_index][i] = map->buckets[bucket_index][map->bucket_usage[bucket_index]-1];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
map->bucket_usage[bucket_index] -= 1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void map_destroy(Map map) {
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < map.buckets_count; i++) {
|
|
|
|
|
|
|
|
free(map.buckets[i]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
free(map.buckets);
|
|
|
|
|
|
|
|
free(map.bucket_sizes);
|
|
|
|
|
|
|
|
free(map.bucket_usage);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define ATTRIBUTE_ID_MESH 0x00000001
|
|
|
|
|
|
|
|
#define ATTRIBUTE_ID_MATERIAL 0x00000002
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct ObjectStruct {
|
|
|
|
|
|
|
|
Map attributes;
|
|
|
|
|
|
|
|
} Object;
|
|
|
|
|
|
|
|
|
|
|
|
// Defines how a mesh is read from a buffer into a graphics pipeline
|
|
|
|
// Defines how a mesh is read from a buffer into a graphics pipeline
|
|
|
|
typedef struct MeshTypeStruct {
|
|
|
|
typedef struct MeshTypeStruct {
|
|
|
|
uint32_t bindings_count;
|
|
|
|
uint32_t bindings_count;
|
|
|
@ -90,29 +240,16 @@ typedef struct MeshStruct {
|
|
|
|
AllocatedBuffer index_buffer;
|
|
|
|
AllocatedBuffer index_buffer;
|
|
|
|
} Mesh;
|
|
|
|
} Mesh;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct DescriptorPoolStruct {
|
|
|
|
|
|
|
|
VkDescriptorPool handle;
|
|
|
|
|
|
|
|
uint32_t allocated;
|
|
|
|
|
|
|
|
} DescriptorPool;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct GrowingDescriptorPoolStruct {
|
|
|
|
|
|
|
|
uint32_t num_pool_sizes;
|
|
|
|
|
|
|
|
VkDescriptorPoolSize* pool_sizes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t sets_per_pool;
|
|
|
|
|
|
|
|
VkDescriptorPoolCreateInfo pool_info;
|
|
|
|
|
|
|
|
VkDescriptorSetLayout set_layout;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t num_pools;
|
|
|
|
|
|
|
|
DescriptorPool* pools;
|
|
|
|
|
|
|
|
} GrowingDescriptorPool;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct MaterialStruct {
|
|
|
|
typedef struct MaterialStruct {
|
|
|
|
VkDescriptorSetLayout material_set_layout;
|
|
|
|
VkDescriptorSetLayout material_set_layout;
|
|
|
|
VkDescriptorSetLayout mesh_set_layout;
|
|
|
|
VkDescriptorSetLayout mesh_set_layout;
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineLayout layout;
|
|
|
|
VkPipelineLayout layout;
|
|
|
|
VkPipeline pipeline;
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPool material_descriptor_pool;
|
|
|
|
|
|
|
|
VkDescriptorSet* material_descriptors;
|
|
|
|
|
|
|
|
uint32_t material_descriptors_count;
|
|
|
|
} Material;
|
|
|
|
} Material;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
@ -155,9 +292,9 @@ typedef struct VulkanContextStruct {
|
|
|
|
VkCommandPool graphics_command_pool;
|
|
|
|
VkCommandPool graphics_command_pool;
|
|
|
|
VkCommandPool transfer_command_pool;
|
|
|
|
VkCommandPool transfer_command_pool;
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPool scene_ubo_pool;
|
|
|
|
VkDescriptorPool scene_pool;
|
|
|
|
VkDescriptorSetLayout scene_ubo_layout;
|
|
|
|
VkDescriptorSetLayout scene_descriptor_layout;
|
|
|
|
VkDescriptorSet* scene_ubo_descriptors;
|
|
|
|
VkDescriptorSet* scene_descriptors;
|
|
|
|
AllocatedBuffer* scene_ubos;
|
|
|
|
AllocatedBuffer* scene_ubos;
|
|
|
|
void** scene_ubo_ptrs;
|
|
|
|
void** scene_ubo_ptrs;
|
|
|
|
|
|
|
|
|
|
|
@ -165,6 +302,8 @@ typedef struct VulkanContextStruct {
|
|
|
|
Mesh triangle_mesh_textured;
|
|
|
|
Mesh triangle_mesh_textured;
|
|
|
|
Material simple_mesh_material;
|
|
|
|
Material simple_mesh_material;
|
|
|
|
Material texture_mesh_material;
|
|
|
|
Material texture_mesh_material;
|
|
|
|
|
|
|
|
Object triangle_object;
|
|
|
|
|
|
|
|
Object triangle_object_textured;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t current_frame;
|
|
|
|
uint32_t current_frame;
|
|
|
|
} VulkanContext;
|
|
|
|
} VulkanContext;
|
|
|
@ -300,122 +439,6 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
|
|
|
|
return VK_FALSE;
|
|
|
|
return VK_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GrowingDescriptorPool create_growing_descriptor_pool(VkDevice device, uint32_t num_bindings, VkDescriptorSetLayoutBinding* bindings, uint32_t sets_per_pool) {
|
|
|
|
|
|
|
|
GrowingDescriptorPool ret = {
|
|
|
|
|
|
|
|
.sets_per_pool = sets_per_pool,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutCreateInfo layout_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
|
|
|
|
|
|
.bindingCount = num_bindings,
|
|
|
|
|
|
|
|
.pBindings = bindings,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayout layout;
|
|
|
|
|
|
|
|
VkResult result = vkCreateDescriptorSetLayout(device, &layout_info, 0, &layout);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPoolSize* pool_sizes = malloc(sizeof(VkDescriptorPoolSize)*num_bindings);
|
|
|
|
|
|
|
|
if(pool_sizes == 0) {
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < num_bindings; i++) {
|
|
|
|
|
|
|
|
VkDescriptorPoolSize size = {
|
|
|
|
|
|
|
|
.type = bindings[i].descriptorType,
|
|
|
|
|
|
|
|
.descriptorCount = bindings[i].descriptorCount * sets_per_pool,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
pool_sizes[i] = size;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPoolCreateInfo pool_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
|
|
|
|
|
|
|
.poolSizeCount = num_bindings,
|
|
|
|
|
|
|
|
.pPoolSizes = pool_sizes,
|
|
|
|
|
|
|
|
.maxSets = sets_per_pool,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DescriptorPool* pools = malloc(sizeof(DescriptorPool));
|
|
|
|
|
|
|
|
if(pools == 0) {
|
|
|
|
|
|
|
|
free(pool_sizes);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkCreateDescriptorPool(device, &pool_info, 0, &pools[0].handle);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
free(pool_sizes);
|
|
|
|
|
|
|
|
free(pools);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret.set_layout = layout;
|
|
|
|
|
|
|
|
ret.pool_info = pool_info;
|
|
|
|
|
|
|
|
ret.pools = pools;
|
|
|
|
|
|
|
|
ret.num_pools = 1;
|
|
|
|
|
|
|
|
ret.pool_info = pool_info;
|
|
|
|
|
|
|
|
ret.pool_sizes = pool_sizes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DescriptorPool* grow_descriptor_pool(VkDevice device, GrowingDescriptorPool* pool) {
|
|
|
|
|
|
|
|
VkDescriptorPool handle;
|
|
|
|
|
|
|
|
VkResult result = vkCreateDescriptorPool(device, &pool->pool_info, 0, &handle);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t new_size = pool->num_pools + 1;
|
|
|
|
|
|
|
|
DescriptorPool* new_pools = realloc(pool->pools, sizeof(DescriptorPool)*new_size);
|
|
|
|
|
|
|
|
if(new_pools == 0) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new_pools[new_size-1].allocated = 0;
|
|
|
|
|
|
|
|
new_pools[new_size-1].handle = handle;
|
|
|
|
|
|
|
|
pool->pools = new_pools;
|
|
|
|
|
|
|
|
pool->num_pools = new_size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return &new_pools[new_size-1];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSet allocate_descriptor_set(VkDevice device, GrowingDescriptorPool* pool) {
|
|
|
|
|
|
|
|
DescriptorPool* selected_pool = 0;
|
|
|
|
|
|
|
|
uint32_t index = 0;
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < pool->num_pools; i++) {
|
|
|
|
|
|
|
|
if(pool->pools[i].allocated < pool->sets_per_pool) {
|
|
|
|
|
|
|
|
selected_pool = &pool->pools[i];
|
|
|
|
|
|
|
|
index = i;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(selected_pool == 0) {
|
|
|
|
|
|
|
|
selected_pool = grow_descriptor_pool(device, pool);
|
|
|
|
|
|
|
|
index = pool->num_pools - 1;
|
|
|
|
|
|
|
|
if(selected_pool == 0) {
|
|
|
|
|
|
|
|
return VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetAllocateInfo alloc_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
|
|
|
|
|
|
.descriptorPool = selected_pool->handle,
|
|
|
|
|
|
|
|
.pSetLayouts = &pool->set_layout,
|
|
|
|
|
|
|
|
.descriptorSetCount = 1,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSet new_set;
|
|
|
|
|
|
|
|
VkResult result = vkAllocateDescriptorSets(device, &alloc_info, &new_set);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pool->pools[index].allocated += 1;
|
|
|
|
|
|
|
|
return new_set;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSet* create_descriptor_sets(VkDevice device, VkDescriptorSetLayout layout, VkDescriptorPool pool, uint32_t count) {
|
|
|
|
VkDescriptorSet* create_descriptor_sets(VkDevice device, VkDescriptorSetLayout layout, VkDescriptorPool pool, uint32_t count) {
|
|
|
|
VkDescriptorSetLayout* layouts = malloc(sizeof(VkDescriptorSetLayout)*count);
|
|
|
|
VkDescriptorSetLayout* layouts = malloc(sizeof(VkDescriptorSetLayout)*count);
|
|
|
|
if(layouts == 0) {
|
|
|
|
if(layouts == 0) {
|
|
|
@ -1056,24 +1079,6 @@ VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFo
|
|
|
|
return render_pass;
|
|
|
|
return render_pass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineLayout create_pipeline_layout(VkDevice device, uint32_t set_count, VkDescriptorSetLayout* sets, uint32_t pcr_count, VkPushConstantRange* pcrs) {
|
|
|
|
|
|
|
|
VkPipelineLayout layout;
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo layout_info = {};
|
|
|
|
|
|
|
|
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
|
|
|
|
|
|
layout_info.setLayoutCount = set_count;
|
|
|
|
|
|
|
|
layout_info.pSetLayouts = sets;
|
|
|
|
|
|
|
|
layout_info.pushConstantRangeCount = pcr_count;
|
|
|
|
|
|
|
|
layout_info.pPushConstantRanges = pcrs;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
result = vkCreatePipelineLayout(device, &layout_info, 0, &layout);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return layout;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter, VkMemoryPropertyFlags properties) {
|
|
|
|
uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter, VkMemoryPropertyFlags properties) {
|
|
|
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
|
|
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
|
|
|
@ -1690,25 +1695,35 @@ VkResult recreate_swap_chain(VulkanContext* context, VkExtent2D new_extent) {
|
|
|
|
return VK_SUCCESS;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) {
|
|
|
|
void command_draw_mesh(Object object, VkCommandBuffer command_buffer) {
|
|
|
|
VkBuffer vertex_buffers[] = {mesh.vertex_buffer.buffer};
|
|
|
|
MaybeValue maybe_mesh = map_lookup(object.attributes, ATTRIBUTE_ID_MESH);
|
|
|
|
|
|
|
|
if(maybe_mesh.has_value == false) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Mesh* mesh = maybe_mesh.value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkBuffer vertex_buffers[] = {mesh->vertex_buffer.buffer};
|
|
|
|
VkDeviceSize offsets[] = {0};
|
|
|
|
VkDeviceSize offsets[] = {0};
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
|
|
|
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
|
|
|
|
vkCmdBindIndexBuffer(command_buffer, mesh.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
|
|
|
vkCmdBindIndexBuffer(command_buffer, mesh->index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0);
|
|
|
|
vkCmdDrawIndexed(command_buffer, mesh->index_count, 1, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) {
|
|
|
|
void command_draw_material(Material material, uint32_t mesh_count, Object* objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, VkCommandBuffer command_buffer) {
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline);
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline);
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_ubo_descriptor, 0, 0);
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_descriptors[frame_num], 0, 0);
|
|
|
|
|
|
|
|
if(material.material_descriptors != 0) {
|
|
|
|
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 1, 1, &material.material_descriptors[frame_num], 0, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
for(uint32_t i = 0; i < mesh_count; i++) {
|
|
|
|
for(uint32_t i = 0; i < mesh_count; i++) {
|
|
|
|
record_command_buffer_mesh(meshes[i], command_buffer);
|
|
|
|
command_draw_mesh(objects[i], command_buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult record_command_buffer_scene(uint32_t materials_count, Material* materials, uint32_t* mesh_counts, Mesh** meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent) {
|
|
|
|
VkResult command_draw_scene(uint32_t materials_count, Material* materials, uint32_t* mesh_counts, Object** objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent) {
|
|
|
|
VkCommandBufferBeginInfo begin_info = {};
|
|
|
|
VkCommandBufferBeginInfo begin_info = {};
|
|
|
|
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
|
|
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
|
|
begin_info.flags = 0;
|
|
|
|
begin_info.flags = 0;
|
|
|
@ -1757,7 +1772,7 @@ VkResult record_command_buffer_scene(uint32_t materials_count, Material* materia
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
|
|
|
|
|
|
|
|
|
|
|
for(uint i = 0; i < materials_count; i++) {
|
|
|
|
for(uint i = 0; i < materials_count; i++) {
|
|
|
|
record_command_buffer_material(materials[i], mesh_counts[i], meshes[i], scene_ubo_descriptor, command_buffer);
|
|
|
|
command_draw_material(materials[i], mesh_counts[i], objects[i], frame_num, scene_descriptors, command_buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdEndRenderPass(command_buffer);
|
|
|
|
vkCmdEndRenderPass(command_buffer);
|
|
|
@ -1854,6 +1869,58 @@ Mesh load_texture_mesh(VkPhysicalDevice physical_device, VkDevice device, struct
|
|
|
|
return mesh;
|
|
|
|
return mesh;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object create_object() {
|
|
|
|
|
|
|
|
Object ret = {
|
|
|
|
|
|
|
|
.attributes = {
|
|
|
|
|
|
|
|
.buckets = 0,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map attributes = map_create(8, 2);
|
|
|
|
|
|
|
|
if(attributes.buckets == 0) {
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret.attributes = attributes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object create_renderable(Mesh* mesh, Material* material) {
|
|
|
|
|
|
|
|
Object zero = {
|
|
|
|
|
|
|
|
.attributes = {
|
|
|
|
|
|
|
|
.buckets = 0,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(mesh == 0 || material == 0) {
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map attributes = map_create(8, 2);
|
|
|
|
|
|
|
|
if(attributes.buckets == 0) {
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool result = map_add(&attributes, ATTRIBUTE_ID_MESH, mesh);
|
|
|
|
|
|
|
|
if(result == false) {
|
|
|
|
|
|
|
|
map_destroy(attributes);
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = map_add(&attributes, ATTRIBUTE_ID_MATERIAL, material);
|
|
|
|
|
|
|
|
if(result == false) {
|
|
|
|
|
|
|
|
map_destroy(attributes);
|
|
|
|
|
|
|
|
return zero;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object ret = {
|
|
|
|
|
|
|
|
.attributes = attributes,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
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) {
|
|
|
|
Mesh mesh = {};
|
|
|
|
Mesh mesh = {};
|
|
|
|
mesh.vertex_buffer.buffer = VK_NULL_HANDLE;
|
|
|
|
mesh.vertex_buffer.buffer = VK_NULL_HANDLE;
|
|
|
@ -1883,8 +1950,6 @@ Mesh load_simple_mesh(VkPhysicalDevice physical_device, VkDevice device, struct
|
|
|
|
return mesh;
|
|
|
|
return mesh;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t HARDCODED_SETS_PER_POOL = 10;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Material create_material(
|
|
|
|
Material create_material(
|
|
|
|
VkDevice device,
|
|
|
|
VkDevice device,
|
|
|
|
VkExtent2D extent,
|
|
|
|
VkExtent2D extent,
|
|
|
@ -1893,7 +1958,8 @@ Material create_material(
|
|
|
|
VkPipelineShaderStageCreateInfo* shader_stages,
|
|
|
|
VkPipelineShaderStageCreateInfo* shader_stages,
|
|
|
|
VkDescriptorSetLayout scene_ubo_layout,
|
|
|
|
VkDescriptorSetLayout scene_ubo_layout,
|
|
|
|
PipelineLayout pipeline_layout,
|
|
|
|
PipelineLayout pipeline_layout,
|
|
|
|
MeshType mesh_type
|
|
|
|
MeshType mesh_type,
|
|
|
|
|
|
|
|
uint32_t max_frames_in_flight
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
Material zero_material = {
|
|
|
|
Material zero_material = {
|
|
|
|
.pipeline = VK_NULL_HANDLE,
|
|
|
|
.pipeline = VK_NULL_HANDLE,
|
|
|
@ -1904,6 +1970,9 @@ Material create_material(
|
|
|
|
VkDescriptorSetLayout all_layouts[3] = {scene_ubo_layout, VK_NULL_HANDLE, VK_NULL_HANDLE};
|
|
|
|
VkDescriptorSetLayout all_layouts[3] = {scene_ubo_layout, VK_NULL_HANDLE, VK_NULL_HANDLE};
|
|
|
|
uint32_t num_layouts = 1;
|
|
|
|
uint32_t num_layouts = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPool material_descriptor_pool = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
VkDescriptorSet* material_descriptors = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(pipeline_layout.material_bindings_count > 0) {
|
|
|
|
if(pipeline_layout.material_bindings_count > 0) {
|
|
|
|
VkDescriptorSetLayoutCreateInfo layout_info = {
|
|
|
|
VkDescriptorSetLayoutCreateInfo layout_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
|
@ -1916,6 +1985,61 @@ Material create_material(
|
|
|
|
return zero_material;
|
|
|
|
return zero_material;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
material_descriptors = malloc(sizeof(VkDescriptorSet)*max_frames_in_flight);
|
|
|
|
|
|
|
|
if(material_descriptors == 0) {
|
|
|
|
|
|
|
|
return zero_material;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPoolSize* pool_sizes = malloc(sizeof(VkDescriptorPool)*pipeline_layout.material_bindings_count);
|
|
|
|
|
|
|
|
if(pool_sizes == 0) {
|
|
|
|
|
|
|
|
return zero_material;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < pipeline_layout.material_bindings_count; i++) {
|
|
|
|
|
|
|
|
VkDescriptorPoolSize pool_size = {
|
|
|
|
|
|
|
|
.type = pipeline_layout.material_bindings[i].descriptorType,
|
|
|
|
|
|
|
|
.descriptorCount = pipeline_layout.material_bindings[i].descriptorCount,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
pool_sizes[i] = pool_size;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPoolCreateInfo pool_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
|
|
|
|
|
|
|
.poolSizeCount = pipeline_layout.material_bindings_count,
|
|
|
|
|
|
|
|
.maxSets = max_frames_in_flight,
|
|
|
|
|
|
|
|
.pPoolSizes = pool_sizes,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkCreateDescriptorPool(device, &pool_info, 0, &material_descriptor_pool);
|
|
|
|
|
|
|
|
free(pool_sizes);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return zero_material;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayout* set_layouts = malloc(sizeof(VkDescriptorSetLayout)*max_frames_in_flight);
|
|
|
|
|
|
|
|
if(set_layouts == 0) {
|
|
|
|
|
|
|
|
vkDestroyDescriptorPool(device, material_descriptor_pool, 0);
|
|
|
|
|
|
|
|
return zero_material;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
|
|
|
|
|
|
|
|
set_layouts[i] = material_set_layout;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetAllocateInfo alloc_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
|
|
|
|
|
|
.descriptorSetCount = max_frames_in_flight,
|
|
|
|
|
|
|
|
.descriptorPool = material_descriptor_pool,
|
|
|
|
|
|
|
|
.pSetLayouts = set_layouts,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkAllocateDescriptorSets(device, &alloc_info, material_descriptors);
|
|
|
|
|
|
|
|
free(set_layouts);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
vkDestroyDescriptorPool(device, material_descriptor_pool, 0);
|
|
|
|
|
|
|
|
return zero_material;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
all_layouts[num_layouts] = material_set_layout;
|
|
|
|
all_layouts[num_layouts] = material_set_layout;
|
|
|
|
num_layouts += 1;
|
|
|
|
num_layouts += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1936,9 +2060,17 @@ Material create_material(
|
|
|
|
num_layouts += 1;
|
|
|
|
num_layouts += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineLayout layout;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo layout_info = {};
|
|
|
|
|
|
|
|
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
|
|
|
|
|
|
layout_info.setLayoutCount = num_layouts;
|
|
|
|
|
|
|
|
layout_info.pSetLayouts = all_layouts;
|
|
|
|
|
|
|
|
layout_info.pushConstantRangeCount = 0; // TODO
|
|
|
|
|
|
|
|
layout_info.pPushConstantRanges = 0; // TODO
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineLayout layout = create_pipeline_layout(device, num_layouts, all_layouts, 0, 0);
|
|
|
|
VkResult result = vkCreatePipelineLayout(device, &layout_info, 0, &layout);
|
|
|
|
if(layout == VK_NULL_HANDLE) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
return zero_material;
|
|
|
|
return zero_material;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1953,12 +2085,16 @@ Material create_material(
|
|
|
|
|
|
|
|
|
|
|
|
.material_set_layout = material_set_layout,
|
|
|
|
.material_set_layout = material_set_layout,
|
|
|
|
.mesh_set_layout = mesh_set_layout,
|
|
|
|
.mesh_set_layout = mesh_set_layout,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.material_descriptors = material_descriptors,
|
|
|
|
|
|
|
|
.material_descriptor_pool = material_descriptor_pool,
|
|
|
|
|
|
|
|
.material_descriptors_count = max_frames_in_flight,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return material;
|
|
|
|
return material;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout) {
|
|
|
|
Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) {
|
|
|
|
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device);
|
|
|
|
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device);
|
|
|
|
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device);
|
|
|
|
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device);
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
|
|
|
@ -2006,10 +2142,10 @@ 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);
|
|
|
|
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, simple_layout, simple_mesh_type, max_frames_in_flight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout) {
|
|
|
|
Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) {
|
|
|
|
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/texture.vert.spv", device);
|
|
|
|
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/texture.vert.spv", device);
|
|
|
|
if(vert_shader == VK_NULL_HANDLE) {
|
|
|
|
if(vert_shader == VK_NULL_HANDLE) {
|
|
|
|
Material tmp = {};
|
|
|
|
Material tmp = {};
|
|
|
@ -2082,7 +2218,7 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
|
|
|
|
.mesh_bindings = mesh_set_bindings,
|
|
|
|
.mesh_bindings = mesh_set_bindings,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type);
|
|
|
|
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
@ -2297,18 +2433,18 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->in_flight_fences = if_fences;
|
|
|
|
context->in_flight_fences = if_fences;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorPoolSize ubo_pool_sizes[] = {
|
|
|
|
VkDescriptorPoolSize scene_pool_sizes[] = {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
.descriptorCount = max_frames_in_flight,
|
|
|
|
.descriptorCount = max_frames_in_flight,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
VkDescriptorPool scene_ubo_pool = create_descriptor_pool(device, ubo_pool_sizes, 1, max_frames_in_flight);
|
|
|
|
VkDescriptorPool scene_pool = create_descriptor_pool(device, scene_pool_sizes, 1, max_frames_in_flight);
|
|
|
|
if(scene_ubo_pool == VK_NULL_HANDLE) {
|
|
|
|
if(scene_pool == VK_NULL_HANDLE) {
|
|
|
|
fprintf(stderr, "failed to create vulkan scene descriptor pool\n");
|
|
|
|
fprintf(stderr, "failed to create vulkan scene descriptor pool\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
context->scene_ubo_pool = scene_ubo_pool;
|
|
|
|
context->scene_pool = scene_pool;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutBinding scene_ubo_layout_binding = {
|
|
|
|
VkDescriptorSetLayoutBinding scene_ubo_layout_binding = {
|
|
|
@ -2319,20 +2455,20 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
.pImmutableSamplers = 0,
|
|
|
|
.pImmutableSamplers = 0,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayout scene_ubo_layout = create_descriptor_set_layout(device, &scene_ubo_layout_binding, 1);
|
|
|
|
VkDescriptorSetLayout scene_descriptor_layout = create_descriptor_set_layout(device, &scene_ubo_layout_binding, 1);
|
|
|
|
if(scene_ubo_layout == VK_NULL_HANDLE) {
|
|
|
|
if(scene_descriptor_layout == VK_NULL_HANDLE) {
|
|
|
|
fprintf(stderr, "failed to create vulkan scene descriptor layout\n");
|
|
|
|
fprintf(stderr, "failed to create vulkan scene descriptor layout\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
context->scene_ubo_layout = scene_ubo_layout;
|
|
|
|
context->scene_descriptor_layout = scene_descriptor_layout;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSet* scene_ubo_descriptors = create_descriptor_sets(context->device, context->scene_ubo_layout, context->scene_ubo_pool, max_frames_in_flight);
|
|
|
|
VkDescriptorSet* scene_descriptors = create_descriptor_sets(context->device, context->scene_descriptor_layout, context->scene_pool, max_frames_in_flight);
|
|
|
|
if(scene_ubo_descriptors == 0) {
|
|
|
|
if(scene_descriptors == 0) {
|
|
|
|
fprintf(stderr, "failed to create vulkan scene descriptore\n");
|
|
|
|
fprintf(stderr, "failed to create vulkan scene descriptore\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
context->scene_ubo_descriptors = scene_ubo_descriptors;
|
|
|
|
context->scene_descriptors = scene_descriptors;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer* scene_ubos = allocate_buffers(context->physical_device, context->device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight);
|
|
|
|
AllocatedBuffer* scene_ubos = allocate_buffers(context->physical_device, context->device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight);
|
|
|
@ -2370,7 +2506,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
|
|
|
|
|
|
|
|
VkWriteDescriptorSet descriptor_write = {};
|
|
|
|
VkWriteDescriptorSet descriptor_write = {};
|
|
|
|
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
|
|
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
|
|
descriptor_write.dstSet = context->scene_ubo_descriptors[i];
|
|
|
|
descriptor_write.dstSet = context->scene_descriptors[i];
|
|
|
|
descriptor_write.dstBinding = 0;
|
|
|
|
descriptor_write.dstBinding = 0;
|
|
|
|
descriptor_write.dstArrayElement = 0;
|
|
|
|
descriptor_write.dstArrayElement = 0;
|
|
|
|
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
|
|
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
|
@ -2382,7 +2518,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0);
|
|
|
|
vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, context->scene_ubo_layout);
|
|
|
|
Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, context->scene_descriptor_layout, max_frames_in_flight);
|
|
|
|
if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
|
|
|
|
if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
|
|
|
|
fprintf(stderr, "failed to create simple mesh material\n");
|
|
|
|
fprintf(stderr, "failed to create simple mesh material\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -2390,14 +2526,6 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->simple_mesh_material = simple_mesh_material;
|
|
|
|
context->simple_mesh_material = simple_mesh_material;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, context->scene_ubo_layout);
|
|
|
|
|
|
|
|
if(texture_mesh_material.pipeline == VK_NULL_HANDLE) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create texture mesh material\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->texture_mesh_material = texture_mesh_material;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Mesh triangle_mesh = load_simple_mesh(context->physical_device, context->device, (struct Vertex*)vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer);
|
|
|
|
Mesh triangle_mesh = load_simple_mesh(context->physical_device, context->device, (struct Vertex*)vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer);
|
|
|
|
if(triangle_mesh.vertex_buffer.buffer == VK_NULL_HANDLE) {
|
|
|
|
if(triangle_mesh.vertex_buffer.buffer == VK_NULL_HANDLE) {
|
|
|
|
fprintf(stderr, "failed to load triangle mesh\n");
|
|
|
|
fprintf(stderr, "failed to load triangle mesh\n");
|
|
|
@ -2406,6 +2534,22 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->triangle_mesh = triangle_mesh;
|
|
|
|
context->triangle_mesh = triangle_mesh;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object triangle_object = create_renderable(&context->triangle_mesh, &context->simple_mesh_material);
|
|
|
|
|
|
|
|
if(triangle_object.attributes.buckets == 0) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create renderable triangle object\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->triangle_object = triangle_object;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, context->scene_descriptor_layout, max_frames_in_flight);
|
|
|
|
|
|
|
|
if(texture_mesh_material.pipeline == VK_NULL_HANDLE) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create texture mesh material\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->texture_mesh_material = texture_mesh_material;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Mesh triangle_mesh_textured = load_texture_mesh(context->physical_device, context->device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer);
|
|
|
|
Mesh triangle_mesh_textured = load_texture_mesh(context->physical_device, context->device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer);
|
|
|
|
if(triangle_mesh_textured.vertex_buffer.buffer == VK_NULL_HANDLE) {
|
|
|
|
if(triangle_mesh_textured.vertex_buffer.buffer == VK_NULL_HANDLE) {
|
|
|
|
fprintf(stderr, "failed to load textured triangle mesh\n");
|
|
|
|
fprintf(stderr, "failed to load textured triangle mesh\n");
|
|
|
@ -2414,6 +2558,14 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->triangle_mesh_textured = triangle_mesh_textured;
|
|
|
|
context->triangle_mesh_textured = triangle_mesh_textured;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object triangle_object_textured = create_renderable(&context->triangle_mesh_textured, &context->texture_mesh_material);
|
|
|
|
|
|
|
|
if(triangle_object_textured.attributes.buckets == 0) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create renderable textured triangle object\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->triangle_object_textured = triangle_object_textured;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return context;
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -2664,8 +2816,8 @@ VkResult draw_frame(VulkanContext* context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t mesh_counts[] = {1};
|
|
|
|
uint32_t mesh_counts[] = {1};
|
|
|
|
Mesh* meshes[] = {&context->triangle_mesh_textured};
|
|
|
|
Object* objects[] = {&context->triangle_object_textured};
|
|
|
|
result = record_command_buffer_scene(1, &context->texture_mesh_material, (uint32_t*)&mesh_counts, (Mesh**)meshes, context->scene_ubo_descriptors[context->current_frame], context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent);
|
|
|
|
result = command_draw_scene(1, &context->texture_mesh_material, (uint32_t*)&mesh_counts, (Object**)objects, context->current_frame, context->scene_descriptors, context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|