Clean up: introduced Vulkan_Instance, Vulkan_Resources structures.

Vulkan_Instance contains variables related to persistent vulkan resources like instance, device, queue, swapchain, etc.
Vulkan_Instance is re-iniitalized only during window creation.

Vulkan_Resources contains data specific to current game context, i.e. current level.
Vulkan_Resources can be re-loaded during level change, level exit, etc.
This commit is contained in:
Artem Kharytoniuk 2017-04-11 14:05:38 +03:00
parent 44a5f950ad
commit eca35b6050
8 changed files with 143 additions and 160 deletions

View File

@ -566,7 +566,7 @@ static bool GLW_SetMode(int mode, qboolean fullscreen) {
if (r_renderAPICompareWindow->integer) { if (r_renderAPICompareWindow->integer) {
HWND hwnd2 = create_api_compare_window(glConfig.vidWidth, glConfig.vidHeight); HWND hwnd2 = create_api_compare_window(glConfig.vidWidth, glConfig.vidHeight);
if (!initialize_vulkan(hwnd2)) { if (!vk_initialize(hwnd2)) {
ShowWindow(hwnd2, SW_HIDE); ShowWindow(hwnd2, SW_HIDE);
DestroyWindow(hwnd2); DestroyWindow(hwnd2);
ri.Printf(PRINT_WARNING, "GLW_SetMode: could not create API compare window"); ri.Printf(PRINT_WARNING, "GLW_SetMode: could not create API compare window");
@ -576,7 +576,7 @@ static bool GLW_SetMode(int mode, qboolean fullscreen) {
} }
} }
} else { // vulkan } else { // vulkan
if (!initialize_vulkan(hwnd)) { if (!vk_initialize(hwnd)) {
ShowWindow(hwnd, SW_HIDE); ShowWindow(hwnd, SW_HIDE);
DestroyWindow(hwnd); DestroyWindow(hwnd);
return false; return false;

View File

@ -691,8 +691,8 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
// VULKAN // VULKAN
vkDestroyImage(get_device(), tr.scratchImage[client]->vk_image, nullptr); vkDestroyImage(vk_instance.device, tr.scratchImage[client]->vk_image, nullptr);
vkDestroyImageView(get_device(), tr.scratchImage[client]->vk_image_view, nullptr); vkDestroyImageView(vk_instance.device, tr.scratchImage[client]->vk_image_view, nullptr);
tr.scratchImage[client]->vk_image = vk_create_cinematic_image(cols, rows, tr.scratchImage[client]->vk_staging_buffer); tr.scratchImage[client]->vk_image = vk_create_cinematic_image(cols, rows, tr.scratchImage[client]->vk_staging_buffer);
tr.scratchImage[client]->vk_image_view = create_image_view(tr.scratchImage[client]->vk_image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); tr.scratchImage[client]->vk_image_view = create_image_view(tr.scratchImage[client]->vk_image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
vk_update_cinematic_image(tr.scratchImage[client]->vk_image, tr.scratchImage[client]->vk_staging_buffer, cols, rows, data); vk_update_cinematic_image(tr.scratchImage[client]->vk_image, tr.scratchImage[client]->vk_staging_buffer, cols, rows, data);
@ -714,7 +714,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
descriptor_writes[0].pBufferInfo = nullptr; descriptor_writes[0].pBufferInfo = nullptr;
descriptor_writes[0].pTexelBufferView = nullptr; descriptor_writes[0].pTexelBufferView = nullptr;
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr); vkUpdateDescriptorSets(vk_instance.device, (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
} else { } else {
if (dirty) { if (dirty) {
// otherwise, just subimage upload it so that drivers can tell we are going to be changing // otherwise, just subimage upload it so that drivers can tell we are going to be changing
@ -898,12 +898,12 @@ const void *RB_DrawBuffer( const void *data ) {
} }
// VULKAN // VULKAN
VkResult result = vkAcquireNextImageKHR(get_device(), get_swapchain(), UINT64_MAX, vulkan_demo->image_acquired, VK_NULL_HANDLE, &vulkan_demo->swapchain_image_index); VkResult result = vkAcquireNextImageKHR(vk_instance.device, vk_instance.swapchain, UINT64_MAX, vulkan_demo->image_acquired, VK_NULL_HANDLE, &vulkan_demo->swapchain_image_index);
check_vk_result(result, "vkAcquireNextImageKHR"); check_vk_result(result, "vkAcquireNextImageKHR");
result = vkWaitForFences(get_device(), 1, &vulkan_demo->rendering_finished_fence, VK_FALSE, 1e9); result = vkWaitForFences(vk_instance.device, 1, &vulkan_demo->rendering_finished_fence, VK_FALSE, 1e9);
check_vk_result(result, "vkWaitForFences"); check_vk_result(result, "vkWaitForFences");
result = vkResetFences(get_device(), 1, &vulkan_demo->rendering_finished_fence); result = vkResetFences(vk_instance.device, 1, &vulkan_demo->rendering_finished_fence);
check_vk_result(result, "vkResetFences"); check_vk_result(result, "vkResetFences");
VkCommandBufferBeginInfo begin_info; VkCommandBufferBeginInfo begin_info;
@ -1051,20 +1051,19 @@ const void *RB_SwapBuffers( const void *data ) {
submit_info.signalSemaphoreCount = 1; submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &vulkan_demo->rendering_finished; submit_info.pSignalSemaphores = &vulkan_demo->rendering_finished;
result = vkQueueSubmit(get_queue(), 1, &submit_info, vulkan_demo->rendering_finished_fence); result = vkQueueSubmit(vk_instance.queue, 1, &submit_info, vulkan_demo->rendering_finished_fence);
check_vk_result(result, "vkQueueSubmit"); check_vk_result(result, "vkQueueSubmit");
VkSwapchainKHR swapchain = get_swapchain();
VkPresentInfoKHR present_info; VkPresentInfoKHR present_info;
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present_info.pNext = nullptr; present_info.pNext = nullptr;
present_info.waitSemaphoreCount = 1; present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = &vulkan_demo->rendering_finished; present_info.pWaitSemaphores = &vulkan_demo->rendering_finished;
present_info.swapchainCount = 1; present_info.swapchainCount = 1;
present_info.pSwapchains = &swapchain; present_info.pSwapchains = &vk_instance.swapchain;
present_info.pImageIndices = &vulkan_demo->swapchain_image_index; present_info.pImageIndices = &vulkan_demo->swapchain_image_index;
present_info.pResults = nullptr; present_info.pResults = nullptr;
result = vkQueuePresentKHR(get_queue(), &present_info); result = vkQueuePresentKHR(vk_instance.queue, &present_info);
check_vk_result(result, "vkQueuePresentKHR"); check_vk_result(result, "vkQueuePresentKHR");
return (const void *)(cmd + 1); return (const void *)(cmd + 1);

View File

@ -26,6 +26,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
glconfig_t glConfig; glconfig_t glConfig;
glstate_t glState; glstate_t glState;
// VULKAN
Vulkan_Instance vk_instance;
static void GfxInfo_f( void ); static void GfxInfo_f( void );
cvar_t *r_renderAPI; cvar_t *r_renderAPI;
@ -1041,7 +1044,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
R_DeleteTextures(); R_DeleteTextures();
// VULKAN // VULKAN
vk_destroy_pipelines(); vk_destroy_resources();
} }
R_DoneFreeType(); R_DoneFreeType();

View File

@ -55,9 +55,6 @@ long myftol( float f );
// can't be increased without changing bit packing for drawsurfs // can't be increased without changing bit packing for drawsurfs
// VULKAN
#define MAX_VK_PIPELINES 2048
typedef struct dlight_s { typedef struct dlight_s {
vec3_t origin; vec3_t origin;
vec3_t color; // range from 0.0 to 1.0, should be color normalized vec3_t color; // range from 0.0 to 1.0, should be color normalized
@ -942,9 +939,7 @@ typedef struct {
float fogTable[FOG_TABLE_SIZE]; float fogTable[FOG_TABLE_SIZE];
// VULKAN // VULKAN
int vk_num_pipelines; Vulkan_Resources vk;
Vk_Pipeline_Desc vk_pipeline_desc[MAX_VK_PIPELINES];
VkPipeline vk_pipelines[MAX_VK_PIPELINES];
} trGlobals_t; } trGlobals_t;
@ -953,6 +948,9 @@ extern trGlobals_t tr;
extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared during ref re-init extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared during ref re-init
extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init
// VULKAN
extern Vulkan_Instance vk_instance; // same as above - shouldn't be cleared during ref re-init
// VULKAN // VULKAN
class Vulkan_Demo; class Vulkan_Demo;
extern Vulkan_Demo* vulkan_demo; extern Vulkan_Demo* vulkan_demo;

View File

@ -11,21 +11,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
struct Vulkan_Globals {
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE;
uint32_t queue_family_index = 0;
VkDevice device = VK_NULL_HANDLE;
VkQueue queue = VK_NULL_HANDLE;
VkSurfaceFormatKHR surface_format = {};
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
std::vector<VkImage> swapchain_images;
std::vector<VkImageView> swapchain_image_views;
};
static Vulkan_Globals vulkan_globals;
static const std::vector<const char*> instance_extensions = { static const std::vector<const char*> instance_extensions = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_WIN32_SURFACE_EXTENSION_NAME VK_KHR_WIN32_SURFACE_EXTENSION_NAME
@ -249,30 +234,31 @@ static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevic
return swapchain; return swapchain;
} }
bool initialize_vulkan(HWND hwnd) { bool vk_initialize(HWND hwnd) {
try { try {
auto& g = vulkan_globals; auto& g = vk_instance;
g.instance = create_instance(); g.instance = create_instance();
g.physical_device = select_physical_device(g.instance); g.physical_device = select_physical_device(g.instance);
g.surface = create_surface(g.instance, hwnd); g.surface = create_surface(g.instance, hwnd);
g.surface_format = select_surface_format(g.physical_device, g.surface);
g.queue_family_index = select_queue_family(g.physical_device, g.surface); g.queue_family_index = select_queue_family(g.physical_device, g.surface);
g.device = create_device(g.physical_device, g.queue_family_index); g.device = create_device(g.physical_device, g.queue_family_index);
vkGetDeviceQueue(g.device, g.queue_family_index, 0, &g.queue); vkGetDeviceQueue(g.device, g.queue_family_index, 0, &g.queue);
g.surface_format = select_surface_format(g.physical_device, g.surface);
g.swapchain = create_swapchain(g.physical_device, g.device, g.surface, g.surface_format); g.swapchain = create_swapchain(g.physical_device, g.device, g.surface, g.surface_format);
uint32_t image_count; VkResult result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &vk_instance.swapchain_image_count, nullptr);
VkResult result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &image_count, nullptr);
check_vk_result(result, "vkGetSwapchainImagesKHR");
g.swapchain_images.resize(image_count);
result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &image_count, g.swapchain_images.data());
check_vk_result(result, "vkGetSwapchainImagesKHR"); check_vk_result(result, "vkGetSwapchainImagesKHR");
g.swapchain_image_views.resize(image_count); if (vk_instance.swapchain_image_count > MAX_SWAPCHAIN_IMAGES)
for (std::size_t i = 0; i < image_count; i++) { ri.Error( ERR_FATAL, "initialize_vulkan: swapchain image count (%d) exceeded limit (%d)", vk_instance.swapchain_image_count, MAX_SWAPCHAIN_IMAGES );
result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &vk_instance.swapchain_image_count, g.swapchain_images);
check_vk_result(result, "vkGetSwapchainImagesKHR");
for (std::size_t i = 0; i < vk_instance.swapchain_image_count; i++) {
VkImageViewCreateInfo desc; VkImageViewCreateInfo desc;
desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
desc.pNext = nullptr; desc.pNext = nullptr;
@ -298,8 +284,8 @@ bool initialize_vulkan(HWND hwnd) {
return true; return true;
} }
void deinitialize_vulkan() { void vk_deinitialize() {
auto& g = vulkan_globals; auto& g = vk_instance;
for (auto image_view : g.swapchain_image_views) { for (auto image_view : g.swapchain_image_views) {
vkDestroyImageView(g.device, image_view, nullptr); vkDestroyImageView(g.device, image_view, nullptr);
} }
@ -307,35 +293,7 @@ void deinitialize_vulkan() {
vkDestroyDevice(g.device, nullptr); vkDestroyDevice(g.device, nullptr);
vkDestroySurfaceKHR(g.instance, g.surface, nullptr); vkDestroySurfaceKHR(g.instance, g.surface, nullptr);
vkDestroyInstance(g.instance, nullptr); vkDestroyInstance(g.instance, nullptr);
g = Vulkan_Globals(); g = Vulkan_Instance();
}
VkPhysicalDevice get_physical_device() {
return vulkan_globals.physical_device;
}
VkDevice get_device() {
return vulkan_globals.device;
}
uint32_t get_queue_family_index() {
return vulkan_globals.queue_family_index;
}
VkQueue get_queue() {
return vulkan_globals.queue;
}
VkSwapchainKHR get_swapchain() {
return vulkan_globals.swapchain;
}
VkFormat get_swapchain_image_format() {
return vulkan_globals.surface_format.format;
}
const std::vector<VkImageView>& get_swapchain_image_views() {
return vulkan_globals.swapchain_image_views;
} }
VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer) { VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer) {
@ -350,11 +308,11 @@ VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& stag
buffer_desc.pQueueFamilyIndices = nullptr; buffer_desc.pQueueFamilyIndices = nullptr;
VkBuffer buffer; VkBuffer buffer;
VkResult result = vkCreateBuffer(get_device(), &buffer_desc, nullptr, &buffer); VkResult result = vkCreateBuffer(vk_instance.device, &buffer_desc, nullptr, &buffer);
check_vk_result(result, "vkCreateBuffer"); check_vk_result(result, "vkCreateBuffer");
VkDeviceMemory buffer_memory = get_allocator()->allocate_staging_memory(buffer); VkDeviceMemory buffer_memory = get_allocator()->allocate_staging_memory(buffer);
result = vkBindBufferMemory(get_device(), buffer, buffer_memory, 0); result = vkBindBufferMemory(vk_instance.device, buffer, buffer_memory, 0);
check_vk_result(result, "vkBindBufferMemory"); check_vk_result(result, "vkBindBufferMemory");
VkImageCreateInfo image_desc; VkImageCreateInfo image_desc;
@ -377,11 +335,11 @@ VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& stag
image_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImage image; VkImage image;
result = vkCreateImage(get_device(), &image_desc, nullptr, &image); result = vkCreateImage(vk_instance.device, &image_desc, nullptr, &image);
check_vk_result(result, "vkCreateImage"); check_vk_result(result, "vkCreateImage");
VkDeviceMemory image_memory = get_allocator()->allocate_memory(image); VkDeviceMemory image_memory = get_allocator()->allocate_memory(image);
result = vkBindImageMemory(get_device(), image, image_memory, 0); result = vkBindImageMemory(vk_instance.device, image, image_memory, 0);
check_vk_result(result, "vkBindImageMemory"); check_vk_result(result, "vkBindImageMemory");
staging_buffer.handle = buffer; staging_buffer.handle = buffer;
@ -393,12 +351,12 @@ VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& stag
void vk_update_cinematic_image(VkImage image, const Vk_Staging_Buffer& staging_buffer, int width, int height, const uint8_t* rgba_pixels) { void vk_update_cinematic_image(VkImage image, const Vk_Staging_Buffer& staging_buffer, int width, int height, const uint8_t* rgba_pixels) {
void* buffer_data; void* buffer_data;
VkResult result = vkMapMemory(get_device(), staging_buffer.memory, staging_buffer.offset, staging_buffer.size, 0, &buffer_data); VkResult result = vkMapMemory(vk_instance.device, staging_buffer.memory, staging_buffer.offset, staging_buffer.size, 0, &buffer_data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
memcpy(buffer_data, rgba_pixels, staging_buffer.size); memcpy(buffer_data, rgba_pixels, staging_buffer.size);
vkUnmapMemory(get_device(), staging_buffer.memory); vkUnmapMemory(vk_instance.device, staging_buffer.memory);
record_and_run_commands(vulkan_demo->command_pool, get_queue(), record_and_run_commands(vulkan_demo->command_pool, vk_instance.queue,
[&image, &staging_buffer, &width, &height](VkCommandBuffer command_buffer) { [&image, &staging_buffer, &width, &height](VkCommandBuffer command_buffer) {
record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM, record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM,
@ -686,7 +644,7 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
create_info.basePipelineIndex = -1; create_info.basePipelineIndex = -1;
VkPipeline pipeline; VkPipeline pipeline;
VkResult result = vkCreateGraphicsPipelines(get_device(), VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline); VkResult result = vkCreateGraphicsPipelines(vk_instance.device, VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline);
check_vk_result(result, "vkCreateGraphicsPipelines"); check_vk_result(result, "vkCreateGraphicsPipelines");
return pipeline; return pipeline;
} }
@ -706,13 +664,13 @@ struct Timer {
}; };
VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc) { VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc) {
for (int i = 0; i < tr.vk_num_pipelines; i++) { for (int i = 0; i < tr.vk.num_pipelines; i++) {
if (tr.vk_pipeline_desc[i] == desc) { if (tr.vk.pipeline_desc[i] == desc) {
return tr.vk_pipelines[i]; return tr.vk.pipelines[i];
} }
} }
if (tr.vk_num_pipelines == MAX_VK_PIPELINES) { if (tr.vk.num_pipelines == MAX_VK_PIPELINES) {
ri.Error( ERR_DROP, "vk_find_pipeline: MAX_VK_PIPELINES hit\n"); ri.Error( ERR_DROP, "vk_find_pipeline: MAX_VK_PIPELINES hit\n");
} }
@ -720,21 +678,27 @@ VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc) {
VkPipeline pipeline = create_pipeline(desc); VkPipeline pipeline = create_pipeline(desc);
pipeline_create_time += t.Elapsed_Seconds(); pipeline_create_time += t.Elapsed_Seconds();
tr.vk_pipeline_desc[tr.vk_num_pipelines] = desc; tr.vk.pipeline_desc[tr.vk.num_pipelines] = desc;
tr.vk_pipelines[tr.vk_num_pipelines] = pipeline; tr.vk.pipelines[tr.vk.num_pipelines] = pipeline;
tr.vk_num_pipelines++; tr.vk.num_pipelines++;
return pipeline; return pipeline;
} }
void vk_destroy_pipelines() { static void vk_destroy_pipelines() {
for (int i = 0; i < tr.vk_num_pipelines; i++) { vkDeviceWaitIdle(vk_instance.device);
vkDestroyPipeline(get_device(), tr.vk_pipelines[i], nullptr);
for (int i = 0; i < tr.vk.num_pipelines; i++) {
vkDestroyPipeline(vk_instance.device, tr.vk.pipelines[i], nullptr);
} }
tr.vk_num_pipelines = 0; tr.vk.num_pipelines = 0;
Com_Memset(tr.vk_pipelines, 0, sizeof(tr.vk_pipelines)); Com_Memset(tr.vk.pipelines, 0, sizeof(tr.vk.pipelines));
Com_Memset(tr.vk_pipeline_desc, 0, sizeof(tr.vk_pipeline_desc)); Com_Memset(tr.vk.pipeline_desc, 0, sizeof(tr.vk.pipeline_desc));
pipeline_create_time = 0.0f; pipeline_create_time = 0.0f;
} }
void vk_destroy_resources() {
vk_destroy_pipelines();
}

View File

@ -8,20 +8,12 @@
#include "vulkan/vulkan.h" #include "vulkan/vulkan.h"
#include <array> #include <array>
#include <vector>
#include "../../game/q_shared.h" #include "../../game/q_shared.h"
bool initialize_vulkan(HWND hwnd); bool vk_initialize(HWND hwnd);
void deinitialize_vulkan(); void vk_deinitialize();
void vk_destroy_resources();
VkPhysicalDevice get_physical_device();
VkDevice get_device();
uint32_t get_queue_family_index();
VkQueue get_queue();
VkSwapchainKHR get_swapchain();
VkFormat get_swapchain_image_format();
const std::vector<VkImageView>& get_swapchain_image_views();
struct Vk_Staging_Buffer { struct Vk_Staging_Buffer {
VkBuffer handle = VK_NULL_HANDLE; VkBuffer handle = VK_NULL_HANDLE;
@ -56,7 +48,6 @@ struct Vk_Pipeline_Desc {
}; };
VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc); VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc);
void vk_destroy_pipelines();
// Vertex formats // Vertex formats
struct Vk_Vertex { struct Vk_Vertex {
@ -138,3 +129,30 @@ extern long long multi_texture_add_frag_spv_size;
extern unsigned char multi_texture_mul_frag_spv[]; extern unsigned char multi_texture_mul_frag_spv[];
extern long long multi_texture_mul_frag_spv_size; extern long long multi_texture_mul_frag_spv_size;
// Vulkan specific structures used by the engine.
const int MAX_SWAPCHAIN_IMAGES = 8;
struct Vulkan_Instance {
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkSurfaceFormatKHR surface_format = {};
uint32_t queue_family_index = 0;
VkDevice device = VK_NULL_HANDLE;
VkQueue queue = VK_NULL_HANDLE;
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
uint32_t swapchain_image_count = 0;
VkImage swapchain_images[MAX_SWAPCHAIN_IMAGES];
VkImageView swapchain_image_views[MAX_SWAPCHAIN_IMAGES];
};
const int MAX_VK_PIPELINES = 1024;
struct Vulkan_Resources {
int num_pipelines = 0;
Vk_Pipeline_Desc pipeline_desc[MAX_VK_PIPELINES];
VkPipeline pipelines[MAX_VK_PIPELINES];
};

View File

@ -44,8 +44,8 @@ Vulkan_Demo::Vulkan_Demo(int window_width, int window_height)
, window_height(window_height) , window_height(window_height)
{ {
logfile = fopen("vk_dev.log", "w"); logfile = fopen("vk_dev.log", "w");
get_allocator()->initialize(get_physical_device(), get_device()); get_allocator()->initialize(vk_instance.physical_device, vk_instance.device);
get_resource_manager()->initialize(get_device()); get_resource_manager()->initialize(vk_instance.device);
create_command_pool(); create_command_pool();
image_acquired = get_resource_manager()->create_semaphore(); image_acquired = get_resource_manager()->create_semaphore();
@ -55,7 +55,7 @@ Vulkan_Demo::Vulkan_Demo(int window_width, int window_height)
fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_desc.pNext = nullptr; fence_desc.pNext = nullptr;
fence_desc.flags = VK_FENCE_CREATE_SIGNALED_BIT; fence_desc.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkResult result = vkCreateFence(get_device(), &fence_desc, nullptr, &rendering_finished_fence); VkResult result = vkCreateFence(vk_instance.device, &fence_desc, nullptr, &rendering_finished_fence);
check_vk_result(result, "vkCreateFence"); check_vk_result(result, "vkCreateFence");
create_descriptor_pool(); create_descriptor_pool();
@ -79,20 +79,20 @@ Vulkan_Demo::Vulkan_Demo(int window_width, int window_height)
alloc_info.commandPool = command_pool; alloc_info.commandPool = command_pool;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
alloc_info.commandBufferCount = 1; alloc_info.commandBufferCount = 1;
result = vkAllocateCommandBuffers(get_device(), &alloc_info, &command_buffer); result = vkAllocateCommandBuffers(vk_instance.device, &alloc_info, &command_buffer);
check_vk_result(result, "vkAllocateCommandBuffers"); check_vk_result(result, "vkAllocateCommandBuffers");
} }
} }
Vulkan_Demo::~Vulkan_Demo() { Vulkan_Demo::~Vulkan_Demo() {
VkResult result = vkDeviceWaitIdle(get_device()); VkResult result = vkDeviceWaitIdle(vk_instance.device);
if (result < 0) if (result < 0)
std::cerr << "vkDeviceWaitIdle returned an error code: " + result; std::cerr << "vkDeviceWaitIdle returned an error code: " + result;
get_resource_manager()->release_resources(); get_resource_manager()->release_resources();
get_allocator()->deallocate_all(); get_allocator()->deallocate_all();
deinitialize_vulkan(); vk_deinitialize();
} }
void Vulkan_Demo::create_command_pool() { void Vulkan_Demo::create_command_pool() {
@ -100,7 +100,7 @@ void Vulkan_Demo::create_command_pool() {
desc.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; desc.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
desc.pNext = nullptr; desc.pNext = nullptr;
desc.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; desc.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
desc.queueFamilyIndex = get_queue_family_index(); desc.queueFamilyIndex = vk_instance.queue_family_index;
command_pool = get_resource_manager()->create_command_pool(desc); command_pool = get_resource_manager()->create_command_pool(desc);
} }
@ -128,7 +128,7 @@ void Vulkan_Demo::create_uniform_buffer() {
uniform_buffer = create_buffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); uniform_buffer = create_buffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
VkPhysicalDeviceProperties props; VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(get_physical_device(), &props); vkGetPhysicalDeviceProperties(vk_instance.physical_device, &props);
VkDeviceSize offset_align = props.limits.minUniformBufferOffsetAlignment; VkDeviceSize offset_align = props.limits.minUniformBufferOffsetAlignment;
tess_ubo_offset_step = (uint32_t)((sizeof(Uniform_Buffer_Object) + offset_align - 1) / offset_align * offset_align); tess_ubo_offset_step = (uint32_t)((sizeof(Uniform_Buffer_Object) + offset_align - 1) / offset_align * offset_align);
} }
@ -138,13 +138,13 @@ VkImage Vulkan_Demo::create_texture(const uint8_t* pixels, int bytes_per_pixel,
bytes_per_pixel == 3 ? VK_FORMAT_R8G8B8_UNORM : VK_FORMAT_R8G8B8A8_UNORM, pixels, bytes_per_pixel); bytes_per_pixel == 3 ? VK_FORMAT_R8G8B8_UNORM : VK_FORMAT_R8G8B8A8_UNORM, pixels, bytes_per_pixel);
Defer_Action destroy_staging_image([this, &staging_image]() { Defer_Action destroy_staging_image([this, &staging_image]() {
vkDestroyImage(get_device(), staging_image, nullptr); vkDestroyImage(vk_instance.device, staging_image, nullptr);
}); });
VkImage texture_image = ::create_texture(image_width, image_height, VkImage texture_image = ::create_texture(image_width, image_height,
bytes_per_pixel == 3 ? VK_FORMAT_R8G8B8_UNORM : VK_FORMAT_R8G8B8A8_UNORM); bytes_per_pixel == 3 ? VK_FORMAT_R8G8B8_UNORM : VK_FORMAT_R8G8B8A8_UNORM);
record_and_run_commands(command_pool, get_queue(), record_and_run_commands(command_pool, vk_instance.queue,
[&texture_image, &staging_image, &image_width, &image_height, this](VkCommandBuffer command_buffer) { [&texture_image, &staging_image, &image_width, &image_height, this](VkCommandBuffer command_buffer) {
record_image_layout_transition(command_buffer, staging_image, VK_FORMAT_R8G8B8A8_UNORM, record_image_layout_transition(command_buffer, staging_image, VK_FORMAT_R8G8B8A8_UNORM,
@ -206,11 +206,11 @@ void Vulkan_Demo::create_texture_sampler() {
} }
void Vulkan_Demo::create_depth_buffer_resources() { void Vulkan_Demo::create_depth_buffer_resources() {
VkFormat depth_format = find_depth_format(get_physical_device()); VkFormat depth_format = find_depth_format(vk_instance.physical_device);
depth_image = create_depth_attachment_image(window_width, window_height, depth_format); depth_image = create_depth_attachment_image(window_width, window_height, depth_format);
depth_image_view = create_image_view(depth_image, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT); depth_image_view = create_image_view(depth_image, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT);
record_and_run_commands(command_pool, get_queue(), [&depth_format, this](VkCommandBuffer command_buffer) { record_and_run_commands(command_pool, vk_instance.queue, [&depth_format, this](VkCommandBuffer command_buffer) {
record_image_layout_transition(command_buffer, depth_image, depth_format, 0, VK_IMAGE_LAYOUT_UNDEFINED, record_image_layout_transition(command_buffer, depth_image, depth_format, 0, VK_IMAGE_LAYOUT_UNDEFINED,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}); });
@ -255,7 +255,7 @@ void Vulkan_Demo::create_image_descriptor_set(const image_t* image) {
desc.pSetLayouts = &descriptor_set_layout; desc.pSetLayouts = &descriptor_set_layout;
VkDescriptorSet set; VkDescriptorSet set;
VkResult result = vkAllocateDescriptorSets(get_device(), &desc, &set); VkResult result = vkAllocateDescriptorSets(vk_instance.device, &desc, &set);
check_vk_result(result, "vkAllocateDescriptorSets"); check_vk_result(result, "vkAllocateDescriptorSets");
VkDescriptorImageInfo image_info; VkDescriptorImageInfo image_info;
@ -275,7 +275,7 @@ void Vulkan_Demo::create_image_descriptor_set(const image_t* image) {
descriptor_writes[0].pBufferInfo = nullptr; descriptor_writes[0].pBufferInfo = nullptr;
descriptor_writes[0].pTexelBufferView = nullptr; descriptor_writes[0].pTexelBufferView = nullptr;
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr); vkUpdateDescriptorSets(vk_instance.device, (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
update_ubo_descriptor(set); update_ubo_descriptor(set);
@ -291,7 +291,7 @@ void Vulkan_Demo::create_multitexture_descriptor_set(const image_t* image, const
desc.pSetLayouts = &descriptor_set_layout; desc.pSetLayouts = &descriptor_set_layout;
VkDescriptorSet set; VkDescriptorSet set;
VkResult result = vkAllocateDescriptorSets(get_device(), &desc, &set); VkResult result = vkAllocateDescriptorSets(vk_instance.device, &desc, &set);
check_vk_result(result, "vkAllocateDescriptorSets"); check_vk_result(result, "vkAllocateDescriptorSets");
VkDescriptorImageInfo image_info[2]; VkDescriptorImageInfo image_info[2];
@ -326,7 +326,7 @@ void Vulkan_Demo::create_multitexture_descriptor_set(const image_t* image, const
descriptor_writes[1].pBufferInfo = nullptr; descriptor_writes[1].pBufferInfo = nullptr;
descriptor_writes[1].pTexelBufferView = nullptr; descriptor_writes[1].pTexelBufferView = nullptr;
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr); vkUpdateDescriptorSets(vk_instance.device, (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
update_ubo_descriptor(set); update_ubo_descriptor(set);
@ -337,7 +337,7 @@ void Vulkan_Demo::create_multitexture_descriptor_set(const image_t* image, const
void Vulkan_Demo::create_render_pass() { void Vulkan_Demo::create_render_pass() {
VkAttachmentDescription color_attachment; VkAttachmentDescription color_attachment;
color_attachment.flags = 0; color_attachment.flags = 0;
color_attachment.format = get_swapchain_image_format(); color_attachment.format = vk_instance.surface_format.format;
color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; color_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@ -348,7 +348,7 @@ void Vulkan_Demo::create_render_pass() {
VkAttachmentDescription depth_attachment; VkAttachmentDescription depth_attachment;
depth_attachment.flags = 0; depth_attachment.flags = 0;
depth_attachment.format = find_depth_format(get_physical_device()); depth_attachment.format = find_depth_format(vk_instance.physical_device);
depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@ -406,10 +406,9 @@ void Vulkan_Demo::create_framebuffers() {
desc.height = window_height; desc.height = window_height;
desc.layers = 1; desc.layers = 1;
const auto& swapchain_image_views = get_swapchain_image_views(); framebuffers.resize(vk_instance.swapchain_image_count);
framebuffers.resize(swapchain_image_views.size());
for (std::size_t i = 0; i < framebuffers.size(); i++) { for (std::size_t i = 0; i < framebuffers.size(); i++) {
attachments[0] = swapchain_image_views[i]; // set color attachment attachments[0] = vk_instance.swapchain_image_views[i]; // set color attachment
framebuffers[i] = get_resource_manager()->create_framebuffer(desc); framebuffers[i] = get_resource_manager()->create_framebuffer(desc);
} }
} }
@ -442,7 +441,7 @@ void Vulkan_Demo::upload_geometry() {
tess_vertex_buffer = get_resource_manager()->create_buffer(desc); tess_vertex_buffer = get_resource_manager()->create_buffer(desc);
tess_vertex_buffer_memory = get_allocator()->allocate_staging_memory(tess_vertex_buffer); tess_vertex_buffer_memory = get_allocator()->allocate_staging_memory(tess_vertex_buffer);
VkResult result = vkBindBufferMemory(get_device(), tess_vertex_buffer, tess_vertex_buffer_memory, 0); VkResult result = vkBindBufferMemory(vk_instance.device, tess_vertex_buffer, tess_vertex_buffer_memory, 0);
check_vk_result(result, "vkBindBufferMemory"); check_vk_result(result, "vkBindBufferMemory");
} }
@ -459,7 +458,7 @@ void Vulkan_Demo::upload_geometry() {
tess_index_buffer = get_resource_manager()->create_buffer(desc); tess_index_buffer = get_resource_manager()->create_buffer(desc);
tess_index_buffer_memory = get_allocator()->allocate_staging_memory(tess_index_buffer); tess_index_buffer_memory = get_allocator()->allocate_staging_memory(tess_index_buffer);
VkResult result = vkBindBufferMemory(get_device(), tess_index_buffer, tess_index_buffer_memory, 0); VkResult result = vkBindBufferMemory(vk_instance.device, tess_index_buffer, tess_index_buffer_memory, 0);
check_vk_result(result, "vkBindBufferMemory"); check_vk_result(result, "vkBindBufferMemory");
} }
} }
@ -482,7 +481,7 @@ void Vulkan_Demo::update_ubo_descriptor(VkDescriptorSet set) {
descriptor_writes[0].pBufferInfo = &buffer_info; descriptor_writes[0].pBufferInfo = &buffer_info;
descriptor_writes[0].pTexelBufferView = nullptr; descriptor_writes[0].pTexelBufferView = nullptr;
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr); vkUpdateDescriptorSets(vk_instance.device, (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
} }
void Vulkan_Demo::update_uniform_buffer() { void Vulkan_Demo::update_uniform_buffer() {
@ -519,10 +518,10 @@ void Vulkan_Demo::update_uniform_buffer() {
} }
void* data; void* data;
VkResult result = vkMapMemory(get_device(), uniform_staging_buffer_memory, tess_ubo_offset, sizeof(ubo), 0, &data); VkResult result = vkMapMemory(vk_instance.device, uniform_staging_buffer_memory, tess_ubo_offset, sizeof(ubo), 0, &data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
memcpy(data, &ubo, sizeof(ubo)); memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(get_device(), uniform_staging_buffer_memory); vkUnmapMemory(vk_instance.device, uniform_staging_buffer_memory);
} }
void Vulkan_Demo::begin_frame() { void Vulkan_Demo::begin_frame() {
@ -581,7 +580,7 @@ void Vulkan_Demo::render_tess(const shaderStage_t* stage) {
fflush(logfile); fflush(logfile);
void* data; void* data;
VkResult result = vkMapMemory(get_device(), tess_vertex_buffer_memory, tess_vertex_buffer_offset, tess.numVertexes * sizeof(Vk_Vertex), 0, &data); VkResult result = vkMapMemory(vk_instance.device, tess_vertex_buffer_memory, tess_vertex_buffer_offset, tess.numVertexes * sizeof(Vk_Vertex), 0, &data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
Vk_Vertex* v = (Vk_Vertex*)data; Vk_Vertex* v = (Vk_Vertex*)data;
for (int i = 0; i < tess.numVertexes; i++, v++) { for (int i = 0; i < tess.numVertexes; i++, v++) {
@ -595,15 +594,15 @@ void Vulkan_Demo::render_tess(const shaderStage_t* stage) {
v->st[0] = tess.svars.texcoords[0][i][0]; v->st[0] = tess.svars.texcoords[0][i][0];
v->st[1] = tess.svars.texcoords[0][i][1]; v->st[1] = tess.svars.texcoords[0][i][1];
} }
vkUnmapMemory(get_device(), tess_vertex_buffer_memory); vkUnmapMemory(vk_instance.device, tess_vertex_buffer_memory);
result = vkMapMemory(get_device(), tess_index_buffer_memory, tess_index_buffer_offset, tess.numIndexes * sizeof(uint32_t), 0, &data); result = vkMapMemory(vk_instance.device, tess_index_buffer_memory, tess_index_buffer_offset, tess.numIndexes * sizeof(uint32_t), 0, &data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
uint32_t* ind = (uint32_t*)data; uint32_t* ind = (uint32_t*)data;
for (int i = 0; i < tess.numIndexes; i++, ind++) { for (int i = 0; i < tess.numIndexes; i++, ind++) {
*ind = tess.indexes[i]; *ind = tess.indexes[i];
} }
vkUnmapMemory(get_device(), tess_index_buffer_memory); vkUnmapMemory(vk_instance.device, tess_index_buffer_memory);
const VkDeviceSize offset = 0; const VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(command_buffer, 0, 1, &tess_vertex_buffer, &tess_vertex_buffer_offset); vkCmdBindVertexBuffers(command_buffer, 0, 1, &tess_vertex_buffer, &tess_vertex_buffer_offset);
@ -660,7 +659,7 @@ void Vulkan_Demo::render_tess_multi(const shaderStage_t* stage) {
fflush(logfile); fflush(logfile);
void* data; void* data;
VkResult result = vkMapMemory(get_device(), tess_vertex_buffer_memory, tess_vertex_buffer_offset, tess.numVertexes * sizeof(Vk_Vertex2), 0, &data); VkResult result = vkMapMemory(vk_instance.device, tess_vertex_buffer_memory, tess_vertex_buffer_offset, tess.numVertexes * sizeof(Vk_Vertex2), 0, &data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
Vk_Vertex2* v = (Vk_Vertex2*)data; Vk_Vertex2* v = (Vk_Vertex2*)data;
for (int i = 0; i < tess.numVertexes; i++, v++) { for (int i = 0; i < tess.numVertexes; i++, v++) {
@ -676,15 +675,15 @@ void Vulkan_Demo::render_tess_multi(const shaderStage_t* stage) {
v->st2[0] = tess.svars.texcoords[1][i][0]; v->st2[0] = tess.svars.texcoords[1][i][0];
v->st2[1] = tess.svars.texcoords[1][i][1]; v->st2[1] = tess.svars.texcoords[1][i][1];
} }
vkUnmapMemory(get_device(), tess_vertex_buffer_memory); vkUnmapMemory(vk_instance.device, tess_vertex_buffer_memory);
result = vkMapMemory(get_device(), tess_index_buffer_memory, tess_index_buffer_offset, tess.numIndexes * sizeof(uint32_t), 0, &data); result = vkMapMemory(vk_instance.device, tess_index_buffer_memory, tess_index_buffer_offset, tess.numIndexes * sizeof(uint32_t), 0, &data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
uint32_t* ind = (uint32_t*)data; uint32_t* ind = (uint32_t*)data;
for (int i = 0; i < tess.numIndexes; i++, ind++) { for (int i = 0; i < tess.numIndexes; i++, ind++) {
*ind = tess.indexes[i]; *ind = tess.indexes[i];
} }
vkUnmapMemory(get_device(), tess_index_buffer_memory); vkUnmapMemory(vk_instance.device, tess_index_buffer_memory);
const VkDeviceSize offset = 0; const VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(command_buffer, 0, 1, &tess_vertex_buffer, &tess_vertex_buffer_offset); vkCmdBindVertexBuffers(command_buffer, 0, 1, &tess_vertex_buffer, &tess_vertex_buffer_offset);

View File

@ -5,6 +5,8 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "tr_local.h"
void check_vk_result(VkResult result, const std::string& functionName) { void check_vk_result(VkResult result, const std::string& functionName) {
if (result < 0) { if (result < 0) {
error(functionName + " has returned error code with value " + std::to_string(result)); error(functionName + " has returned error code with value " + std::to_string(result));
@ -28,12 +30,12 @@ Shader_Module::Shader_Module(uint8_t bytes[], int size) {
desc.codeSize = data.size(); desc.codeSize = data.size();
desc.pCode = reinterpret_cast<const uint32_t*>(data.data()); desc.pCode = reinterpret_cast<const uint32_t*>(data.data());
VkResult result = vkCreateShaderModule(get_device(), &desc, nullptr, &handle); VkResult result = vkCreateShaderModule(vk_instance.device, &desc, nullptr, &handle);
check_vk_result(result, "vkCreateShaderModule"); check_vk_result(result, "vkCreateShaderModule");
} }
Shader_Module::~Shader_Module() { Shader_Module::~Shader_Module() {
vkDestroyShaderModule(get_device(), handle, nullptr); vkDestroyShaderModule(vk_instance.device, handle, nullptr);
} }
void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::function<void(VkCommandBuffer)> recorder) { void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::function<void(VkCommandBuffer)> recorder) {
@ -46,7 +48,7 @@ void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::fun
alloc_info.commandBufferCount = 1; alloc_info.commandBufferCount = 1;
VkCommandBuffer command_buffer; VkCommandBuffer command_buffer;
VkResult result = vkAllocateCommandBuffers(get_device(), &alloc_info, &command_buffer); VkResult result = vkAllocateCommandBuffers(vk_instance.device, &alloc_info, &command_buffer);
check_vk_result(result, "vkAllocateCommandBuffers"); check_vk_result(result, "vkAllocateCommandBuffers");
VkCommandBufferBeginInfo begin_info; VkCommandBufferBeginInfo begin_info;
@ -76,7 +78,7 @@ void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::fun
check_vk_result(result, "vkQueueSubmit"); check_vk_result(result, "vkQueueSubmit");
result = vkQueueWaitIdle(queue); result = vkQueueWaitIdle(queue);
check_vk_result(result, "vkQueueWaitIdle"); check_vk_result(result, "vkQueueWaitIdle");
vkFreeCommandBuffers(get_device(), command_pool, 1, &command_buffer); vkFreeCommandBuffers(vk_instance.device, command_pool, 1, &command_buffer);
} }
static bool has_depth_component(VkFormat format) { static bool has_depth_component(VkFormat format) {
@ -162,7 +164,7 @@ VkImage create_texture(int image_width, int image_height, VkFormat format) {
VkImage image = get_resource_manager()->create_image(desc); VkImage image = get_resource_manager()->create_image(desc);
VkDeviceMemory memory = get_allocator()->allocate_memory(image); VkDeviceMemory memory = get_allocator()->allocate_memory(image);
VkResult result = vkBindImageMemory(get_device(), image, memory, 0); VkResult result = vkBindImageMemory(vk_instance.device, image, memory, 0);
check_vk_result(result, "vkBindImageMemory"); check_vk_result(result, "vkBindImageMemory");
return image; return image;
} }
@ -188,12 +190,12 @@ VkImage create_staging_texture(int image_width, int image_height, VkFormat forma
desc.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; desc.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
VkImage image; VkImage image;
VkResult result = vkCreateImage(get_device(), &desc, nullptr, &image); VkResult result = vkCreateImage(vk_instance.device, &desc, nullptr, &image);
check_vk_result(result, "vkCreateImage"); check_vk_result(result, "vkCreateImage");
get_allocator()->get_shared_staging_memory().ensure_allocation_for_object(image); get_allocator()->get_shared_staging_memory().ensure_allocation_for_object(image);
VkDeviceMemory memory = get_allocator()->get_shared_staging_memory().get_handle(); VkDeviceMemory memory = get_allocator()->get_shared_staging_memory().get_handle();
result = vkBindImageMemory(get_device(), image, memory, 0); result = vkBindImageMemory(vk_instance.device, image, memory, 0);
check_vk_result(result, "vkBindImageMemory"); check_vk_result(result, "vkBindImageMemory");
VkImageSubresource staging_image_subresource; VkImageSubresource staging_image_subresource;
@ -201,10 +203,10 @@ VkImage create_staging_texture(int image_width, int image_height, VkFormat forma
staging_image_subresource.mipLevel = 0; staging_image_subresource.mipLevel = 0;
staging_image_subresource.arrayLayer = 0; staging_image_subresource.arrayLayer = 0;
VkSubresourceLayout staging_image_layout; VkSubresourceLayout staging_image_layout;
vkGetImageSubresourceLayout(get_device(), image, &staging_image_subresource, &staging_image_layout); vkGetImageSubresourceLayout(vk_instance.device, image, &staging_image_subresource, &staging_image_layout);
void* data; void* data;
result = vkMapMemory(get_device(), memory, 0, staging_image_layout.size, 0, &data); result = vkMapMemory(vk_instance.device, memory, 0, staging_image_layout.size, 0, &data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
const int bytes_per_row = image_width * bytes_per_pixel; const int bytes_per_row = image_width * bytes_per_pixel;
@ -216,7 +218,7 @@ VkImage create_staging_texture(int image_width, int image_height, VkFormat forma
memcpy(&bytes[i * staging_image_layout.rowPitch], &pixels[i * bytes_per_row], bytes_per_row); memcpy(&bytes[i * staging_image_layout.rowPitch], &pixels[i * bytes_per_row], bytes_per_row);
} }
} }
vkUnmapMemory(get_device(), memory); vkUnmapMemory(vk_instance.device, memory);
return image; return image;
} }
@ -243,7 +245,7 @@ VkImage create_depth_attachment_image(int image_width, int image_height, VkForma
VkImage image = get_resource_manager()->create_image(desc); VkImage image = get_resource_manager()->create_image(desc);
VkDeviceMemory memory = get_allocator()->allocate_memory(image); VkDeviceMemory memory = get_allocator()->allocate_memory(image);
VkResult result = vkBindImageMemory(get_device(), image, memory, 0); VkResult result = vkBindImageMemory(vk_instance.device, image, memory, 0);
check_vk_result(result, "vkBindImageMemory"); check_vk_result(result, "vkBindImageMemory");
return image; return image;
} }
@ -283,7 +285,7 @@ VkBuffer create_buffer(VkDeviceSize size, VkBufferUsageFlags usage) {
VkBuffer buffer = get_resource_manager()->create_buffer(desc); VkBuffer buffer = get_resource_manager()->create_buffer(desc);
VkDeviceMemory memory = get_allocator()->allocate_memory(buffer); VkDeviceMemory memory = get_allocator()->allocate_memory(buffer);
VkResult result = vkBindBufferMemory(get_device(), buffer, memory, 0); VkResult result = vkBindBufferMemory(vk_instance.device, buffer, memory, 0);
check_vk_result(result, "vkBindBufferMemory"); check_vk_result(result, "vkBindBufferMemory");
return buffer; return buffer;
} }
@ -300,19 +302,19 @@ VkBuffer create_staging_buffer(VkDeviceSize size, const void* data) {
desc.pQueueFamilyIndices = nullptr; desc.pQueueFamilyIndices = nullptr;
VkBuffer buffer; VkBuffer buffer;
VkResult result = vkCreateBuffer(get_device(), &desc, nullptr, &buffer); VkResult result = vkCreateBuffer(vk_instance.device, &desc, nullptr, &buffer);
check_vk_result(result, "vkCreateBuffer"); check_vk_result(result, "vkCreateBuffer");
get_allocator()->get_shared_staging_memory().ensure_allocation_for_object(buffer); get_allocator()->get_shared_staging_memory().ensure_allocation_for_object(buffer);
VkDeviceMemory memory = get_allocator()->get_shared_staging_memory().get_handle(); VkDeviceMemory memory = get_allocator()->get_shared_staging_memory().get_handle();
result = vkBindBufferMemory(get_device(), buffer, memory, 0); result = vkBindBufferMemory(vk_instance.device, buffer, memory, 0);
check_vk_result(result, "vkBindBufferMemory"); check_vk_result(result, "vkBindBufferMemory");
void* buffer_data; void* buffer_data;
result = vkMapMemory(get_device(), memory, 0, size, 0, &buffer_data); result = vkMapMemory(vk_instance.device, memory, 0, size, 0, &buffer_data);
check_vk_result(result, "vkMapMemory"); check_vk_result(result, "vkMapMemory");
memcpy(buffer_data, data, size); memcpy(buffer_data, data, size);
vkUnmapMemory(get_device(), memory); vkUnmapMemory(vk_instance.device, memory);
return buffer; return buffer;
} }
@ -330,7 +332,7 @@ VkBuffer create_permanent_staging_buffer(VkDeviceSize size, VkDeviceMemory& memo
VkBuffer buffer = get_resource_manager()->create_buffer(desc); VkBuffer buffer = get_resource_manager()->create_buffer(desc);
memory = get_allocator()->allocate_staging_memory(buffer); memory = get_allocator()->allocate_staging_memory(buffer);
VkResult result = vkBindBufferMemory(get_device(), buffer, memory, 0); VkResult result = vkBindBufferMemory(vk_instance.device, buffer, memory, 0);
check_vk_result(result, "vkBindBufferMemory"); check_vk_result(result, "vkBindBufferMemory");
return buffer; return buffer;
} }