|
|
@ -18,6 +18,17 @@
|
|
|
|
#include <string.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <ply.h>
|
|
|
|
#include <ply.h>
|
|
|
|
|
|
|
|
#include <map.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct AllocatedBufferStruct {
|
|
|
|
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
|
|
|
VkBuffer buffer;
|
|
|
|
|
|
|
|
} AllocatedBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct AllocatedImageStruct {
|
|
|
|
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
|
|
|
VkImage image;
|
|
|
|
|
|
|
|
} AllocatedImage;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct QueueIndicesStruct {
|
|
|
|
typedef struct QueueIndicesStruct {
|
|
|
|
uint32_t graphics_family;
|
|
|
|
uint32_t graphics_family;
|
|
|
@ -51,217 +62,12 @@ typedef struct SwapchainImagesStruct {
|
|
|
|
uint32_t count;
|
|
|
|
uint32_t count;
|
|
|
|
} SwapchainImages;
|
|
|
|
} SwapchainImages;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct AllocatedBufferStruct {
|
|
|
|
|
|
|
|
VkBuffer buffer;
|
|
|
|
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
|
|
|
} AllocatedBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct AllocatedImageStruct {
|
|
|
|
|
|
|
|
VkImage image;
|
|
|
|
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
|
|
|
} AllocatedImage;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct TextureStruct {
|
|
|
|
typedef struct TextureStruct {
|
|
|
|
AllocatedImage image;
|
|
|
|
AllocatedImage image;
|
|
|
|
VkImageView view;
|
|
|
|
VkImageView view;
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct MapIteratorStruct {
|
|
|
|
|
|
|
|
uint32_t count;
|
|
|
|
|
|
|
|
uint32_t* keys;
|
|
|
|
|
|
|
|
void** vals;
|
|
|
|
|
|
|
|
} MapIterator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MapIterator map_iterator_create(Map map) {
|
|
|
|
|
|
|
|
MapIterator iterator = {
|
|
|
|
|
|
|
|
.keys = 0,
|
|
|
|
|
|
|
|
.vals = 0,
|
|
|
|
|
|
|
|
.count = 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < map.buckets_count; i++) {
|
|
|
|
|
|
|
|
count += map.bucket_usage[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t* keys = malloc(sizeof(uint32_t)*count);
|
|
|
|
|
|
|
|
if(keys == 0) {
|
|
|
|
|
|
|
|
return iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void** vals = malloc(sizeof(void*)*count);
|
|
|
|
|
|
|
|
if(vals == 0) {
|
|
|
|
|
|
|
|
free(keys);
|
|
|
|
|
|
|
|
return iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t idx = 0;
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < map.buckets_count; i++) {
|
|
|
|
|
|
|
|
for(uint32_t j = 0; j < map.bucket_usage[i]; j++) {
|
|
|
|
|
|
|
|
keys[idx] = map.buckets[i][j].key;
|
|
|
|
|
|
|
|
vals[idx] = map.buckets[i][j].value;
|
|
|
|
|
|
|
|
idx += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
iterator.keys = keys;
|
|
|
|
|
|
|
|
iterator.vals = vals;
|
|
|
|
|
|
|
|
iterator.count = count;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void map_iterator_free(MapIterator iterator) {
|
|
|
|
|
|
|
|
if(iterator.count > 0) {
|
|
|
|
|
|
|
|
free(iterator.keys);
|
|
|
|
|
|
|
|
free(iterator.vals);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct PositionStruct {
|
|
|
|
typedef struct PositionStruct {
|
|
|
|
vec3 position;
|
|
|
|
vec3 position;
|
|
|
|
vec3 scale;
|
|
|
|
vec3 scale;
|
|
|
@ -338,6 +144,12 @@ typedef struct MaterialStruct {
|
|
|
|
Map object_descriptor_mappings;
|
|
|
|
Map object_descriptor_mappings;
|
|
|
|
} Material;
|
|
|
|
} Material;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct MemoryIndicesStruct {
|
|
|
|
|
|
|
|
uint32_t host_visible;
|
|
|
|
|
|
|
|
uint32_t device_local;
|
|
|
|
|
|
|
|
uint32_t device_lazy;
|
|
|
|
|
|
|
|
} MemoryIndices;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
VkInstance instance;
|
|
|
|
VkInstance instance;
|
|
|
|
VkDebugUtilsMessengerEXT debug_messenger;
|
|
|
|
VkDebugUtilsMessengerEXT debug_messenger;
|
|
|
@ -362,7 +174,8 @@ typedef struct VulkanContextStruct {
|
|
|
|
VkImageView* swapchain_image_views;
|
|
|
|
VkImageView* swapchain_image_views;
|
|
|
|
VkFramebuffer* swapchain_framebuffers;
|
|
|
|
VkFramebuffer* swapchain_framebuffers;
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedImage depth_image;
|
|
|
|
VkDeviceMemory depth_image_memory;
|
|
|
|
|
|
|
|
VkImage depth_image;
|
|
|
|
VkFormat depth_format;
|
|
|
|
VkFormat depth_format;
|
|
|
|
VkImageView depth_image_view;
|
|
|
|
VkImageView depth_image_view;
|
|
|
|
|
|
|
|
|
|
|
@ -374,13 +187,14 @@ typedef struct VulkanContextStruct {
|
|
|
|
VkSemaphore* render_finished_semaphores;
|
|
|
|
VkSemaphore* render_finished_semaphores;
|
|
|
|
VkFence* in_flight_fences;
|
|
|
|
VkFence* in_flight_fences;
|
|
|
|
|
|
|
|
|
|
|
|
VkPhysicalDeviceMemoryProperties memories;
|
|
|
|
|
|
|
|
VkRenderPass render_pass;
|
|
|
|
VkRenderPass render_pass;
|
|
|
|
|
|
|
|
|
|
|
|
VkCommandPool graphics_command_pool;
|
|
|
|
VkCommandPool graphics_command_pool;
|
|
|
|
VkCommandPool transfer_command_pool;
|
|
|
|
VkCommandPool transfer_command_pool;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t current_frame;
|
|
|
|
uint32_t current_frame;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MemoryIndices memory_indices;
|
|
|
|
} VulkanContext;
|
|
|
|
} VulkanContext;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct SceneContextStruct {
|
|
|
|
typedef struct SceneContextStruct {
|
|
|
@ -440,13 +254,14 @@ uint32_t validation_layer_count = sizeof(validation_layers) / sizeof(const char
|
|
|
|
const char * instance_extensions[] = {
|
|
|
|
const char * instance_extensions[] = {
|
|
|
|
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
|
|
|
|
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
|
|
|
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
|
|
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
|
|
|
VK_MVK_MACOS_SURFACE_EXTENSION_NAME,
|
|
|
|
"VK_EXT_metal_surface",
|
|
|
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
|
|
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
uint32_t instance_extension_count = sizeof(instance_extensions) / sizeof(const char *);
|
|
|
|
uint32_t instance_extension_count = sizeof(instance_extensions) / sizeof(const char *);
|
|
|
|
|
|
|
|
|
|
|
|
const char * device_extensions[] = {
|
|
|
|
const char * device_extensions[] = {
|
|
|
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
|
|
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
|
|
|
|
|
|
|
"VK_KHR_portability_subset",
|
|
|
|
};
|
|
|
|
};
|
|
|
|
uint32_t device_extension_count = sizeof(device_extensions) / sizeof(const char *);
|
|
|
|
uint32_t device_extension_count = sizeof(device_extensions) / sizeof(const char *);
|
|
|
|
|
|
|
|
|
|
|
@ -739,7 +554,7 @@ VkInstance create_instance() {
|
|
|
|
app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
|
|
|
|
app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
|
|
|
|
app_info.pEngineName = "spacegame";
|
|
|
|
app_info.pEngineName = "spacegame";
|
|
|
|
app_info.engineVersion = VK_MAKE_VERSION(0, 0, 1);
|
|
|
|
app_info.engineVersion = VK_MAKE_VERSION(0, 0, 1);
|
|
|
|
app_info.apiVersion = VK_API_VERSION_1_3;
|
|
|
|
app_info.apiVersion = VK_API_VERSION_1_2;
|
|
|
|
|
|
|
|
|
|
|
|
VkInstanceCreateInfo instance_info = {};
|
|
|
|
VkInstanceCreateInfo instance_info = {};
|
|
|
|
instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
|
|
instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
|
@ -1164,7 +979,7 @@ uint32_t pick_memory_type(VkPhysicalDeviceMemoryProperties memories, uint32_t fi
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage, VkMemoryPropertyFlags properties) {
|
|
|
|
AllocatedImage allocate_image(uint32_t memory_index, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage) {
|
|
|
|
VkImageCreateInfo image_info = {
|
|
|
|
VkImageCreateInfo image_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
.imageType = type,
|
|
|
|
.imageType = type,
|
|
|
@ -1195,7 +1010,7 @@ AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevic
|
|
|
|
VkMemoryAllocateInfo memory_info = {
|
|
|
|
VkMemoryAllocateInfo memory_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
.allocationSize = memory_requirements.size,
|
|
|
|
.allocationSize = memory_requirements.size,
|
|
|
|
.memoryTypeIndex = pick_memory_type(memories, memory_requirements.memoryTypeBits, properties),
|
|
|
|
.memoryTypeIndex = memory_index,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
result = vkAllocateMemory(device, &memory_info, 0, &allocated.memory);
|
|
|
|
result = vkAllocateMemory(device, &memory_info, 0, &allocated.memory);
|
|
|
@ -1218,7 +1033,7 @@ AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevic
|
|
|
|
return allocated;
|
|
|
|
return allocated;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer allocate_buffer(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) {
|
|
|
|
AllocatedBuffer allocate_buffer(uint32_t memory_index, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage) {
|
|
|
|
AllocatedBuffer ret = {};
|
|
|
|
AllocatedBuffer ret = {};
|
|
|
|
ret.memory = VK_NULL_HANDLE;
|
|
|
|
ret.memory = VK_NULL_HANDLE;
|
|
|
|
ret.buffer = VK_NULL_HANDLE;
|
|
|
|
ret.buffer = VK_NULL_HANDLE;
|
|
|
@ -1243,7 +1058,7 @@ AllocatedBuffer allocate_buffer(VkPhysicalDeviceMemoryProperties memories, VkDev
|
|
|
|
VkMemoryAllocateInfo alloc_info = {};
|
|
|
|
VkMemoryAllocateInfo alloc_info = {};
|
|
|
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
|
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
|
|
alloc_info.allocationSize = memory_requirements.size;
|
|
|
|
alloc_info.allocationSize = memory_requirements.size;
|
|
|
|
alloc_info.memoryTypeIndex = pick_memory_type(memories, memory_requirements.memoryTypeBits, properties);
|
|
|
|
alloc_info.memoryTypeIndex = memory_index;
|
|
|
|
|
|
|
|
|
|
|
|
result = vkAllocateMemory(device, &alloc_info, 0, &ret.memory);
|
|
|
|
result = vkAllocateMemory(device, &alloc_info, 0, &ret.memory);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
@ -1274,14 +1089,14 @@ void deallocate_image(VkDevice device, AllocatedImage image) {
|
|
|
|
vkFreeMemory(device, image.memory, 0);
|
|
|
|
vkFreeMemory(device, image.memory, 0);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer* allocate_buffers(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, uint32_t count) {
|
|
|
|
AllocatedBuffer* allocate_buffers(uint32_t memory_index, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, uint32_t count) {
|
|
|
|
AllocatedBuffer* buffers = malloc(sizeof(AllocatedBuffer)*count);
|
|
|
|
AllocatedBuffer* buffers = malloc(sizeof(AllocatedBuffer)*count);
|
|
|
|
if(buffers == 0) {
|
|
|
|
if(buffers == 0) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < count; i++) {
|
|
|
|
for(uint32_t i = 0; i < count; i++) {
|
|
|
|
buffers[i] = allocate_buffer(memories, device, size, usage, properties);
|
|
|
|
buffers[i] = allocate_buffer(memory_index, device, size, usage);
|
|
|
|
if(buffers[i].memory == VK_NULL_HANDLE) {
|
|
|
|
if(buffers[i].memory == VK_NULL_HANDLE) {
|
|
|
|
for(uint32_t j = 0; j < i; j++) {
|
|
|
|
for(uint32_t j = 0; j < i; j++) {
|
|
|
|
deallocate_buffer(device, buffers[i]);
|
|
|
|
deallocate_buffer(device, buffers[i]);
|
|
|
@ -1407,10 +1222,10 @@ VkResult command_copy_buffer_to_image(VkDevice device, VkCommandPool transfer_po
|
|
|
|
return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
|
|
|
|
return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer create_populated_buffer(VkPhysicalDeviceMemoryProperties memories, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) {
|
|
|
|
AllocatedBuffer create_populated_buffer(MemoryIndices memories, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) {
|
|
|
|
AllocatedBuffer staging_buffer = {};
|
|
|
|
AllocatedBuffer staging_buffer = {};
|
|
|
|
AllocatedBuffer vertex_buffer = {};
|
|
|
|
AllocatedBuffer vertex_buffer = {};
|
|
|
|
staging_buffer = allocate_buffer(memories, device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
|
|
staging_buffer = allocate_buffer(memories.host_visible, device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
|
|
|
if(staging_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
if(staging_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
return vertex_buffer;
|
|
|
|
return vertex_buffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1427,7 +1242,7 @@ AllocatedBuffer create_populated_buffer(VkPhysicalDeviceMemoryProperties memorie
|
|
|
|
|
|
|
|
|
|
|
|
vkUnmapMemory(device, staging_buffer.memory);
|
|
|
|
vkUnmapMemory(device, staging_buffer.memory);
|
|
|
|
|
|
|
|
|
|
|
|
vertex_buffer = allocate_buffer(memories, device, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
|
|
vertex_buffer = allocate_buffer(memories.device_local, device, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage);
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
deallocate_buffer(device, staging_buffer);
|
|
|
|
deallocate_buffer(device, staging_buffer);
|
|
|
|
return vertex_buffer;
|
|
|
|
return vertex_buffer;
|
|
|
@ -1445,7 +1260,7 @@ AllocatedBuffer create_populated_buffer(VkPhysicalDeviceMemoryProperties memorie
|
|
|
|
return vertex_buffer;
|
|
|
|
return vertex_buffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkExtent2D size, uint32_t stride, VkFormat format, void* image_data){
|
|
|
|
Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkExtent2D size, uint32_t stride, VkFormat format, void* image_data){
|
|
|
|
Texture ret = {
|
|
|
|
Texture ret = {
|
|
|
|
.image.image = VK_NULL_HANDLE,
|
|
|
|
.image.image = VK_NULL_HANDLE,
|
|
|
|
.image.memory = VK_NULL_HANDLE,
|
|
|
|
.image.memory = VK_NULL_HANDLE,
|
|
|
@ -1453,7 +1268,7 @@ Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t image_size = size.width * size.height * stride;
|
|
|
|
uint32_t image_size = size.width * size.height * stride;
|
|
|
|
AllocatedBuffer staging = allocate_buffer(memories, device, image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
|
|
AllocatedBuffer staging = allocate_buffer(memories.host_visible, device, image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
|
|
|
if(staging.memory == VK_NULL_HANDLE) {
|
|
|
|
if(staging.memory == VK_NULL_HANDLE) {
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1474,7 +1289,7 @@ Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device,
|
|
|
|
.height = size.height,
|
|
|
|
.height = size.height,
|
|
|
|
.depth = 1,
|
|
|
|
.depth = 1,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
AllocatedImage image = allocate_image(memories, device, VK_IMAGE_TYPE_2D, format, full_extent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
|
|
AllocatedImage image = allocate_image(memories.device_local, device, VK_IMAGE_TYPE_2D, format, full_extent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
|
|
|
if(image.memory == VK_NULL_HANDLE) {
|
|
|
|
if(image.memory == VK_NULL_HANDLE) {
|
|
|
|
deallocate_buffer(device, staging);
|
|
|
|
deallocate_buffer(device, staging);
|
|
|
|
deallocate_image(device, image);
|
|
|
|
deallocate_image(device, image);
|
|
|
@ -1707,49 +1522,64 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) {
|
|
|
|
return command_pool;
|
|
|
|
return command_pool;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult recreate_swap_chain(VulkanContext* context) {
|
|
|
|
int create_depth_image(VulkanContext* context) {
|
|
|
|
for(uint32_t i = 0; i < context->swapchain_image_count; i++) {
|
|
|
|
VkExtent3D depth_extent = {
|
|
|
|
vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0);
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
|
vkDestroyImageView(context->device, context->swapchain_image_views[i], 0);
|
|
|
|
.height = context->swapchain_extent.height,
|
|
|
|
}
|
|
|
|
.depth = 1,
|
|
|
|
|
|
|
|
};
|
|
|
|
vkDestroySwapchainKHR(context->device, context->swapchain, 0);
|
|
|
|
|
|
|
|
free(context->swapchain_images);
|
|
|
|
|
|
|
|
free(context->swapchain_image_views);
|
|
|
|
|
|
|
|
free(context->swapchain_framebuffers);
|
|
|
|
|
|
|
|
free(context->swapchain_details.formats);
|
|
|
|
|
|
|
|
free(context->swapchain_details.present_modes);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkDestroyImageView(context->device, context->depth_image_view, 0);
|
|
|
|
VkImageCreateInfo depth_image_info = {
|
|
|
|
deallocate_image(context->device, context->depth_image);
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
|
|
|
|
.imageType = VK_IMAGE_TYPE_2D,
|
|
|
|
|
|
|
|
.extent = depth_extent,
|
|
|
|
|
|
|
|
.mipLevels = 1,
|
|
|
|
|
|
|
|
.arrayLayers = 1,
|
|
|
|
|
|
|
|
.format = context->depth_format,
|
|
|
|
|
|
|
|
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
|
|
|
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
|
|
|
.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
|
|
|
|
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
|
|
|
|
|
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
|
|
|
|
.flags = 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
SwapchainDetails swapchain_details = get_swapchain_details(context->physical_device, context->surface);
|
|
|
|
VkImage depth_image;
|
|
|
|
if(swapchain_details.formats == 0) {
|
|
|
|
VkResult result = vkCreateImage(context->device, &depth_image_info, 0, &depth_image);
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create depth image\n");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
context->swapchain_details = swapchain_details;
|
|
|
|
context->depth_image = depth_image;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
context->swapchain_format = choose_swapchain_format(context->swapchain_details);
|
|
|
|
VkMemoryRequirements depth_image_requirements;
|
|
|
|
context->swapchain_present_mode = choose_present_mode(context->swapchain_details);
|
|
|
|
vkGetImageMemoryRequirements(context->device, context->depth_image, &depth_image_requirements);
|
|
|
|
context->swapchain_extent = choose_swapchain_extent(context->swapchain_details);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkExtent3D depth_extent = {
|
|
|
|
VkMemoryAllocateInfo depth_memory_info = {
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
.height = context->swapchain_extent.height,
|
|
|
|
.allocationSize = depth_image_requirements.size,
|
|
|
|
.depth = 1,
|
|
|
|
.memoryTypeIndex = context->memory_indices.device_lazy,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedImage depth_image = allocate_image(context->memories, context->device, VK_IMAGE_TYPE_2D, context->depth_format, depth_extent, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
|
|
VkDeviceMemory depth_image_memory;
|
|
|
|
if(depth_image.memory == VK_NULL_HANDLE) {
|
|
|
|
result = vkAllocateMemory(context->device, &depth_memory_info, 0, &depth_image_memory);
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to allocate memory for depth image\n");
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
context->depth_image = depth_image;
|
|
|
|
context->depth_image_memory = depth_image_memory;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkBindImageMemory(context->device, context->depth_image, context->depth_image_memory, 0);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to bind memory for depth image\n");
|
|
|
|
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkImageViewCreateInfo depth_view_info = {
|
|
|
|
VkImageViewCreateInfo depth_view_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
.image = depth_image.image,
|
|
|
|
.image = context->depth_image,
|
|
|
|
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
|
|
|
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
|
|
|
.format = context->depth_format,
|
|
|
|
.format = context->depth_format,
|
|
|
|
.components = {
|
|
|
|
.components = {
|
|
|
@ -1768,13 +1598,47 @@ VkResult recreate_swap_chain(VulkanContext* context) {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
VkImageView depth_image_view;
|
|
|
|
VkImageView depth_image_view;
|
|
|
|
VkResult result = vkCreateImageView(context->device, &depth_view_info, 0, &depth_image_view);
|
|
|
|
result = vkCreateImageView(context->device, &depth_view_info, 0, &depth_image_view);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
fprintf(stderr, "failed to create vulkan depth image view\n");
|
|
|
|
|
|
|
|
return 4;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
context->depth_image_view = depth_image_view;
|
|
|
|
context->depth_image_view = depth_image_view;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkResult recreate_swap_chain(VulkanContext* context) {
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < context->swapchain_image_count; i++) {
|
|
|
|
|
|
|
|
vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0);
|
|
|
|
|
|
|
|
vkDestroyImageView(context->device, context->swapchain_image_views[i], 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkDestroySwapchainKHR(context->device, context->swapchain, 0);
|
|
|
|
|
|
|
|
free(context->swapchain_images);
|
|
|
|
|
|
|
|
free(context->swapchain_image_views);
|
|
|
|
|
|
|
|
free(context->swapchain_framebuffers);
|
|
|
|
|
|
|
|
free(context->swapchain_details.formats);
|
|
|
|
|
|
|
|
free(context->swapchain_details.present_modes);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkDestroyImageView(context->device, context->depth_image_view, 0);
|
|
|
|
|
|
|
|
vkDestroyImage(context->device, context->depth_image, 0);
|
|
|
|
|
|
|
|
vkFreeMemory(context->device, context->depth_image_memory, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SwapchainDetails swapchain_details = get_swapchain_details(context->physical_device, context->surface);
|
|
|
|
|
|
|
|
if(swapchain_details.formats == 0) {
|
|
|
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->swapchain_details = swapchain_details;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context->swapchain_format = choose_swapchain_format(context->swapchain_details);
|
|
|
|
|
|
|
|
context->swapchain_present_mode = choose_present_mode(context->swapchain_details);
|
|
|
|
|
|
|
|
context->swapchain_extent = choose_swapchain_extent(context->swapchain_details);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create_depth_image(context);
|
|
|
|
|
|
|
|
|
|
|
|
VkSwapchainKHR swapchain = create_swapchain(context->device, context->swapchain_format, context->swapchain_present_mode, context->swapchain_extent, context->surface, context->swapchain_details.capabilities, context->queue_indices, context->swapchain);
|
|
|
|
VkSwapchainKHR swapchain = create_swapchain(context->device, context->swapchain_format, context->swapchain_present_mode, context->swapchain_extent, context->surface, context->swapchain_details.capabilities, context->queue_indices, context->swapchain);
|
|
|
|
if(swapchain == VK_NULL_HANDLE) {
|
|
|
|
if(swapchain == VK_NULL_HANDLE) {
|
|
|
|
context->swapchain = VK_NULL_HANDLE;
|
|
|
|
context->swapchain = VK_NULL_HANDLE;
|
|
|
@ -1967,7 +1831,7 @@ VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count
|
|
|
|
return fences;
|
|
|
|
return fences;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Mesh* load_texture_mesh(VkPhysicalDeviceMemoryProperties memories, VkDevice device, struct TextureVertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) {
|
|
|
|
Mesh* load_texture_mesh(MemoryIndices memories, VkDevice device, struct TextureVertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) {
|
|
|
|
AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct TextureVertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
|
|
|
AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct TextureVertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -2074,7 +1938,7 @@ Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_set
|
|
|
|
return object;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Mesh* load_simple_mesh(VkPhysicalDeviceMemoryProperties memories, 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(MemoryIndices memories, VkDevice device, struct Vertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) {
|
|
|
|
AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct Vertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
|
|
|
AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct Vertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -2461,7 +2325,35 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->physical_device = physical_device;
|
|
|
|
context->physical_device = physical_device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(context->physical_device, &context->memories);
|
|
|
|
VkPhysicalDeviceMemoryProperties memories;
|
|
|
|
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(context->physical_device, &memories);
|
|
|
|
|
|
|
|
MemoryIndices memory_indices = {
|
|
|
|
|
|
|
|
.device_local = 0xFFFFFFFF,
|
|
|
|
|
|
|
|
.host_visible = 0xFFFFFFFF,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < memories.memoryTypeCount; i++) {
|
|
|
|
|
|
|
|
VkMemoryPropertyFlags flags = memories.memoryTypes[i].propertyFlags;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
|
|
|
|
|
|
|
&& !(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
|
|
|
|
|
|
|
&& (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)) {
|
|
|
|
|
|
|
|
memory_indices.device_lazy = i;
|
|
|
|
|
|
|
|
} else if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
|
|
|
|
|
|
|
&& !(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
|
|
|
|
|
|
|
|
memory_indices.device_local = i;
|
|
|
|
|
|
|
|
} else if((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
|
|
|
|
|
|
|
&& !(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
|
|
|
|
|
|
|
|
memory_indices.host_visible = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(memory_indices.host_visible == 0xFFFFFFFF || memory_indices.device_local == 0xFFFFFFFF || memory_indices.device_lazy == 0xFFFFFFFF) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to select suitable memory types\n");
|
|
|
|
|
|
|
|
fprintf(stderr, "%d, %d, %d\n", memory_indices.device_local, memory_indices.device_lazy, memory_indices.host_visible);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->memory_indices = memory_indices;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkSurfaceKHR surface;
|
|
|
|
VkSurfaceKHR surface;
|
|
|
|
VkResult result = glfwCreateWindowSurface(instance, window, 0, &surface);
|
|
|
|
VkResult result = glfwCreateWindowSurface(instance, window, 0, &surface);
|
|
|
@ -2541,6 +2433,11 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->depth_format = depth_format;
|
|
|
|
context->depth_format = depth_format;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(create_depth_image(context) != 0) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create depth image\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkRenderPass render_pass = create_render_pass(context->device, context->swapchain_format, context->depth_format);
|
|
|
|
VkRenderPass render_pass = create_render_pass(context->device, context->swapchain_format, context->depth_format);
|
|
|
|
if(render_pass == VK_NULL_HANDLE) {
|
|
|
|
if(render_pass == VK_NULL_HANDLE) {
|
|
|
|
fprintf(stderr, "failed to create vulkan render pass\n");
|
|
|
|
fprintf(stderr, "failed to create vulkan render pass\n");
|
|
|
@ -2549,48 +2446,6 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->render_pass = render_pass;
|
|
|
|
context->render_pass = render_pass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkExtent3D depth_extent = {
|
|
|
|
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
|
|
|
|
|
.height = context->swapchain_extent.height,
|
|
|
|
|
|
|
|
.depth = 1,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
AllocatedImage depth_image = allocate_image(context->memories, context->device, VK_IMAGE_TYPE_2D, depth_format, depth_extent, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
|
|
|
|
|
|
if(depth_image.memory == VK_NULL_HANDLE) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create vulkan depth image\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->depth_image = depth_image;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkImageViewCreateInfo depth_view_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
|
|
|
|
.image = depth_image.image,
|
|
|
|
|
|
|
|
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
|
|
|
|
|
|
|
.format = depth_format,
|
|
|
|
|
|
|
|
.components = {
|
|
|
|
|
|
|
|
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
.subresourceRange = {
|
|
|
|
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
|
|
|
|
|
|
|
|
.baseMipLevel = 0,
|
|
|
|
|
|
|
|
.levelCount = 1,
|
|
|
|
|
|
|
|
.baseArrayLayer = 0,
|
|
|
|
|
|
|
|
.layerCount = 1,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkImageView depth_image_view;
|
|
|
|
|
|
|
|
result = vkCreateImageView(context->device, &depth_view_info, 0, &depth_image_view);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create vulkan depth image view\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context->depth_image_view = depth_image_view;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent);
|
|
|
|
VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent);
|
|
|
|
if(framebuffers == 0) {
|
|
|
|
if(framebuffers == 0) {
|
|
|
|
fprintf(stderr, "failed to create vulkan framebuffers\n");
|
|
|
|
fprintf(stderr, "failed to create vulkan framebuffers\n");
|
|
|
@ -2652,7 +2507,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
return context;
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryProperties memories, uint32_t max_frames_in_flight) {
|
|
|
|
SceneContext create_scene_context(VkDevice device, MemoryIndices memories, uint32_t max_frames_in_flight) {
|
|
|
|
SceneContext ret = {
|
|
|
|
SceneContext ret = {
|
|
|
|
.pool = VK_NULL_HANDLE,
|
|
|
|
.pool = VK_NULL_HANDLE,
|
|
|
|
.descriptor_layout = VK_NULL_HANDLE,
|
|
|
|
.descriptor_layout = VK_NULL_HANDLE,
|
|
|
@ -2736,7 +2591,7 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer* ubos = allocate_buffers(memories, 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* ubos = allocate_buffers(memories.host_visible, device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight);
|
|
|
|
if(ubos == 0) {
|
|
|
|
if(ubos == 0) {
|
|
|
|
free(layouts);
|
|
|
|
free(layouts);
|
|
|
|
free(sets);
|
|
|
|
free(sets);
|
|
|
@ -3085,7 +2940,7 @@ VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t materi
|
|
|
|
return vkQueuePresentKHR(context->queues.present, &present_info);
|
|
|
|
return vkQueuePresentKHR(context->queues.present, &present_info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) {
|
|
|
|
Object create_simple_mesh_object(Material* simple_mesh_material, MemoryIndices memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) {
|
|
|
|
Object zero = {};
|
|
|
|
Object zero = {};
|
|
|
|
|
|
|
|
|
|
|
|
Mesh* mesh = load_simple_mesh(memories, device, (struct Vertex*)vertices, 4, (uint16*)indices, 6, transfer_pool, transfer_queue);
|
|
|
|
Mesh* mesh = load_simple_mesh(memories, device, (struct Vertex*)vertices, 4, (uint16*)indices, 6, transfer_pool, transfer_queue);
|
|
|
@ -3140,7 +2995,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic
|
|
|
|
return zero;
|
|
|
|
return zero;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer* position_buffers = allocate_buffers(memories, 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);
|
|
|
|
AllocatedBuffer* position_buffers = allocate_buffers(memories.host_visible, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight);
|
|
|
|
if(position_buffers == 0) {
|
|
|
|
if(position_buffers == 0) {
|
|
|
|
return zero;
|
|
|
|
return zero;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -3179,7 +3034,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic
|
|
|
|
return object;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) {
|
|
|
|
Object create_texture_mesh_object(Material* texture_mesh_material, MemoryIndices memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) {
|
|
|
|
Object zero = {};
|
|
|
|
Object zero = {};
|
|
|
|
|
|
|
|
|
|
|
|
Mesh* mesh = load_texture_mesh(memories, device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, transfer_pool, transfer_queue);
|
|
|
|
Mesh* mesh = load_texture_mesh(memories, device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, transfer_pool, transfer_queue);
|
|
|
@ -3234,7 +3089,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev
|
|
|
|
return zero;
|
|
|
|
return zero;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer* ubos = allocate_buffers(memories, 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);
|
|
|
|
AllocatedBuffer* ubos = allocate_buffers(memories.host_visible, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight);
|
|
|
|
if(ubos == 0) {
|
|
|
|
if(ubos == 0) {
|
|
|
|
return zero;
|
|
|
|
return zero;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -3328,7 +3183,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void main_loop(GLFWwindow* window, VulkanContext* context) {
|
|
|
|
void main_loop(GLFWwindow* window, VulkanContext* context) {
|
|
|
|
SceneContext scene = create_scene_context(context->device, context->memories, context->max_frames_in_flight);
|
|
|
|
SceneContext scene = create_scene_context(context->device, context->memory_indices, context->max_frames_in_flight);
|
|
|
|
if(scene.pool == VK_NULL_HANDLE) {
|
|
|
|
if(scene.pool == VK_NULL_HANDLE) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -3360,7 +3215,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Object triangle_object = create_simple_mesh_object(&simple_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, simple_pool);
|
|
|
|
Object triangle_object = create_simple_mesh_object(&simple_mesh_material, context->memory_indices, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, simple_pool);
|
|
|
|
if(triangle_object.attributes.buckets == 0) {
|
|
|
|
if(triangle_object.attributes.buckets == 0) {
|
|
|
|
fprintf(stderr, "failed to create simple mesh object\n");
|
|
|
|
fprintf(stderr, "failed to create simple mesh object\n");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -3397,7 +3252,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Object triangle_object_textured = create_texture_mesh_object(&texture_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, texture_pool);
|
|
|
|
Object triangle_object_textured = create_texture_mesh_object(&texture_mesh_material, context->memory_indices, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, texture_pool);
|
|
|
|
if(triangle_object_textured.attributes.buckets == 0) {
|
|
|
|
if(triangle_object_textured.attributes.buckets == 0) {
|
|
|
|
fprintf(stderr, "failed to create texture mesh object\n");
|
|
|
|
fprintf(stderr, "failed to create texture mesh object\n");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -3460,10 +3315,9 @@ void cleanup(GLFWwindow* window, VulkanContext* context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
int main() {
|
|
|
|
PlyElement* monkey = ply_load_mesh("monkey.ply");
|
|
|
|
PlyMesh monkey = ply_load_mesh("monkey.ply");
|
|
|
|
if(monkey == 0) {
|
|
|
|
if(monkey.position == 0) {
|
|
|
|
fprintf(stderr, "failed to load %s\n", "monkey.ply");
|
|
|
|
fprintf(stderr, "failed to load %s\n", "monkey.ply");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GLFWwindow* window = init_window(800, 600);
|
|
|
|
GLFWwindow* window = init_window(800, 600);
|
|
|
|