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:
parent
44a5f950ad
commit
eca35b6050
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user