diff --git a/src/engine/renderer/tr_backend.c b/src/engine/renderer/tr_backend.c index 5b33808..299a8a4 100644 --- a/src/engine/renderer/tr_backend.c +++ b/src/engine/renderer/tr_backend.c @@ -63,11 +63,11 @@ void GL_Bind( image_t *image ) { glState.currenttextures[glState.currenttmu] = texnum; qglBindTexture (GL_TEXTURE_2D, texnum); - // VULKAN - if (vk.active) { - VkDescriptorSet set = vk_resources.images[final_image->index].descriptor_set; - vk_resources.current_descriptor_sets[glState.currenttmu] = set; - } + // VULKAN + if (vk.active) { + VkDescriptorSet set = vk_resources.images[final_image->index].descriptor_set; + vk_resources.current_descriptor_sets[glState.currenttmu] = set; + } } } @@ -710,26 +710,26 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); - // VULKAN - if (vk.active) { - Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; - vkDestroyImage(vk.device, image.handle, nullptr); - vkDestroyImageView(vk.device, image.view, nullptr); - vkFreeDescriptorSets(vk.device, vk.descriptor_pool, 1, &image.descriptor_set); - image = vk_create_image(cols, rows, VK_FORMAT_R8G8B8A8_UNORM, 1, false); - vk_upload_image_data(image.handle, cols, rows, false, data, 4); - } + // VULKAN + if (vk.active) { + Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; + vkDestroyImage(vk.device, image.handle, nullptr); + vkDestroyImageView(vk.device, image.view, nullptr); + vkFreeDescriptorSets(vk.device, vk.descriptor_pool, 1, &image.descriptor_set); + image = vk_create_image(cols, rows, VK_FORMAT_R8G8B8A8_UNORM, 1, false); + vk_upload_image_data(image.handle, cols, rows, false, data, 4); + } } else { if (dirty) { // otherwise, just subimage upload it so that drivers can tell we are going to be changing // it and don't try and do a texture compression qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); - // VULKAN - if (vk.active) { - const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; - vk_upload_image_data(image.handle, cols, rows, false, data, 4); - } + // VULKAN + if (vk.active) { + const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; + vk_upload_image_data(image.handle, cols, rows, false, data, 4); + } } } } @@ -1045,8 +1045,8 @@ const void *RB_SwapBuffers( const void *data ) { backEnd.projection2D = qfalse; - // VULKAN - vk_end_frame(); + // VULKAN + vk_end_frame(); return (const void *)(cmd + 1); } diff --git a/src/engine/renderer/tr_image.c b/src/engine/renderer/tr_image.c index 1590c20..ddf50e9 100644 --- a/src/engine/renderer/tr_image.c +++ b/src/engine/renderer/tr_image.c @@ -144,17 +144,17 @@ void GL_TextureMode( const char *string ) { } } - // VULKAN - if (vk.active) { - VK_CHECK(vkDeviceWaitIdle(vk.device)); - for ( i = 0 ; i < tr.numImages ; i++ ) { - image_t* glt = tr.images[i]; - if (glt->mipmap) { - Vk_Image& image = vk_resources.images[i]; - vk_update_descriptor_set(image.descriptor_set, image.view, true, glt->wrapClampMode == GL_REPEAT); - } - } - } + // VULKAN + if (vk.active) { + VK_CHECK(vkDeviceWaitIdle(vk.device)); + for ( i = 0 ; i < tr.numImages ; i++ ) { + image_t* glt = tr.images[i]; + if (glt->mipmap) { + Vk_Image& image = vk_resources.images[i]; + vk_update_descriptor_set(image.descriptor_set, image.view, true, glt->wrapClampMode == GL_REPEAT); + } + } + } } /* diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 592367c..c55eddc 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -318,10 +318,10 @@ typedef struct { qboolean isDetail; - // VULKAN - VkPipeline vk_pipeline = VK_NULL_HANDLE; - VkPipeline vk_portal_pipeline = VK_NULL_HANDLE; - VkPipeline vk_mirror_pipeline = VK_NULL_HANDLE; + // VULKAN + VkPipeline vk_pipeline = VK_NULL_HANDLE; + VkPipeline vk_portal_pipeline = VK_NULL_HANDLE; + VkPipeline vk_mirror_pipeline = VK_NULL_HANDLE; } shaderStage_t; struct shaderCommands_s; @@ -929,16 +929,16 @@ extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared duri extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init // VULKAN -extern Vk_Instance vk; // shouldn't be cleared during ref re-init -extern Vk_Resources vk_resources; // this data is cleared during ref re-init +extern Vk_Instance vk; // shouldn't be cleared during ref re-init +extern Vk_Resources vk_resources; // this data is cleared during ref re-init // // cvars // -extern cvar_t *r_renderAPI; // 3D API to use: 0 - OpenGL, 1 - Vulkan. +extern cvar_t *r_renderAPI; // 3D API to use: 0 - OpenGL, 1 - Vulkan. -extern cvar_t *r_twinMode; // If enabled, renderer creates two separate windows. +extern cvar_t *r_twinMode; // If enabled, renderer creates two separate windows. // The first window uses rendering API specified by r_renderAPI, // the second window uses rendering API corresponding to (1 - r_renderAPI). diff --git a/src/engine/renderer/tr_shade.c b/src/engine/renderer/tr_shade.c index 08a2aaf..819d088 100644 --- a/src/engine/renderer/tr_shade.c +++ b/src/engine/renderer/tr_shade.c @@ -393,11 +393,11 @@ static void ProjectDlightTexture( void ) { backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; - // VULKAN - if (vk.active) { - VkPipeline pipeline = vk.dlight_pipelines[dl->additive > 0 ? 1 : 0][tess.shader->cullType][tess.shader->polygonOffset]; - vk_shade_geometry(pipeline, false, Vk_Depth_Range::normal); - } + // VULKAN + if (vk.active) { + VkPipeline pipeline = vk.dlight_pipelines[dl->additive > 0 ? 1 : 0][tess.shader->cullType][tess.shader->polygonOffset]; + vk_shade_geometry(pipeline, false, Vk_Depth_Range::normal); + } } } @@ -437,12 +437,12 @@ static void RB_FogPass( void ) { R_DrawElements( tess.numIndexes, tess.indexes ); - // VULKAN - if (vk.active) { - assert(tess.shader->fogPass > 0); - VkPipeline pipeline = vk.fog_pipelines[tess.shader->fogPass - 1][tess.shader->cullType][tess.shader->polygonOffset]; - vk_shade_geometry(pipeline, false, Vk_Depth_Range::normal); - } + // VULKAN + if (vk.active) { + assert(tess.shader->fogPass > 0); + VkPipeline pipeline = vk.fog_pipelines[tess.shader->fogPass - 1][tess.shader->cullType][tess.shader->polygonOffset]; + vk_shade_geometry(pipeline, false, Vk_Depth_Range::normal); + } } /* @@ -745,8 +745,8 @@ static void ComputeTexCoords( shaderStage_t *pStage ) { */ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { - // VULKAN - vk_bind_geometry(); + // VULKAN + vk_bind_geometry(); for ( int stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { @@ -794,23 +794,21 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) R_DrawElements( input->numIndexes, input->indexes ); } - // VULKAN - if (vk.active) { - VkPipeline pipeline = pStage->vk_pipeline; - if (backEnd.viewParms.isMirror) - pipeline = pStage->vk_mirror_pipeline; - else if (backEnd.viewParms.isPortal) - pipeline = pStage->vk_portal_pipeline; + // VULKAN + if (vk.active) { + VkPipeline pipeline = pStage->vk_pipeline; + if (backEnd.viewParms.isMirror) + pipeline = pStage->vk_mirror_pipeline; + else if (backEnd.viewParms.isPortal) + pipeline = pStage->vk_portal_pipeline; - Vk_Depth_Range depth_range; + Vk_Depth_Range depth_range = Vk_Depth_Range::normal; if (input->shader->isSky) { depth_range = Vk_Depth_Range::force_one; if (r_showsky->integer) depth_range = Vk_Depth_Range::force_zero; } else if (backEnd.currentEntity->e.renderfx & RF_DEPTHHACK) { depth_range = Vk_Depth_Range::weapon; - } else { - depth_range = Vk_Depth_Range::normal; } if (r_lightmap->integer && multitexture) diff --git a/src/engine/renderer/tr_shader.c b/src/engine/renderer/tr_shader.c index c1ecf5d..6e6db72 100644 --- a/src/engine/renderer/tr_shader.c +++ b/src/engine/renderer/tr_shader.c @@ -2160,38 +2160,38 @@ static shader_t *FinishShader( void ) { shader.sort = SS_FOG; } - // VULKAN: create pipelines for each shader stage - if (vk.active) { - Vk_Pipeline_Def def; - def.face_culling = shader.cullType; - def.polygon_offset = (shader.polygonOffset == qtrue); + // VULKAN: create pipelines for each shader stage + if (vk.active) { + Vk_Pipeline_Def def; + def.face_culling = shader.cullType; + def.polygon_offset = (shader.polygonOffset == qtrue); - for (int i = 0; i < stage; i++) { - shaderStage_t *pStage = &stages[i]; - def.state_bits = pStage->stateBits; + for (int i = 0; i < stage; i++) { + shaderStage_t *pStage = &stages[i]; + def.state_bits = pStage->stateBits; - if (pStage->bundle[1].image[0] == nullptr) - def.shader_type = Vk_Shader_Type::single_texture; - else if (shader.multitextureEnv == GL_MODULATE) - def.shader_type = Vk_Shader_Type::multi_texture_mul; - else if (shader.multitextureEnv == GL_ADD) - def.shader_type = Vk_Shader_Type::multi_texture_add; - else - ri.Error(ERR_FATAL, "Vulkan: could not create pipelines for q3 shader '%s'\n", shader.name); + if (pStage->bundle[1].image[0] == nullptr) + def.shader_type = Vk_Shader_Type::single_texture; + else if (shader.multitextureEnv == GL_MODULATE) + def.shader_type = Vk_Shader_Type::multi_texture_mul; + else if (shader.multitextureEnv == GL_ADD) + def.shader_type = Vk_Shader_Type::multi_texture_add; + else + ri.Error(ERR_FATAL, "Vulkan: could not create pipelines for q3 shader '%s'\n", shader.name); - def.clipping_plane = false; - def.mirror = false; - pStage->vk_pipeline = vk_find_pipeline(def); + def.clipping_plane = false; + def.mirror = false; + pStage->vk_pipeline = vk_find_pipeline(def); - def.clipping_plane = true; - def.mirror = false; - pStage->vk_portal_pipeline = vk_find_pipeline(def); + def.clipping_plane = true; + def.mirror = false; + pStage->vk_portal_pipeline = vk_find_pipeline(def); - def.clipping_plane = true; - def.mirror = true; - pStage->vk_mirror_pipeline = vk_find_pipeline(def); - } - } + def.clipping_plane = true; + def.mirror = true; + pStage->vk_mirror_pipeline = vk_find_pipeline(def); + } + } return GeneratePermanentShader(); } diff --git a/src/engine/renderer/tr_sky.c b/src/engine/renderer/tr_sky.c index 7bb9750..c13caff 100644 --- a/src/engine/renderer/tr_sky.c +++ b/src/engine/renderer/tr_sky.c @@ -450,53 +450,53 @@ static void DrawSkyBox( shader_t *shader ) sky_mins_subd, sky_maxs_subd ); - // VULKAN: draw skybox side - if (vk.active) { + // VULKAN: draw skybox side + if (vk.active) { GL_Bind(shader->sky.outerbox[sky_texorder[i]]); Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); - tess.numVertexes = 0; - tess.numIndexes = 0; + tess.numVertexes = 0; + tess.numIndexes = 0; - for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t < sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) - { - for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s < sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) - { - int ndx = tess.numVertexes; + for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t < sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) + { + for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s < sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) + { + int ndx = tess.numVertexes; - tess.indexes[ tess.numIndexes ] = ndx; - tess.indexes[ tess.numIndexes + 1 ] = ndx + 1; - tess.indexes[ tess.numIndexes + 2 ] = ndx + 2; + tess.indexes[ tess.numIndexes ] = ndx; + tess.indexes[ tess.numIndexes + 1 ] = ndx + 1; + tess.indexes[ tess.numIndexes + 2 ] = ndx + 2; - tess.indexes[ tess.numIndexes + 3 ] = ndx + 2; - tess.indexes[ tess.numIndexes + 4 ] = ndx + 1; - tess.indexes[ tess.numIndexes + 5 ] = ndx + 3; - tess.numIndexes += 6; + tess.indexes[ tess.numIndexes + 3 ] = ndx + 2; + tess.indexes[ tess.numIndexes + 4 ] = ndx + 1; + tess.indexes[ tess.numIndexes + 5 ] = ndx + 3; + tess.numIndexes += 6; - VectorCopy(s_skyPoints[t][s], tess.xyz[ndx]); - tess.svars.texcoords[0][ndx][0] = s_skyTexCoords[t][s][0]; - tess.svars.texcoords[0][ndx][1] = s_skyTexCoords[t][s][1]; + VectorCopy(s_skyPoints[t][s], tess.xyz[ndx]); + tess.svars.texcoords[0][ndx][0] = s_skyTexCoords[t][s][0]; + tess.svars.texcoords[0][ndx][1] = s_skyTexCoords[t][s][1]; - VectorCopy(s_skyPoints[t + 1][s], tess.xyz[ndx + 1]); - tess.svars.texcoords[0][ndx + 1][0] = s_skyTexCoords[t + 1][s][0]; - tess.svars.texcoords[0][ndx + 1][1] = s_skyTexCoords[t + 1][s][1]; + VectorCopy(s_skyPoints[t + 1][s], tess.xyz[ndx + 1]); + tess.svars.texcoords[0][ndx + 1][0] = s_skyTexCoords[t + 1][s][0]; + tess.svars.texcoords[0][ndx + 1][1] = s_skyTexCoords[t + 1][s][1]; - VectorCopy(s_skyPoints[t][s + 1], tess.xyz[ndx + 2]); - tess.svars.texcoords[0][ndx + 2][0] = s_skyTexCoords[t][s + 1][0]; - tess.svars.texcoords[0][ndx + 2][1] = s_skyTexCoords[t][s + 1][1]; + VectorCopy(s_skyPoints[t][s + 1], tess.xyz[ndx + 2]); + tess.svars.texcoords[0][ndx + 2][0] = s_skyTexCoords[t][s + 1][0]; + tess.svars.texcoords[0][ndx + 2][1] = s_skyTexCoords[t][s + 1][1]; - VectorCopy(s_skyPoints[t + 1][s + 1], tess.xyz[ndx + 3]); - tess.svars.texcoords[0][ndx + 3][0] = s_skyTexCoords[t + 1][s + 1][0]; - tess.svars.texcoords[0][ndx + 3][1] = s_skyTexCoords[t + 1][s + 1][1]; + VectorCopy(s_skyPoints[t + 1][s + 1], tess.xyz[ndx + 3]); + tess.svars.texcoords[0][ndx + 3][0] = s_skyTexCoords[t + 1][s + 1][0]; + tess.svars.texcoords[0][ndx + 3][1] = s_skyTexCoords[t + 1][s + 1][1]; - tess.numVertexes += 4; - } - } + tess.numVertexes += 4; + } + } - vk_bind_geometry(); - vk_shade_geometry(vk.skybox_pipeline, false, r_showsky->integer ? Vk_Depth_Range::force_zero : Vk_Depth_Range::force_one); - } + vk_bind_geometry(); + vk_shade_geometry(vk.skybox_pipeline, false, r_showsky->integer ? Vk_Depth_Range::force_zero : Vk_Depth_Range::force_one); + } } } diff --git a/src/engine/renderer/vk.cpp b/src/engine/renderer/vk.cpp index cc7241d..5ae0cf6 100644 --- a/src/engine/renderer/vk.cpp +++ b/src/engine/renderer/vk.cpp @@ -23,34 +23,34 @@ static const int VERTEX_BUFFER_SIZE = XYZ_SIZE + COLOR_SIZE + ST0_SIZE + ST1_SIZ static const int INDEX_BUFFER_SIZE = 2 * 1024 * 1024; static const std::vector instance_extensions = { - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_WIN32_SURFACE_EXTENSION_NAME + VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; static const std::vector device_extensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME + VK_KHR_SWAPCHAIN_EXTENSION_NAME }; static bool is_extension_available(const std::vector& properties, const char* extension_name) { - for (const auto& property : properties) { - if (strcmp(property.extensionName, extension_name) == 0) - return true; - } - return false; + for (const auto& property : properties) { + if (strcmp(property.extensionName, extension_name) == 0) + return true; + } + return false; } static uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t memory_type_bits, VkMemoryPropertyFlags properties) { - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties); + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties); - for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) { - if ((memory_type_bits & (1 << i)) != 0 && - (memory_properties.memoryTypes[i].propertyFlags & properties) == properties) { - return i; - } - } - ri.Error(ERR_FATAL, "Vulkan error: failed to find matching memory type with requested properties"); - return -1; + for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) { + if ((memory_type_bits & (1 << i)) != 0 && + (memory_properties.memoryTypes[i].propertyFlags & properties) == properties) { + return i; + } + } + ri.Error(ERR_FATAL, "Vulkan error: failed to find matching memory type with requested properties"); + return -1; } static VkFormat find_depth_format(VkPhysicalDevice physical_device) { @@ -81,28 +81,28 @@ static VkFormat find_depth_format(VkPhysicalDevice physical_device) { } static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevice device, VkSurfaceKHR surface, VkSurfaceFormatKHR surface_format) { - VkSurfaceCapabilitiesKHR surface_caps; - VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surface_caps)); + VkSurfaceCapabilitiesKHR surface_caps; + VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surface_caps)); - VkExtent2D image_extent = surface_caps.currentExtent; - if (image_extent.width == 0xffffffff && image_extent.height == 0xffffffff) { - image_extent.width = std::min(surface_caps.maxImageExtent.width, std::max(surface_caps.minImageExtent.width, 640u)); - image_extent.height = std::min(surface_caps.maxImageExtent.height, std::max(surface_caps.minImageExtent.height, 480u)); - } + VkExtent2D image_extent = surface_caps.currentExtent; + if (image_extent.width == 0xffffffff && image_extent.height == 0xffffffff) { + image_extent.width = std::min(surface_caps.maxImageExtent.width, std::max(surface_caps.minImageExtent.width, 640u)); + image_extent.height = std::min(surface_caps.maxImageExtent.height, std::max(surface_caps.minImageExtent.height, 480u)); + } - // VK_IMAGE_USAGE_TRANSFER_DST_BIT is required by image clear operations. - if ((surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) - ri.Error(ERR_FATAL, "create_swapchain: VK_IMAGE_USAGE_TRANSFER_DST_BIT is not supported by the swapchain"); + // VK_IMAGE_USAGE_TRANSFER_DST_BIT is required by image clear operations. + if ((surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) + ri.Error(ERR_FATAL, "create_swapchain: VK_IMAGE_USAGE_TRANSFER_DST_BIT is not supported by the swapchain"); // VK_IMAGE_USAGE_TRANSFER_SRC_BIT is required in order to take screenshots. if ((surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0) ri.Error(ERR_FATAL, "create_swapchain: VK_IMAGE_USAGE_TRANSFER_SRC_BIT is not supported by the swapchain"); - // determine present mode and swapchain image count - uint32_t present_mode_count; - VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, nullptr)); - std::vector present_modes(present_mode_count); - VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, present_modes.data())); + // determine present mode and swapchain image count + uint32_t present_mode_count; + VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, nullptr)); + std::vector present_modes(present_mode_count); + VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, present_modes.data())); bool mailbox_supported = false; bool immediate_supported = false; @@ -129,238 +129,238 @@ static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevic image_count = surface_caps.minImageCount; } - // create swap chain - VkSwapchainCreateInfoKHR desc; - desc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - desc.pNext = nullptr; - desc.flags = 0; - desc.surface = surface; - desc.minImageCount = image_count; - desc.imageFormat = surface_format.format; - desc.imageColorSpace = surface_format.colorSpace; - desc.imageExtent = image_extent; - desc.imageArrayLayers = 1; - desc.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - desc.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - desc.queueFamilyIndexCount = 0; - desc.pQueueFamilyIndices = nullptr; - desc.preTransform = surface_caps.currentTransform; - desc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - desc.presentMode = present_mode; - desc.clipped = VK_TRUE; - desc.oldSwapchain = VK_NULL_HANDLE; + // create swap chain + VkSwapchainCreateInfoKHR desc; + desc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + desc.pNext = nullptr; + desc.flags = 0; + desc.surface = surface; + desc.minImageCount = image_count; + desc.imageFormat = surface_format.format; + desc.imageColorSpace = surface_format.colorSpace; + desc.imageExtent = image_extent; + desc.imageArrayLayers = 1; + desc.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + desc.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + desc.queueFamilyIndexCount = 0; + desc.pQueueFamilyIndices = nullptr; + desc.preTransform = surface_caps.currentTransform; + desc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + desc.presentMode = present_mode; + desc.clipped = VK_TRUE; + desc.oldSwapchain = VK_NULL_HANDLE; - VkSwapchainKHR swapchain; - VK_CHECK(vkCreateSwapchainKHR(device, &desc, nullptr, &swapchain)); - return swapchain; + VkSwapchainKHR swapchain; + VK_CHECK(vkCreateSwapchainKHR(device, &desc, nullptr, &swapchain)); + return swapchain; } static VkRenderPass create_render_pass(VkDevice device, VkFormat color_format, VkFormat depth_format) { - VkAttachmentDescription attachments[2]; - attachments[0].flags = 0; + VkAttachmentDescription attachments[2]; + attachments[0].flags = 0; attachments[0].format = color_format; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - attachments[1].flags = 0; + attachments[1].flags = 0; attachments[1].format = depth_format; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - VkAttachmentReference color_attachment_ref; - color_attachment_ref.attachment = 0; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference color_attachment_ref; + color_attachment_ref.attachment = 0; + color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference depth_attachment_ref; - depth_attachment_ref.attachment = 1; - depth_attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + VkAttachmentReference depth_attachment_ref; + depth_attachment_ref.attachment = 1; + depth_attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - VkSubpassDescription subpass; - subpass.flags = 0; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = nullptr; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_ref; - subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = &depth_attachment_ref; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = nullptr; + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_attachment_ref; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = &depth_attachment_ref; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; - VkRenderPassCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; + VkRenderPassCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; desc.attachmentCount = sizeof(attachments) / sizeof(attachments[0]); desc.pAttachments = attachments; - desc.subpassCount = 1; - desc.pSubpasses = &subpass; - desc.dependencyCount = 0; - desc.pDependencies = nullptr; + desc.subpassCount = 1; + desc.pSubpasses = &subpass; + desc.dependencyCount = 0; + desc.pDependencies = nullptr; - VkRenderPass render_pass; - VK_CHECK(vkCreateRenderPass(device, &desc, nullptr, &render_pass)); - return render_pass; + VkRenderPass render_pass; + VK_CHECK(vkCreateRenderPass(device, &desc, nullptr, &render_pass)); + return render_pass; } static void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::function recorder) { - VkCommandBufferAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.commandPool = command_pool; - alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - alloc_info.commandBufferCount = 1; + VkCommandBufferAllocateInfo alloc_info; + alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.commandPool = command_pool; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandBufferCount = 1; - VkCommandBuffer command_buffer; - VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &command_buffer)); + VkCommandBuffer command_buffer; + VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &command_buffer)); - VkCommandBufferBeginInfo begin_info; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.pNext = nullptr; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - begin_info.pInheritanceInfo = nullptr; + VkCommandBufferBeginInfo begin_info; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.pNext = nullptr; + begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + begin_info.pInheritanceInfo = nullptr; - VK_CHECK(vkBeginCommandBuffer(command_buffer, &begin_info)); - recorder(command_buffer); - VK_CHECK(vkEndCommandBuffer(command_buffer)); + VK_CHECK(vkBeginCommandBuffer(command_buffer, &begin_info)); + recorder(command_buffer); + VK_CHECK(vkEndCommandBuffer(command_buffer)); - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = nullptr; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = nullptr; - submit_info.pWaitDstStageMask = nullptr; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; + VkSubmitInfo submit_info; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + submit_info.signalSemaphoreCount = 0; + submit_info.pSignalSemaphores = nullptr; - VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE)); - VK_CHECK(vkQueueWaitIdle(queue)); - vkFreeCommandBuffers(vk.device, command_pool, 1, &command_buffer); + VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE)); + VK_CHECK(vkQueueWaitIdle(queue)); + vkFreeCommandBuffers(vk.device, command_pool, 1, &command_buffer); } static void record_image_layout_transition(VkCommandBuffer command_buffer, VkImage image, VkImageAspectFlags image_aspect_flags, - VkAccessFlags src_access_flags, VkImageLayout old_layout, VkAccessFlags dst_access_flags, VkImageLayout new_layout) { + VkAccessFlags src_access_flags, VkImageLayout old_layout, VkAccessFlags dst_access_flags, VkImageLayout new_layout) { - VkImageMemoryBarrier barrier; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.pNext = nullptr; - barrier.srcAccessMask = src_access_flags; - barrier.dstAccessMask = dst_access_flags; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; + VkImageMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = src_access_flags; + barrier.dstAccessMask = dst_access_flags; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; barrier.subresourceRange.aspectMask = image_aspect_flags; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, - 0, nullptr, 0, nullptr, 1, &barrier); + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, + 0, nullptr, 0, nullptr, 1, &barrier); } static void allocate_and_bind_image_memory(VkImage image) { - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(vk.device, image, &memory_requirements); + VkMemoryRequirements memory_requirements; + vkGetImageMemoryRequirements(vk.device, image, &memory_requirements); - if (memory_requirements.size > IMAGE_CHUNK_SIZE) { - ri.Error(ERR_FATAL, "Vulkan: could not allocate memory, image is too large."); - } + if (memory_requirements.size > IMAGE_CHUNK_SIZE) { + ri.Error(ERR_FATAL, "Vulkan: could not allocate memory, image is too large."); + } - Vk_Resources::Chunk* chunk = nullptr; + Vk_Resources::Chunk* chunk = nullptr; - // Try to find an existing chunk of sufficient capacity. - const auto mask = ~(memory_requirements.alignment - 1); - for (int i = 0; i < vk_resources.num_image_chunks; i++) { - // ensure that memory region has proper alignment - VkDeviceSize offset = (vk_resources.image_chunks[i].used + memory_requirements.alignment - 1) & mask; + // Try to find an existing chunk of sufficient capacity. + const auto mask = ~(memory_requirements.alignment - 1); + for (int i = 0; i < vk_resources.num_image_chunks; i++) { + // ensure that memory region has proper alignment + VkDeviceSize offset = (vk_resources.image_chunks[i].used + memory_requirements.alignment - 1) & mask; - if (offset + memory_requirements.size <= IMAGE_CHUNK_SIZE) { - chunk = &vk_resources.image_chunks[i]; - chunk->used = offset + memory_requirements.size; - break; - } - } + if (offset + memory_requirements.size <= IMAGE_CHUNK_SIZE) { + chunk = &vk_resources.image_chunks[i]; + chunk->used = offset + memory_requirements.size; + break; + } + } - // Allocate a new chunk in case we couldn't find suitable existing chunk. - if (chunk == nullptr) { - if (vk_resources.num_image_chunks >= MAX_IMAGE_CHUNKS) { - ri.Error(ERR_FATAL, "Vulkan: image chunk limit has been reached"); - } + // Allocate a new chunk in case we couldn't find suitable existing chunk. + if (chunk == nullptr) { + if (vk_resources.num_image_chunks >= MAX_IMAGE_CHUNKS) { + ri.Error(ERR_FATAL, "Vulkan: image chunk limit has been reached"); + } - VkMemoryAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.allocationSize = IMAGE_CHUNK_SIZE; - alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VkMemoryAllocateInfo alloc_info; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.allocationSize = IMAGE_CHUNK_SIZE; + alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VkDeviceMemory memory; - VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &memory)); + VkDeviceMemory memory; + VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &memory)); - chunk = &vk_resources.image_chunks[vk_resources.num_image_chunks]; - vk_resources.num_image_chunks++; - chunk->memory = memory; - chunk->used = memory_requirements.size; - } + chunk = &vk_resources.image_chunks[vk_resources.num_image_chunks]; + vk_resources.num_image_chunks++; + chunk->memory = memory; + chunk->used = memory_requirements.size; + } - VK_CHECK(vkBindImageMemory(vk.device, image, chunk->memory, chunk->used - memory_requirements.size)); + VK_CHECK(vkBindImageMemory(vk.device, image, chunk->memory, chunk->used - memory_requirements.size)); } static void ensure_staging_buffer_allocation(VkDeviceSize size) { - if (vk_resources.staging_buffer_size >= size) - return; + if (vk_resources.staging_buffer_size >= size) + return; - if (vk_resources.staging_buffer != VK_NULL_HANDLE) - vkDestroyBuffer(vk.device, vk_resources.staging_buffer, nullptr); + if (vk_resources.staging_buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vk.device, vk_resources.staging_buffer, nullptr); - if (vk_resources.staging_buffer_memory != VK_NULL_HANDLE) - vkFreeMemory(vk.device, vk_resources.staging_buffer_memory, nullptr); + if (vk_resources.staging_buffer_memory != VK_NULL_HANDLE) + vkFreeMemory(vk.device, vk_resources.staging_buffer_memory, nullptr); - vk_resources.staging_buffer_size = size; + vk_resources.staging_buffer_size = size; - VkBufferCreateInfo buffer_desc; - buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_desc.pNext = nullptr; - buffer_desc.flags = 0; - buffer_desc.size = size; - buffer_desc.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - buffer_desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buffer_desc.queueFamilyIndexCount = 0; - buffer_desc.pQueueFamilyIndices = nullptr; - VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &vk_resources.staging_buffer)); + VkBufferCreateInfo buffer_desc; + buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_desc.pNext = nullptr; + buffer_desc.flags = 0; + buffer_desc.size = size; + buffer_desc.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_desc.queueFamilyIndexCount = 0; + buffer_desc.pQueueFamilyIndices = nullptr; + VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &vk_resources.staging_buffer)); - VkMemoryRequirements memory_requirements; - vkGetBufferMemoryRequirements(vk.device, vk_resources.staging_buffer, &memory_requirements); + VkMemoryRequirements memory_requirements; + vkGetBufferMemoryRequirements(vk.device, vk_resources.staging_buffer, &memory_requirements); - uint32_t memory_type = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + uint32_t memory_type = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VkMemoryAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.allocationSize = memory_requirements.size; - alloc_info.memoryTypeIndex = memory_type; - VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &vk_resources.staging_buffer_memory)); - VK_CHECK(vkBindBufferMemory(vk.device, vk_resources.staging_buffer, vk_resources.staging_buffer_memory, 0)); + VkMemoryAllocateInfo alloc_info; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.allocationSize = memory_requirements.size; + alloc_info.memoryTypeIndex = memory_type; + VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &vk_resources.staging_buffer_memory)); + VK_CHECK(vkBindBufferMemory(vk.device, vk_resources.staging_buffer, vk_resources.staging_buffer_memory, 0)); - void* data; - VK_CHECK(vkMapMemory(vk.device, vk_resources.staging_buffer_memory, 0, VK_WHOLE_SIZE, 0, &data)); - vk_resources.staging_buffer_ptr = (byte*)data; + void* data; + VK_CHECK(vkMapMemory(vk.device, vk_resources.staging_buffer_memory, 0, VK_WHOLE_SIZE, 0, &data)); + vk_resources.staging_buffer_ptr = (byte*)data; } VkPipeline create_pipeline(const Vk_Pipeline_Def&); @@ -708,357 +708,357 @@ void vk_initialize() { if (features.fillModeNonSolid == VK_FALSE) ri.Error(ERR_FATAL, "vk_create_instance: fillModeNonSolid feature is not supported"); - vkGetDeviceQueue(vk.device, vk.queue_family_index, 0, &vk.queue); + vkGetDeviceQueue(vk.device, vk.queue_family_index, 0, &vk.queue); - vk.swapchain = create_swapchain(vk.physical_device, vk.device, vk.surface, vk.surface_format); + vk.swapchain = create_swapchain(vk.physical_device, vk.device, vk.surface, vk.surface_format); - VK_CHECK(vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &vk.swapchain_image_count, nullptr)); + VK_CHECK(vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &vk.swapchain_image_count, nullptr)); - if (vk.swapchain_image_count > MAX_SWAPCHAIN_IMAGES) - ri.Error( ERR_FATAL, "initialize_vulkan: swapchain image count (%d) exceeded limit (%d)", vk.swapchain_image_count, MAX_SWAPCHAIN_IMAGES ); + if (vk.swapchain_image_count > MAX_SWAPCHAIN_IMAGES) + ri.Error( ERR_FATAL, "initialize_vulkan: swapchain image count (%d) exceeded limit (%d)", vk.swapchain_image_count, MAX_SWAPCHAIN_IMAGES ); - VK_CHECK(vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &vk.swapchain_image_count, vk.swapchain_images)); + VK_CHECK(vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &vk.swapchain_image_count, vk.swapchain_images)); - for (std::size_t i = 0; i < vk.swapchain_image_count; i++) { - VkImageViewCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.image = vk.swapchain_images[i]; - desc.viewType = VK_IMAGE_VIEW_TYPE_2D; - desc.format = vk.surface_format.format; - desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - desc.subresourceRange.baseMipLevel = 0; - desc.subresourceRange.levelCount = 1; - desc.subresourceRange.baseArrayLayer = 0; - desc.subresourceRange.layerCount = 1; - VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &vk.swapchain_image_views[i])); - } + for (std::size_t i = 0; i < vk.swapchain_image_count; i++) { + VkImageViewCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.image = vk.swapchain_images[i]; + desc.viewType = VK_IMAGE_VIEW_TYPE_2D; + desc.format = vk.surface_format.format; + desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + desc.subresourceRange.baseMipLevel = 0; + desc.subresourceRange.levelCount = 1; + desc.subresourceRange.baseArrayLayer = 0; + desc.subresourceRange.layerCount = 1; + VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &vk.swapchain_image_views[i])); + } - { - VkCommandPoolCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - desc.queueFamilyIndex = vk.queue_family_index; + { + VkCommandPoolCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + desc.queueFamilyIndex = vk.queue_family_index; - VK_CHECK(vkCreateCommandPool(vk.device, &desc, nullptr, &vk.command_pool)); - } + VK_CHECK(vkCreateCommandPool(vk.device, &desc, nullptr, &vk.command_pool)); + } - { - VkCommandBufferAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.commandPool = vk.command_pool; - alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - alloc_info.commandBufferCount = 1; - VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &vk.command_buffer)); - } + { + VkCommandBufferAllocateInfo alloc_info; + alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.commandPool = vk.command_pool; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandBufferCount = 1; + VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &vk.command_buffer)); + } - // - // Depth attachment image. - // - { - VkFormat depth_format = find_depth_format(vk.physical_device); + // + // Depth attachment image. + // + { + VkFormat depth_format = find_depth_format(vk.physical_device); - // create depth image - { - VkImageCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.imageType = VK_IMAGE_TYPE_2D; - desc.format = depth_format; - desc.extent.width = glConfig.vidWidth; - desc.extent.height = glConfig.vidHeight; - desc.extent.depth = 1; - desc.mipLevels = 1; - desc.arrayLayers = 1; - desc.samples = VK_SAMPLE_COUNT_1_BIT; - desc.tiling = VK_IMAGE_TILING_OPTIMAL; - desc.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - desc.queueFamilyIndexCount = 0; - desc.pQueueFamilyIndices = nullptr; - desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &vk.depth_image)); - } + // create depth image + { + VkImageCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.imageType = VK_IMAGE_TYPE_2D; + desc.format = depth_format; + desc.extent.width = glConfig.vidWidth; + desc.extent.height = glConfig.vidHeight; + desc.extent.depth = 1; + desc.mipLevels = 1; + desc.arrayLayers = 1; + desc.samples = VK_SAMPLE_COUNT_1_BIT; + desc.tiling = VK_IMAGE_TILING_OPTIMAL; + desc.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + desc.queueFamilyIndexCount = 0; + desc.pQueueFamilyIndices = nullptr; + desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &vk.depth_image)); + } - // allocate depth image memory - { - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(vk.device, vk.depth_image, &memory_requirements); + // allocate depth image memory + { + VkMemoryRequirements memory_requirements; + vkGetImageMemoryRequirements(vk.device, vk.depth_image, &memory_requirements); - VkMemoryAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.allocationSize = memory_requirements.size; - alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VkMemoryAllocateInfo alloc_info; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.allocationSize = memory_requirements.size; + alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &vk.depth_image_memory)); - VK_CHECK(vkBindImageMemory(vk.device, vk.depth_image, vk.depth_image_memory, 0)); - } + VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &vk.depth_image_memory)); + VK_CHECK(vkBindImageMemory(vk.device, vk.depth_image, vk.depth_image_memory, 0)); + } - // create depth image view - { - VkImageViewCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.image = vk.depth_image; - desc.viewType = VK_IMAGE_VIEW_TYPE_2D; - desc.format = depth_format; - desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - desc.subresourceRange.baseMipLevel = 0; - desc.subresourceRange.levelCount = 1; - desc.subresourceRange.baseArrayLayer = 0; - desc.subresourceRange.layerCount = 1; - VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &vk.depth_image_view)); - } + // create depth image view + { + VkImageViewCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.image = vk.depth_image; + desc.viewType = VK_IMAGE_VIEW_TYPE_2D; + desc.format = depth_format; + desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + desc.subresourceRange.baseMipLevel = 0; + desc.subresourceRange.levelCount = 1; + desc.subresourceRange.baseArrayLayer = 0; + desc.subresourceRange.layerCount = 1; + VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &vk.depth_image_view)); + } VkImageAspectFlags image_aspect_flags = VK_IMAGE_ASPECT_DEPTH_BIT; if (r_stencilbits->integer) image_aspect_flags |= VK_IMAGE_ASPECT_STENCIL_BIT; - record_and_run_commands(vk.command_pool, vk.queue, [&image_aspect_flags](VkCommandBuffer command_buffer) { - record_image_layout_transition(command_buffer, vk.depth_image, image_aspect_flags, 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); - }); - } + record_and_run_commands(vk.command_pool, vk.queue, [&image_aspect_flags](VkCommandBuffer command_buffer) { + record_image_layout_transition(command_buffer, vk.depth_image, image_aspect_flags, 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); + }); + } - // - // Renderpass. - // - { - VkFormat depth_format = find_depth_format(vk.physical_device); - vk.render_pass = create_render_pass(vk.device, vk.surface_format.format, depth_format); - } + // + // Renderpass. + // + { + VkFormat depth_format = find_depth_format(vk.physical_device); + vk.render_pass = create_render_pass(vk.device, vk.surface_format.format, depth_format); + } - // - // Framebuffers for each swapchain image. - // - { - VkImageView attachments[2] = {VK_NULL_HANDLE, vk.depth_image_view}; + // + // Framebuffers for each swapchain image. + // + { + VkImageView attachments[2] = {VK_NULL_HANDLE, vk.depth_image_view}; - VkFramebufferCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.renderPass = vk.render_pass; - desc.attachmentCount = 2; - desc.pAttachments = attachments; - desc.width = glConfig.vidWidth; - desc.height = glConfig.vidHeight; - desc.layers = 1; + VkFramebufferCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.renderPass = vk.render_pass; + desc.attachmentCount = 2; + desc.pAttachments = attachments; + desc.width = glConfig.vidWidth; + desc.height = glConfig.vidHeight; + desc.layers = 1; - for (uint32_t i = 0; i < vk.swapchain_image_count; i++) { - attachments[0] = vk.swapchain_image_views[i]; // set color attachment - VK_CHECK(vkCreateFramebuffer(vk.device, &desc, nullptr, &vk.framebuffers[i])); - } - } + for (uint32_t i = 0; i < vk.swapchain_image_count; i++) { + attachments[0] = vk.swapchain_image_views[i]; // set color attachment + VK_CHECK(vkCreateFramebuffer(vk.device, &desc, nullptr, &vk.framebuffers[i])); + } + } - // - // Descriptor pool. - // - { - VkDescriptorPoolSize pool_size; - pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - pool_size.descriptorCount = MAX_DRAWIMAGES; + // + // Descriptor pool. + // + { + VkDescriptorPoolSize pool_size; + pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + pool_size.descriptorCount = MAX_DRAWIMAGES; - VkDescriptorPoolCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // used by the cinematic images - desc.maxSets = MAX_DRAWIMAGES; - desc.poolSizeCount = 1; - desc.pPoolSizes = &pool_size; + VkDescriptorPoolCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // used by the cinematic images + desc.maxSets = MAX_DRAWIMAGES; + desc.poolSizeCount = 1; + desc.pPoolSizes = &pool_size; - VK_CHECK(vkCreateDescriptorPool(vk.device, &desc, nullptr, &vk.descriptor_pool)); - } + VK_CHECK(vkCreateDescriptorPool(vk.device, &desc, nullptr, &vk.descriptor_pool)); + } - // - // Descriptor set layout. - // - { - VkDescriptorSetLayoutBinding descriptor_binding; - descriptor_binding.binding = 0; - descriptor_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_binding.descriptorCount = 1; - descriptor_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - descriptor_binding.pImmutableSamplers = nullptr; + // + // Descriptor set layout. + // + { + VkDescriptorSetLayoutBinding descriptor_binding; + descriptor_binding.binding = 0; + descriptor_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptor_binding.descriptorCount = 1; + descriptor_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + descriptor_binding.pImmutableSamplers = nullptr; - VkDescriptorSetLayoutCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.bindingCount = 1; - desc.pBindings = &descriptor_binding; + VkDescriptorSetLayoutCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.bindingCount = 1; + desc.pBindings = &descriptor_binding; - VK_CHECK(vkCreateDescriptorSetLayout(vk.device, &desc, nullptr, &vk.set_layout)); - } + VK_CHECK(vkCreateDescriptorSetLayout(vk.device, &desc, nullptr, &vk.set_layout)); + } - // - // Pipeline layout. - // - { - VkPushConstantRange push_range; - push_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - push_range.offset = 0; - push_range.size = 128; // 32 floats + // + // Pipeline layout. + // + { + VkPushConstantRange push_range; + push_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_range.offset = 0; + push_range.size = 128; // 32 floats - VkDescriptorSetLayout set_layouts[2] = {vk.set_layout, vk.set_layout}; + VkDescriptorSetLayout set_layouts[2] = {vk.set_layout, vk.set_layout}; - VkPipelineLayoutCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.setLayoutCount = 2; - desc.pSetLayouts = set_layouts; - desc.pushConstantRangeCount = 1; - desc.pPushConstantRanges = &push_range; + VkPipelineLayoutCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.setLayoutCount = 2; + desc.pSetLayouts = set_layouts; + desc.pushConstantRangeCount = 1; + desc.pPushConstantRanges = &push_range; - VK_CHECK(vkCreatePipelineLayout(vk.device, &desc, nullptr, &vk.pipeline_layout)); - } + VK_CHECK(vkCreatePipelineLayout(vk.device, &desc, nullptr, &vk.pipeline_layout)); + } - // - // Geometry buffers. - // - { - VkBufferCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - desc.queueFamilyIndexCount = 0; - desc.pQueueFamilyIndices = nullptr; + // + // Geometry buffers. + // + { + VkBufferCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + desc.queueFamilyIndexCount = 0; + desc.pQueueFamilyIndices = nullptr; - desc.size = VERTEX_BUFFER_SIZE; - desc.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - VK_CHECK(vkCreateBuffer(vk.device, &desc, nullptr, &vk.vertex_buffer)); + desc.size = VERTEX_BUFFER_SIZE; + desc.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + VK_CHECK(vkCreateBuffer(vk.device, &desc, nullptr, &vk.vertex_buffer)); - desc.size = INDEX_BUFFER_SIZE; - desc.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - VK_CHECK(vkCreateBuffer(vk.device, &desc, nullptr, &vk.index_buffer)); + desc.size = INDEX_BUFFER_SIZE; + desc.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + VK_CHECK(vkCreateBuffer(vk.device, &desc, nullptr, &vk.index_buffer)); - VkMemoryRequirements vb_memory_requirements; - vkGetBufferMemoryRequirements(vk.device, vk.vertex_buffer, &vb_memory_requirements); + VkMemoryRequirements vb_memory_requirements; + vkGetBufferMemoryRequirements(vk.device, vk.vertex_buffer, &vb_memory_requirements); - VkMemoryRequirements ib_memory_requirements; - vkGetBufferMemoryRequirements(vk.device, vk.index_buffer, &ib_memory_requirements); + VkMemoryRequirements ib_memory_requirements; + vkGetBufferMemoryRequirements(vk.device, vk.index_buffer, &ib_memory_requirements); - VkDeviceSize mask = ~(ib_memory_requirements.alignment - 1); - VkDeviceSize index_buffer_offset = (vb_memory_requirements.size + ib_memory_requirements.alignment - 1) & mask; + VkDeviceSize mask = ~(ib_memory_requirements.alignment - 1); + VkDeviceSize index_buffer_offset = (vb_memory_requirements.size + ib_memory_requirements.alignment - 1) & mask; - uint32_t memory_type_bits = vb_memory_requirements.memoryTypeBits & ib_memory_requirements.memoryTypeBits; - uint32_t memory_type = find_memory_type(vk.physical_device, memory_type_bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + uint32_t memory_type_bits = vb_memory_requirements.memoryTypeBits & ib_memory_requirements.memoryTypeBits; + uint32_t memory_type = find_memory_type(vk.physical_device, memory_type_bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VkMemoryAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.allocationSize = index_buffer_offset + ib_memory_requirements.size; - alloc_info.memoryTypeIndex = memory_type; - VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &vk.geometry_buffer_memory)); + VkMemoryAllocateInfo alloc_info; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.allocationSize = index_buffer_offset + ib_memory_requirements.size; + alloc_info.memoryTypeIndex = memory_type; + VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &vk.geometry_buffer_memory)); - vkBindBufferMemory(vk.device, vk.vertex_buffer, vk.geometry_buffer_memory, 0); - vkBindBufferMemory(vk.device, vk.index_buffer, vk.geometry_buffer_memory, index_buffer_offset); + vkBindBufferMemory(vk.device, vk.vertex_buffer, vk.geometry_buffer_memory, 0); + vkBindBufferMemory(vk.device, vk.index_buffer, vk.geometry_buffer_memory, index_buffer_offset); - void* data; - VK_CHECK(vkMapMemory(vk.device, vk.geometry_buffer_memory, 0, VK_WHOLE_SIZE, 0, &data)); - vk.vertex_buffer_ptr = (byte*)data; - vk.index_buffer_ptr = (byte*)data + index_buffer_offset; - } + void* data; + VK_CHECK(vkMapMemory(vk.device, vk.geometry_buffer_memory, 0, VK_WHOLE_SIZE, 0, &data)); + vk.vertex_buffer_ptr = (byte*)data; + vk.index_buffer_ptr = (byte*)data + index_buffer_offset; + } - // - // Sync primitives. - // - { - VkSemaphoreCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; + // + // Sync primitives. + // + { + VkSemaphoreCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; - VK_CHECK(vkCreateSemaphore(vk.device, &desc, nullptr, &vk.image_acquired)); - VK_CHECK(vkCreateSemaphore(vk.device, &desc, nullptr, &vk.rendering_finished)); + VK_CHECK(vkCreateSemaphore(vk.device, &desc, nullptr, &vk.image_acquired)); + VK_CHECK(vkCreateSemaphore(vk.device, &desc, nullptr, &vk.rendering_finished)); - VkFenceCreateInfo fence_desc; - fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_desc.pNext = nullptr; - fence_desc.flags = VK_FENCE_CREATE_SIGNALED_BIT; - VK_CHECK(vkCreateFence(vk.device, &fence_desc, nullptr, &vk.rendering_finished_fence)); - } + VkFenceCreateInfo fence_desc; + fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_desc.pNext = nullptr; + fence_desc.flags = VK_FENCE_CREATE_SIGNALED_BIT; + VK_CHECK(vkCreateFence(vk.device, &fence_desc, nullptr, &vk.rendering_finished_fence)); + } - // - // Shader modules. - // - { - auto create_shader_module = [](uint8_t* bytes, int count) { - if (count % 4 != 0) { - ri.Error(ERR_FATAL, "Vulkan error: SPIR-V binary buffer size is not multiple of 4"); - } - VkShaderModuleCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.codeSize = count; - desc.pCode = reinterpret_cast(bytes); - - VkShaderModule module; - VK_CHECK(vkCreateShaderModule(vk.device, &desc, nullptr, &module)); - return module; - }; + // + // Shader modules. + // + { + auto create_shader_module = [](uint8_t* bytes, int count) { + if (count % 4 != 0) { + ri.Error(ERR_FATAL, "Vulkan error: SPIR-V binary buffer size is not multiple of 4"); + } + VkShaderModuleCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.codeSize = count; + desc.pCode = reinterpret_cast(bytes); + + VkShaderModule module; + VK_CHECK(vkCreateShaderModule(vk.device, &desc, nullptr, &module)); + return module; + }; - extern unsigned char single_texture_vert_spv[]; - extern long long single_texture_vert_spv_size; - vk.single_texture_vs = create_shader_module(single_texture_vert_spv, single_texture_vert_spv_size); + extern unsigned char single_texture_vert_spv[]; + extern long long single_texture_vert_spv_size; + vk.single_texture_vs = create_shader_module(single_texture_vert_spv, single_texture_vert_spv_size); - extern unsigned char single_texture_clipping_plane_vert_spv[]; - extern long long single_texture_clipping_plane_vert_spv_size; - vk.single_texture_clipping_plane_vs = create_shader_module(single_texture_clipping_plane_vert_spv, single_texture_clipping_plane_vert_spv_size); + extern unsigned char single_texture_clipping_plane_vert_spv[]; + extern long long single_texture_clipping_plane_vert_spv_size; + vk.single_texture_clipping_plane_vs = create_shader_module(single_texture_clipping_plane_vert_spv, single_texture_clipping_plane_vert_spv_size); - extern unsigned char single_texture_frag_spv[]; - extern long long single_texture_frag_spv_size; - vk.single_texture_fs = create_shader_module(single_texture_frag_spv, single_texture_frag_spv_size); + extern unsigned char single_texture_frag_spv[]; + extern long long single_texture_frag_spv_size; + vk.single_texture_fs = create_shader_module(single_texture_frag_spv, single_texture_frag_spv_size); - extern unsigned char multi_texture_vert_spv[]; - extern long long multi_texture_vert_spv_size; - vk.multi_texture_vs = create_shader_module(multi_texture_vert_spv, multi_texture_vert_spv_size); + extern unsigned char multi_texture_vert_spv[]; + extern long long multi_texture_vert_spv_size; + vk.multi_texture_vs = create_shader_module(multi_texture_vert_spv, multi_texture_vert_spv_size); - extern unsigned char multi_texture_clipping_plane_vert_spv[]; - extern long long multi_texture_clipping_plane_vert_spv_size; - vk.multi_texture_clipping_plane_vs = create_shader_module(multi_texture_clipping_plane_vert_spv, multi_texture_clipping_plane_vert_spv_size); + extern unsigned char multi_texture_clipping_plane_vert_spv[]; + extern long long multi_texture_clipping_plane_vert_spv_size; + vk.multi_texture_clipping_plane_vs = create_shader_module(multi_texture_clipping_plane_vert_spv, multi_texture_clipping_plane_vert_spv_size); - extern unsigned char multi_texture_mul_frag_spv[]; - extern long long multi_texture_mul_frag_spv_size; - vk.multi_texture_mul_fs = create_shader_module(multi_texture_mul_frag_spv, multi_texture_mul_frag_spv_size); + extern unsigned char multi_texture_mul_frag_spv[]; + extern long long multi_texture_mul_frag_spv_size; + vk.multi_texture_mul_fs = create_shader_module(multi_texture_mul_frag_spv, multi_texture_mul_frag_spv_size); - extern unsigned char multi_texture_add_frag_spv[]; - extern long long multi_texture_add_frag_spv_size; - vk.multi_texture_add_fs = create_shader_module(multi_texture_add_frag_spv, multi_texture_add_frag_spv_size); - } + extern unsigned char multi_texture_add_frag_spv[]; + extern long long multi_texture_add_frag_spv_size; + vk.multi_texture_add_fs = create_shader_module(multi_texture_add_frag_spv, multi_texture_add_frag_spv_size); + } - // - // Standard pipelines. - // - { - // skybox - { - Vk_Pipeline_Def def; - def.shader_type = Vk_Shader_Type::single_texture; - def.state_bits = 0; - def.face_culling = CT_FRONT_SIDED; - def.polygon_offset = false; - def.clipping_plane = false; - def.mirror = false; - vk.skybox_pipeline = create_pipeline(def); - } + // + // Standard pipelines. + // + { + // skybox + { + Vk_Pipeline_Def def; + def.shader_type = Vk_Shader_Type::single_texture; + def.state_bits = 0; + def.face_culling = CT_FRONT_SIDED; + def.polygon_offset = false; + def.clipping_plane = false; + def.mirror = false; + vk.skybox_pipeline = create_pipeline(def); + } // Q3 stencil shadows { @@ -1095,42 +1095,42 @@ void vk_initialize() { } } - // fog and dlights - { - Vk_Pipeline_Def def; - def.shader_type = Vk_Shader_Type::single_texture; - def.clipping_plane = false; - def.mirror = false; + // fog and dlights + { + Vk_Pipeline_Def def; + def.shader_type = Vk_Shader_Type::single_texture; + def.clipping_plane = false; + def.mirror = false; - unsigned int fog_state_bits[2] = { - GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL, - GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA - }; - unsigned int dlight_state_bits[2] = { - GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL, - GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL - }; - bool polygon_offset[2] = {false, true}; + unsigned int fog_state_bits[2] = { + GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL, + GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA + }; + unsigned int dlight_state_bits[2] = { + GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL, + GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL + }; + bool polygon_offset[2] = {false, true}; - for (int i = 0; i < 2; i++) { - unsigned fog_state = fog_state_bits[i]; - unsigned dlight_state = dlight_state_bits[i]; + for (int i = 0; i < 2; i++) { + unsigned fog_state = fog_state_bits[i]; + unsigned dlight_state = dlight_state_bits[i]; - for (int j = 0; j < 3; j++) { - def.face_culling = j; // cullType_t value + for (int j = 0; j < 3; j++) { + def.face_culling = j; // cullType_t value - for (int k = 0; k < 2; k++) { - def.polygon_offset = polygon_offset[k]; + for (int k = 0; k < 2; k++) { + def.polygon_offset = polygon_offset[k]; - def.state_bits = fog_state; - vk.fog_pipelines[i][j][k] = create_pipeline(def); + def.state_bits = fog_state; + vk.fog_pipelines[i][j][k] = create_pipeline(def); - def.state_bits = dlight_state; - vk.dlight_pipelines[i][j][k] = create_pipeline(def); - } - } - } - } + def.state_bits = dlight_state; + vk.dlight_pipelines[i][j][k] = create_pipeline(def); + } + } + } + } // debug pipelines { @@ -1166,55 +1166,55 @@ void vk_initialize() { def.state_bits = GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; vk.images_debug_pipeline = create_pipeline(def); } - } + } vk.active = true; } void vk_shutdown() { - vkDestroyImage(vk.device, vk.depth_image, nullptr); - vkFreeMemory(vk.device, vk.depth_image_memory, nullptr); - vkDestroyImageView(vk.device, vk.depth_image_view, nullptr); + vkDestroyImage(vk.device, vk.depth_image, nullptr); + vkFreeMemory(vk.device, vk.depth_image_memory, nullptr); + vkDestroyImageView(vk.device, vk.depth_image_view, nullptr); - for (uint32_t i = 0; i < vk.swapchain_image_count; i++) - vkDestroyFramebuffer(vk.device, vk.framebuffers[i], nullptr); + for (uint32_t i = 0; i < vk.swapchain_image_count; i++) + vkDestroyFramebuffer(vk.device, vk.framebuffers[i], nullptr); - vkDestroyRenderPass(vk.device, vk.render_pass, nullptr); + vkDestroyRenderPass(vk.device, vk.render_pass, nullptr); - vkDestroyCommandPool(vk.device, vk.command_pool, nullptr); + vkDestroyCommandPool(vk.device, vk.command_pool, nullptr); - for (uint32_t i = 0; i < vk.swapchain_image_count; i++) - vkDestroyImageView(vk.device, vk.swapchain_image_views[i], nullptr); + for (uint32_t i = 0; i < vk.swapchain_image_count; i++) + vkDestroyImageView(vk.device, vk.swapchain_image_views[i], nullptr); - vkDestroyDescriptorPool(vk.device, vk.descriptor_pool, nullptr); - vkDestroyDescriptorSetLayout(vk.device, vk.set_layout, nullptr); - vkDestroyPipelineLayout(vk.device, vk.pipeline_layout, nullptr); - vkDestroyBuffer(vk.device, vk.vertex_buffer, nullptr); - vkDestroyBuffer(vk.device, vk.index_buffer, nullptr); - vkFreeMemory(vk.device, vk.geometry_buffer_memory, nullptr); - vkDestroySemaphore(vk.device, vk.image_acquired, nullptr); - vkDestroySemaphore(vk.device, vk.rendering_finished, nullptr); - vkDestroyFence(vk.device, vk.rendering_finished_fence, nullptr); + vkDestroyDescriptorPool(vk.device, vk.descriptor_pool, nullptr); + vkDestroyDescriptorSetLayout(vk.device, vk.set_layout, nullptr); + vkDestroyPipelineLayout(vk.device, vk.pipeline_layout, nullptr); + vkDestroyBuffer(vk.device, vk.vertex_buffer, nullptr); + vkDestroyBuffer(vk.device, vk.index_buffer, nullptr); + vkFreeMemory(vk.device, vk.geometry_buffer_memory, nullptr); + vkDestroySemaphore(vk.device, vk.image_acquired, nullptr); + vkDestroySemaphore(vk.device, vk.rendering_finished, nullptr); + vkDestroyFence(vk.device, vk.rendering_finished_fence, nullptr); - vkDestroyShaderModule(vk.device, vk.single_texture_vs, nullptr); - vkDestroyShaderModule(vk.device, vk.single_texture_clipping_plane_vs, nullptr); - vkDestroyShaderModule(vk.device, vk.single_texture_fs, nullptr); - vkDestroyShaderModule(vk.device, vk.multi_texture_vs, nullptr); - vkDestroyShaderModule(vk.device, vk.multi_texture_clipping_plane_vs, nullptr); - vkDestroyShaderModule(vk.device, vk.multi_texture_mul_fs, nullptr); - vkDestroyShaderModule(vk.device, vk.multi_texture_add_fs, nullptr); + vkDestroyShaderModule(vk.device, vk.single_texture_vs, nullptr); + vkDestroyShaderModule(vk.device, vk.single_texture_clipping_plane_vs, nullptr); + vkDestroyShaderModule(vk.device, vk.single_texture_fs, nullptr); + vkDestroyShaderModule(vk.device, vk.multi_texture_vs, nullptr); + vkDestroyShaderModule(vk.device, vk.multi_texture_clipping_plane_vs, nullptr); + vkDestroyShaderModule(vk.device, vk.multi_texture_mul_fs, nullptr); + vkDestroyShaderModule(vk.device, vk.multi_texture_add_fs, nullptr); - vkDestroyPipeline(vk.device, vk.skybox_pipeline, nullptr); + vkDestroyPipeline(vk.device, vk.skybox_pipeline, nullptr); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) { vkDestroyPipeline(vk.device, vk.shadow_volume_pipelines[i][j], nullptr); } vkDestroyPipeline(vk.device, vk.shadow_finish_pipeline, nullptr); - for (int i = 0; i < 2; i++) - for (int j = 0; j < 3; j++) - for (int k = 0; k < 2; k++) { - vkDestroyPipeline(vk.device, vk.fog_pipelines[i][j][k], nullptr); - vkDestroyPipeline(vk.device, vk.dlight_pipelines[i][j][k], nullptr); - } + for (int i = 0; i < 2; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 2; k++) { + vkDestroyPipeline(vk.device, vk.fog_pipelines[i][j][k], nullptr); + vkDestroyPipeline(vk.device, vk.dlight_pipelines[i][j][k], nullptr); + } vkDestroyPipeline(vk.device, vk.tris_debug_pipeline, nullptr); vkDestroyPipeline(vk.device, vk.tris_mirror_debug_pipeline, nullptr); vkDestroyPipeline(vk.device, vk.normals_debug_pipeline, nullptr); @@ -1222,409 +1222,409 @@ void vk_shutdown() { vkDestroyPipeline(vk.device, vk.surface_debug_pipeline_outline, nullptr); vkDestroyPipeline(vk.device, vk.images_debug_pipeline, nullptr); - vkDestroySwapchainKHR(vk.device, vk.swapchain, nullptr); - vkDestroyDevice(vk.device, nullptr); - vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr); - vkDestroyInstance(vk.instance, nullptr); + vkDestroySwapchainKHR(vk.device, vk.swapchain, nullptr); + vkDestroyDevice(vk.device, nullptr); + vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr); + vkDestroyInstance(vk.instance, nullptr); - Com_Memset(&vk, 0, sizeof(vk)); + Com_Memset(&vk, 0, sizeof(vk)); deinit_vulkan_library(); } void vk_release_resources() { - vkDeviceWaitIdle(vk.device); - auto& res = vk_resources; + vkDeviceWaitIdle(vk.device); + auto& res = vk_resources; - for (int i = 0; i < res.num_image_chunks; i++) - vkFreeMemory(vk.device, res.image_chunks[i].memory, nullptr); + for (int i = 0; i < res.num_image_chunks; i++) + vkFreeMemory(vk.device, res.image_chunks[i].memory, nullptr); - if (res.staging_buffer != VK_NULL_HANDLE) - vkDestroyBuffer(vk.device, res.staging_buffer, nullptr); + if (res.staging_buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vk.device, res.staging_buffer, nullptr); - if (res.staging_buffer_memory != VK_NULL_HANDLE) - vkFreeMemory(vk.device, res.staging_buffer_memory, nullptr); + if (res.staging_buffer_memory != VK_NULL_HANDLE) + vkFreeMemory(vk.device, res.staging_buffer_memory, nullptr); - for (int i = 0; i < res.num_samplers; i++) - vkDestroySampler(vk.device, res.samplers[i], nullptr); + for (int i = 0; i < res.num_samplers; i++) + vkDestroySampler(vk.device, res.samplers[i], nullptr); - for (int i = 0; i < res.num_pipelines; i++) - vkDestroyPipeline(vk.device, res.pipelines[i], nullptr); + for (int i = 0; i < res.num_pipelines; i++) + vkDestroyPipeline(vk.device, res.pipelines[i], nullptr); vk_resources.pipeline_create_time = 0.0f; - for (int i = 0; i < MAX_VK_IMAGES; i++) { - Vk_Image& image = res.images[i]; + for (int i = 0; i < MAX_VK_IMAGES; i++) { + Vk_Image& image = res.images[i]; - if (image.handle != VK_NULL_HANDLE) { - vkDestroyImage(vk.device, image.handle, nullptr); - vkDestroyImageView(vk.device, image.view, nullptr); - } - } + if (image.handle != VK_NULL_HANDLE) { + vkDestroyImage(vk.device, image.handle, nullptr); + vkDestroyImageView(vk.device, image.view, nullptr); + } + } - Com_Memset(&res, 0, sizeof(res)); + Com_Memset(&res, 0, sizeof(res)); - VK_CHECK(vkResetDescriptorPool(vk.device, vk.descriptor_pool, 0)); + VK_CHECK(vkResetDescriptorPool(vk.device, vk.descriptor_pool, 0)); - // Reset geometry buffer's current offsets. - vk.xyz_elements = 0; - vk.color_st_elements = 0; - vk.index_buffer_offset = 0; + // Reset geometry buffer's current offsets. + vk.xyz_elements = 0; + vk.color_st_elements = 0; + vk.index_buffer_offset = 0; } static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer, - VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages, - VkAccessFlags src_access, VkAccessFlags dst_access) { + VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages, + VkAccessFlags src_access, VkAccessFlags dst_access) { - VkBufferMemoryBarrier barrier; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;; - barrier.pNext = nullptr; - barrier.srcAccessMask = src_access; - barrier.dstAccessMask = dst_access; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.buffer = buffer; - barrier.offset = 0; - barrier.size = VK_WHOLE_SIZE; + VkBufferMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;; + barrier.pNext = nullptr; + barrier.srcAccessMask = src_access; + barrier.dstAccessMask = dst_access; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.buffer = buffer; + barrier.offset = 0; + barrier.size = VK_WHOLE_SIZE; - vkCmdPipelineBarrier(cb, src_stages, dst_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr); + vkCmdPipelineBarrier(cb, src_stages, dst_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr); } Vk_Image vk_create_image(int width, int height, VkFormat format, int mip_levels, bool repeat_texture) { - Vk_Image image; + Vk_Image image; - // create image - { - VkImageCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.imageType = VK_IMAGE_TYPE_2D; - desc.format = format; - desc.extent.width = width; - desc.extent.height = height; - desc.extent.depth = 1; - desc.mipLevels = mip_levels; - desc.arrayLayers = 1; - desc.samples = VK_SAMPLE_COUNT_1_BIT; - desc.tiling = VK_IMAGE_TILING_OPTIMAL; - desc.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - desc.queueFamilyIndexCount = 0; - desc.pQueueFamilyIndices = nullptr; - desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + // create image + { + VkImageCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.imageType = VK_IMAGE_TYPE_2D; + desc.format = format; + desc.extent.width = width; + desc.extent.height = height; + desc.extent.depth = 1; + desc.mipLevels = mip_levels; + desc.arrayLayers = 1; + desc.samples = VK_SAMPLE_COUNT_1_BIT; + desc.tiling = VK_IMAGE_TILING_OPTIMAL; + desc.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + desc.queueFamilyIndexCount = 0; + desc.pQueueFamilyIndices = nullptr; + desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &image.handle)); - allocate_and_bind_image_memory(image.handle); - } + VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &image.handle)); + allocate_and_bind_image_memory(image.handle); + } - // create image view - { - VkImageViewCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.image = image.handle; - desc.viewType = VK_IMAGE_VIEW_TYPE_2D; - desc.format = format; - desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - desc.subresourceRange.baseMipLevel = 0; - desc.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - desc.subresourceRange.baseArrayLayer = 0; - desc.subresourceRange.layerCount = 1; - VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &image.view)); - } + // create image view + { + VkImageViewCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.image = image.handle; + desc.viewType = VK_IMAGE_VIEW_TYPE_2D; + desc.format = format; + desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + desc.subresourceRange.baseMipLevel = 0; + desc.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + desc.subresourceRange.baseArrayLayer = 0; + desc.subresourceRange.layerCount = 1; + VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &image.view)); + } - // create associated descriptor set - { - VkDescriptorSetAllocateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - desc.pNext = nullptr; - desc.descriptorPool = vk.descriptor_pool; - desc.descriptorSetCount = 1; - desc.pSetLayouts = &vk.set_layout; - VK_CHECK(vkAllocateDescriptorSets(vk.device, &desc, &image.descriptor_set)); + // create associated descriptor set + { + VkDescriptorSetAllocateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + desc.pNext = nullptr; + desc.descriptorPool = vk.descriptor_pool; + desc.descriptorSetCount = 1; + desc.pSetLayouts = &vk.set_layout; + VK_CHECK(vkAllocateDescriptorSets(vk.device, &desc, &image.descriptor_set)); - vk_update_descriptor_set(image.descriptor_set, image.view, mip_levels > 1, repeat_texture); + vk_update_descriptor_set(image.descriptor_set, image.view, mip_levels > 1, repeat_texture); vk_resources.current_descriptor_sets[glState.currenttmu] = image.descriptor_set; - } + } - return image; + return image; } void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* pixels, int bytes_per_pixel) { - VkBufferImageCopy regions[16]; - int num_regions = 0; + VkBufferImageCopy regions[16]; + int num_regions = 0; - int buffer_size = 0; + int buffer_size = 0; - while (true) { - VkBufferImageCopy region; - region.bufferOffset = buffer_size; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = num_regions; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; - region.imageOffset = VkOffset3D{ 0, 0, 0 }; - region.imageExtent = VkExtent3D{ (uint32_t)width, (uint32_t)height, 1 }; + while (true) { + VkBufferImageCopy region; + region.bufferOffset = buffer_size; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = num_regions; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageOffset = VkOffset3D{ 0, 0, 0 }; + region.imageExtent = VkExtent3D{ (uint32_t)width, (uint32_t)height, 1 }; - regions[num_regions] = region; - num_regions++; + regions[num_regions] = region; + num_regions++; - buffer_size += width * height * bytes_per_pixel; + buffer_size += width * height * bytes_per_pixel; - if (!mipmap || (width == 1 && height == 1)) - break; + if (!mipmap || (width == 1 && height == 1)) + break; - width >>= 1; - if (width < 1) width = 1; + width >>= 1; + if (width < 1) width = 1; - height >>= 1; - if (height < 1) height = 1; - } + height >>= 1; + if (height < 1) height = 1; + } - ensure_staging_buffer_allocation(buffer_size); - Com_Memcpy(vk_resources.staging_buffer_ptr, pixels, buffer_size); + ensure_staging_buffer_allocation(buffer_size); + Com_Memcpy(vk_resources.staging_buffer_ptr, pixels, buffer_size); - record_and_run_commands(vk.command_pool, vk.queue, - [&image, &num_regions, ®ions](VkCommandBuffer command_buffer) { + record_and_run_commands(vk.command_pool, vk.queue, + [&image, &num_regions, ®ions](VkCommandBuffer command_buffer) { - record_buffer_memory_barrier(command_buffer, vk_resources.staging_buffer, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); + record_buffer_memory_barrier(command_buffer, vk_resources.staging_buffer, + VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); - record_image_layout_transition(command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, - 0, VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + record_image_layout_transition(command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, + 0, VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - vkCmdCopyBufferToImage(command_buffer, vk_resources.staging_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, num_regions, regions); + vkCmdCopyBufferToImage(command_buffer, vk_resources.staging_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, num_regions, regions); - record_image_layout_transition(command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - }); + record_image_layout_transition(command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + }); } void vk_update_descriptor_set(VkDescriptorSet set, VkImageView image_view, bool mipmap, bool repeat_texture) { - Vk_Sampler_Def sampler_def; - sampler_def.repeat_texture = repeat_texture; - if (mipmap) { - sampler_def.gl_mag_filter = gl_filter_max; - sampler_def.gl_min_filter = gl_filter_min; - } else { - sampler_def.gl_mag_filter = GL_LINEAR; - sampler_def.gl_min_filter = GL_LINEAR; - } + Vk_Sampler_Def sampler_def; + sampler_def.repeat_texture = repeat_texture; + if (mipmap) { + sampler_def.gl_mag_filter = gl_filter_max; + sampler_def.gl_min_filter = gl_filter_min; + } else { + sampler_def.gl_mag_filter = GL_LINEAR; + sampler_def.gl_min_filter = GL_LINEAR; + } - VkDescriptorImageInfo image_info; - image_info.sampler = vk_find_sampler(sampler_def); - image_info.imageView = image_view; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkDescriptorImageInfo image_info; + image_info.sampler = vk_find_sampler(sampler_def); + image_info.imageView = image_view; + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VkWriteDescriptorSet descriptor_write; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = set; - descriptor_write.dstBinding = 0; - descriptor_write.dstArrayElement = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.pNext = nullptr; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &image_info; - descriptor_write.pBufferInfo = nullptr; - descriptor_write.pTexelBufferView = nullptr; + VkWriteDescriptorSet descriptor_write; + descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_write.dstSet = set; + descriptor_write.dstBinding = 0; + descriptor_write.dstArrayElement = 0; + descriptor_write.descriptorCount = 1; + descriptor_write.pNext = nullptr; + descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptor_write.pImageInfo = &image_info; + descriptor_write.pBufferInfo = nullptr; + descriptor_write.pTexelBufferView = nullptr; - vkUpdateDescriptorSets(vk.device, 1, &descriptor_write, 0, nullptr); + vkUpdateDescriptorSets(vk.device, 1, &descriptor_write, 0, nullptr); } static VkPipeline create_pipeline(const Vk_Pipeline_Def& def) { - auto get_shader_stage_desc = [](VkShaderStageFlagBits stage, VkShaderModule shader_module, const char* entry) { - VkPipelineShaderStageCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.stage = stage; - desc.module = shader_module; - desc.pName = entry; - desc.pSpecializationInfo = nullptr; - return desc; - }; + auto get_shader_stage_desc = [](VkShaderStageFlagBits stage, VkShaderModule shader_module, const char* entry) { + VkPipelineShaderStageCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.stage = stage; + desc.module = shader_module; + desc.pName = entry; + desc.pSpecializationInfo = nullptr; + return desc; + }; - struct Specialization_Data { - int32_t alpha_test_func; - } specialization_data; + struct Specialization_Data { + int32_t alpha_test_func; + } specialization_data; - if ((def.state_bits & GLS_ATEST_BITS) == 0) - specialization_data.alpha_test_func = 0; - else if (def.state_bits & GLS_ATEST_GT_0) - specialization_data.alpha_test_func = 1; - else if (def.state_bits & GLS_ATEST_LT_80) - specialization_data.alpha_test_func = 2; - else if (def.state_bits & GLS_ATEST_GE_80) - specialization_data.alpha_test_func = 3; - else - ri.Error(ERR_DROP, "create_pipeline: invalid alpha test state bits\n"); + if ((def.state_bits & GLS_ATEST_BITS) == 0) + specialization_data.alpha_test_func = 0; + else if (def.state_bits & GLS_ATEST_GT_0) + specialization_data.alpha_test_func = 1; + else if (def.state_bits & GLS_ATEST_LT_80) + specialization_data.alpha_test_func = 2; + else if (def.state_bits & GLS_ATEST_GE_80) + specialization_data.alpha_test_func = 3; + else + ri.Error(ERR_DROP, "create_pipeline: invalid alpha test state bits\n"); - VkSpecializationMapEntry specialization_entries[1]; - specialization_entries[0].constantID = 0; - specialization_entries[0].offset = offsetof(struct Specialization_Data, alpha_test_func); - specialization_entries[0].size = sizeof(int32_t); + VkSpecializationMapEntry specialization_entries[1]; + specialization_entries[0].constantID = 0; + specialization_entries[0].offset = offsetof(struct Specialization_Data, alpha_test_func); + specialization_entries[0].size = sizeof(int32_t); - VkSpecializationInfo specialization_info; - specialization_info.mapEntryCount = 1; - specialization_info.pMapEntries = specialization_entries; - specialization_info.dataSize = sizeof(Specialization_Data); - specialization_info.pData = &specialization_data; + VkSpecializationInfo specialization_info; + specialization_info.mapEntryCount = 1; + specialization_info.pMapEntries = specialization_entries; + specialization_info.dataSize = sizeof(Specialization_Data); + specialization_info.pData = &specialization_data; - std::vector shader_stages_state; + std::vector shader_stages_state; - VkShaderModule* vs_module, *fs_module; - if (def.shader_type == Vk_Shader_Type::single_texture) { - vs_module = def.clipping_plane ? &vk.single_texture_clipping_plane_vs : &vk.single_texture_vs; - fs_module = &vk.single_texture_fs; - } else if (def.shader_type == Vk_Shader_Type::multi_texture_mul) { - vs_module = def.clipping_plane ? &vk.multi_texture_clipping_plane_vs : &vk.multi_texture_vs; - fs_module = &vk.multi_texture_mul_fs; - } else if (def.shader_type == Vk_Shader_Type::multi_texture_add) { - vs_module = def.clipping_plane ? &vk.multi_texture_clipping_plane_vs : &vk.multi_texture_vs; - fs_module = &vk.multi_texture_add_fs; - } - shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_VERTEX_BIT, *vs_module, "main")); - shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_FRAGMENT_BIT, *fs_module, "main")); + VkShaderModule* vs_module, *fs_module; + if (def.shader_type == Vk_Shader_Type::single_texture) { + vs_module = def.clipping_plane ? &vk.single_texture_clipping_plane_vs : &vk.single_texture_vs; + fs_module = &vk.single_texture_fs; + } else if (def.shader_type == Vk_Shader_Type::multi_texture_mul) { + vs_module = def.clipping_plane ? &vk.multi_texture_clipping_plane_vs : &vk.multi_texture_vs; + fs_module = &vk.multi_texture_mul_fs; + } else if (def.shader_type == Vk_Shader_Type::multi_texture_add) { + vs_module = def.clipping_plane ? &vk.multi_texture_clipping_plane_vs : &vk.multi_texture_vs; + fs_module = &vk.multi_texture_add_fs; + } + shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_VERTEX_BIT, *vs_module, "main")); + shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_FRAGMENT_BIT, *fs_module, "main")); - if (def.state_bits & GLS_ATEST_BITS) - shader_stages_state.back().pSpecializationInfo = &specialization_info; + if (def.state_bits & GLS_ATEST_BITS) + shader_stages_state.back().pSpecializationInfo = &specialization_info; - // - // Vertex input - // - VkVertexInputBindingDescription bindings[4]; - // xyz array - bindings[0].binding = 0; - bindings[0].stride = sizeof(vec4_t); - bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + // + // Vertex input + // + VkVertexInputBindingDescription bindings[4]; + // xyz array + bindings[0].binding = 0; + bindings[0].stride = sizeof(vec4_t); + bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - // color array - bindings[1].binding = 1; - bindings[1].stride = sizeof(color4ub_t); - bindings[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + // color array + bindings[1].binding = 1; + bindings[1].stride = sizeof(color4ub_t); + bindings[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - // st0 array - bindings[2].binding = 2; - bindings[2].stride = sizeof(vec2_t); - bindings[2].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + // st0 array + bindings[2].binding = 2; + bindings[2].stride = sizeof(vec2_t); + bindings[2].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - // st1 array - bindings[3].binding = 3; - bindings[3].stride = sizeof(vec2_t); - bindings[3].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + // st1 array + bindings[3].binding = 3; + bindings[3].stride = sizeof(vec2_t); + bindings[3].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - VkVertexInputAttributeDescription attribs[4]; - // xyz - attribs[0].location = 0; - attribs[0].binding = 0; - attribs[0].format = VK_FORMAT_R32G32B32A32_SFLOAT; - attribs[0].offset = 0; + VkVertexInputAttributeDescription attribs[4]; + // xyz + attribs[0].location = 0; + attribs[0].binding = 0; + attribs[0].format = VK_FORMAT_R32G32B32A32_SFLOAT; + attribs[0].offset = 0; - // color - attribs[1].location = 1; - attribs[1].binding = 1; - attribs[1].format = VK_FORMAT_R8G8B8A8_UNORM; - attribs[1].offset = 0; + // color + attribs[1].location = 1; + attribs[1].binding = 1; + attribs[1].format = VK_FORMAT_R8G8B8A8_UNORM; + attribs[1].offset = 0; - // st0 - attribs[2].location = 2; - attribs[2].binding = 2; - attribs[2].format = VK_FORMAT_R32G32_SFLOAT; - attribs[2].offset = 0; + // st0 + attribs[2].location = 2; + attribs[2].binding = 2; + attribs[2].format = VK_FORMAT_R32G32_SFLOAT; + attribs[2].offset = 0; - // st1 - attribs[3].location = 3; - attribs[3].binding = 3; - attribs[3].format = VK_FORMAT_R32G32_SFLOAT; - attribs[3].offset = 0; + // st1 + attribs[3].location = 3; + attribs[3].binding = 3; + attribs[3].format = VK_FORMAT_R32G32_SFLOAT; + attribs[3].offset = 0; - VkPipelineVertexInputStateCreateInfo vertex_input_state; - vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pNext = nullptr; - vertex_input_state.flags = 0; - vertex_input_state.vertexBindingDescriptionCount = (def.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4; - vertex_input_state.pVertexBindingDescriptions = bindings; - vertex_input_state.vertexAttributeDescriptionCount = (def.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4; - vertex_input_state.pVertexAttributeDescriptions = attribs; + VkPipelineVertexInputStateCreateInfo vertex_input_state; + vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_input_state.pNext = nullptr; + vertex_input_state.flags = 0; + vertex_input_state.vertexBindingDescriptionCount = (def.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4; + vertex_input_state.pVertexBindingDescriptions = bindings; + vertex_input_state.vertexAttributeDescriptionCount = (def.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4; + vertex_input_state.pVertexAttributeDescriptions = attribs; - // - // Primitive assembly. - // - VkPipelineInputAssemblyStateCreateInfo input_assembly_state; - input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly_state.pNext = nullptr; - input_assembly_state.flags = 0; - input_assembly_state.topology = def.line_primitives ? VK_PRIMITIVE_TOPOLOGY_LINE_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - input_assembly_state.primitiveRestartEnable = VK_FALSE; + // + // Primitive assembly. + // + VkPipelineInputAssemblyStateCreateInfo input_assembly_state; + input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly_state.pNext = nullptr; + input_assembly_state.flags = 0; + input_assembly_state.topology = def.line_primitives ? VK_PRIMITIVE_TOPOLOGY_LINE_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + input_assembly_state.primitiveRestartEnable = VK_FALSE; - // - // Viewport. - // - VkPipelineViewportStateCreateInfo viewport_state; - viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state.pNext = nullptr; - viewport_state.flags = 0; - viewport_state.viewportCount = 1; - viewport_state.pViewports = nullptr; // dynamic viewport state - viewport_state.scissorCount = 1; - viewport_state.pScissors = nullptr; // dynamic scissor state + // + // Viewport. + // + VkPipelineViewportStateCreateInfo viewport_state; + viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_state.pNext = nullptr; + viewport_state.flags = 0; + viewport_state.viewportCount = 1; + viewport_state.pViewports = nullptr; // dynamic viewport state + viewport_state.scissorCount = 1; + viewport_state.pScissors = nullptr; // dynamic scissor state - // - // Rasterization. - // - VkPipelineRasterizationStateCreateInfo rasterization_state; - rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_state.pNext = nullptr; - rasterization_state.flags = 0; - rasterization_state.depthClampEnable = VK_FALSE; - rasterization_state.rasterizerDiscardEnable = VK_FALSE; - rasterization_state.polygonMode = (def.state_bits & GLS_POLYMODE_LINE) ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL; + // + // Rasterization. + // + VkPipelineRasterizationStateCreateInfo rasterization_state; + rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterization_state.pNext = nullptr; + rasterization_state.flags = 0; + rasterization_state.depthClampEnable = VK_FALSE; + rasterization_state.rasterizerDiscardEnable = VK_FALSE; + rasterization_state.polygonMode = (def.state_bits & GLS_POLYMODE_LINE) ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL; - if (def.face_culling == CT_TWO_SIDED) - rasterization_state.cullMode = VK_CULL_MODE_NONE; - else if (def.face_culling == CT_FRONT_SIDED) - rasterization_state.cullMode = (def.mirror ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT); - else if (def.face_culling == CT_BACK_SIDED) - rasterization_state.cullMode = (def.mirror ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT); - else - ri.Error(ERR_DROP, "create_pipeline: invalid face culling mode\n"); + if (def.face_culling == CT_TWO_SIDED) + rasterization_state.cullMode = VK_CULL_MODE_NONE; + else if (def.face_culling == CT_FRONT_SIDED) + rasterization_state.cullMode = (def.mirror ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT); + else if (def.face_culling == CT_BACK_SIDED) + rasterization_state.cullMode = (def.mirror ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT); + else + ri.Error(ERR_DROP, "create_pipeline: invalid face culling mode\n"); - rasterization_state.frontFace = VK_FRONT_FACE_CLOCKWISE; // Q3 defaults to clockwise vertex order + rasterization_state.frontFace = VK_FRONT_FACE_CLOCKWISE; // Q3 defaults to clockwise vertex order - rasterization_state.depthBiasEnable = def.polygon_offset ? VK_TRUE : VK_FALSE; - rasterization_state.depthBiasConstantFactor = 0.0f; // dynamic depth bias state - rasterization_state.depthBiasClamp = 0.0f; // dynamic depth bias state - rasterization_state.depthBiasSlopeFactor = 0.0f; // dynamic depth bias state - rasterization_state.lineWidth = 1.0f; + rasterization_state.depthBiasEnable = def.polygon_offset ? VK_TRUE : VK_FALSE; + rasterization_state.depthBiasConstantFactor = 0.0f; // dynamic depth bias state + rasterization_state.depthBiasClamp = 0.0f; // dynamic depth bias state + rasterization_state.depthBiasSlopeFactor = 0.0f; // dynamic depth bias state + rasterization_state.lineWidth = 1.0f; - VkPipelineMultisampleStateCreateInfo multisample_state; - multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_state.pNext = nullptr; - multisample_state.flags = 0; - multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_state.sampleShadingEnable = VK_FALSE; - multisample_state.minSampleShading = 1.0f; - multisample_state.pSampleMask = nullptr; - multisample_state.alphaToCoverageEnable = VK_FALSE; - multisample_state.alphaToOneEnable = VK_FALSE; + VkPipelineMultisampleStateCreateInfo multisample_state; + multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisample_state.pNext = nullptr; + multisample_state.flags = 0; + multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisample_state.sampleShadingEnable = VK_FALSE; + multisample_state.minSampleShading = 1.0f; + multisample_state.pSampleMask = nullptr; + multisample_state.alphaToCoverageEnable = VK_FALSE; + multisample_state.alphaToOneEnable = VK_FALSE; - VkPipelineDepthStencilStateCreateInfo depth_stencil_state; - depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depth_stencil_state.pNext = nullptr; - depth_stencil_state.flags = 0; - depth_stencil_state.depthTestEnable = (def.state_bits & GLS_DEPTHTEST_DISABLE) ? VK_FALSE : VK_TRUE; - depth_stencil_state.depthWriteEnable = (def.state_bits & GLS_DEPTHMASK_TRUE) ? VK_TRUE : VK_FALSE; - depth_stencil_state.depthCompareOp = (def.state_bits & GLS_DEPTHFUNC_EQUAL) ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_LESS_OR_EQUAL; - depth_stencil_state.depthBoundsTestEnable = VK_FALSE; - depth_stencil_state.stencilTestEnable = (def.shadow_phase != Vk_Shadow_Phase::disabled) ? VK_TRUE : VK_FALSE; + VkPipelineDepthStencilStateCreateInfo depth_stencil_state; + depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil_state.pNext = nullptr; + depth_stencil_state.flags = 0; + depth_stencil_state.depthTestEnable = (def.state_bits & GLS_DEPTHTEST_DISABLE) ? VK_FALSE : VK_TRUE; + depth_stencil_state.depthWriteEnable = (def.state_bits & GLS_DEPTHMASK_TRUE) ? VK_TRUE : VK_FALSE; + depth_stencil_state.depthCompareOp = (def.state_bits & GLS_DEPTHFUNC_EQUAL) ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_LESS_OR_EQUAL; + depth_stencil_state.depthBoundsTestEnable = VK_FALSE; + depth_stencil_state.stencilTestEnable = (def.shadow_phase != Vk_Shadow_Phase::disabled) ? VK_TRUE : VK_FALSE; if (def.shadow_phase == Vk_Shadow_Phase::shadow_edges_rendering) { depth_stencil_state.front.failOp = VK_STENCIL_OP_KEEP; @@ -1653,269 +1653,269 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Def& def) { depth_stencil_state.back = {}; } - depth_stencil_state.minDepthBounds = 0.0; - depth_stencil_state.maxDepthBounds = 0.0; + depth_stencil_state.minDepthBounds = 0.0; + depth_stencil_state.maxDepthBounds = 0.0; - VkPipelineColorBlendAttachmentState attachment_blend_state = {}; - attachment_blend_state.blendEnable = (def.state_bits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) ? VK_TRUE : VK_FALSE; + VkPipelineColorBlendAttachmentState attachment_blend_state = {}; + attachment_blend_state.blendEnable = (def.state_bits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) ? VK_TRUE : VK_FALSE; if (def.shadow_phase == Vk_Shadow_Phase::shadow_edges_rendering) attachment_blend_state.colorWriteMask = 0; else attachment_blend_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - - if (attachment_blend_state.blendEnable) { - switch (def.state_bits & GLS_SRCBLEND_BITS) { - case GLS_SRCBLEND_ZERO: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO; - break; - case GLS_SRCBLEND_ONE: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - break; - case GLS_SRCBLEND_DST_COLOR: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR; - break; - case GLS_SRCBLEND_ONE_MINUS_DST_COLOR: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - break; - case GLS_SRCBLEND_SRC_ALPHA: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - break; - case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GLS_SRCBLEND_DST_ALPHA: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - break; - case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - case GLS_SRCBLEND_ALPHA_SATURATE: - attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; - break; - default: - ri.Error( ERR_DROP, "create_pipeline: invalid src blend state bits\n" ); - break; - } - switch (def.state_bits & GLS_DSTBLEND_BITS) { - case GLS_DSTBLEND_ZERO: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; - break; - case GLS_DSTBLEND_ONE: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - break; - case GLS_DSTBLEND_SRC_COLOR: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; - break; - case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - break; - case GLS_DSTBLEND_SRC_ALPHA: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - break; - case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GLS_DSTBLEND_DST_ALPHA: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - break; - case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA: - attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - default: - ri.Error( ERR_DROP, "create_pipeline: invalid dst blend state bits\n" ); - break; - } + + if (attachment_blend_state.blendEnable) { + switch (def.state_bits & GLS_SRCBLEND_BITS) { + case GLS_SRCBLEND_ZERO: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO; + break; + case GLS_SRCBLEND_ONE: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + break; + case GLS_SRCBLEND_DST_COLOR: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR; + break; + case GLS_SRCBLEND_ONE_MINUS_DST_COLOR: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; + break; + case GLS_SRCBLEND_SRC_ALPHA: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + break; + case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + break; + case GLS_SRCBLEND_DST_ALPHA: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; + break; + case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; + break; + case GLS_SRCBLEND_ALPHA_SATURATE: + attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; + break; + default: + ri.Error( ERR_DROP, "create_pipeline: invalid src blend state bits\n" ); + break; + } + switch (def.state_bits & GLS_DSTBLEND_BITS) { + case GLS_DSTBLEND_ZERO: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + break; + case GLS_DSTBLEND_ONE: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; + break; + case GLS_DSTBLEND_SRC_COLOR: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; + break; + case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + break; + case GLS_DSTBLEND_SRC_ALPHA: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + break; + case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + break; + case GLS_DSTBLEND_DST_ALPHA: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; + break; + case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA: + attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; + break; + default: + ri.Error( ERR_DROP, "create_pipeline: invalid dst blend state bits\n" ); + break; + } - attachment_blend_state.srcAlphaBlendFactor = attachment_blend_state.srcColorBlendFactor; - attachment_blend_state.dstAlphaBlendFactor = attachment_blend_state.dstColorBlendFactor; - attachment_blend_state.colorBlendOp = VK_BLEND_OP_ADD; - attachment_blend_state.alphaBlendOp = VK_BLEND_OP_ADD; - } + attachment_blend_state.srcAlphaBlendFactor = attachment_blend_state.srcColorBlendFactor; + attachment_blend_state.dstAlphaBlendFactor = attachment_blend_state.dstColorBlendFactor; + attachment_blend_state.colorBlendOp = VK_BLEND_OP_ADD; + attachment_blend_state.alphaBlendOp = VK_BLEND_OP_ADD; + } - VkPipelineColorBlendStateCreateInfo blend_state; - blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - blend_state.pNext = nullptr; - blend_state.flags = 0; - blend_state.logicOpEnable = VK_FALSE; - blend_state.logicOp = VK_LOGIC_OP_COPY; - blend_state.attachmentCount = 1; - blend_state.pAttachments = &attachment_blend_state; - blend_state.blendConstants[0] = 0.0f; - blend_state.blendConstants[1] = 0.0f; - blend_state.blendConstants[2] = 0.0f; - blend_state.blendConstants[3] = 0.0f; + VkPipelineColorBlendStateCreateInfo blend_state; + blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_state.pNext = nullptr; + blend_state.flags = 0; + blend_state.logicOpEnable = VK_FALSE; + blend_state.logicOp = VK_LOGIC_OP_COPY; + blend_state.attachmentCount = 1; + blend_state.pAttachments = &attachment_blend_state; + blend_state.blendConstants[0] = 0.0f; + blend_state.blendConstants[1] = 0.0f; + blend_state.blendConstants[2] = 0.0f; + blend_state.blendConstants[3] = 0.0f; - VkPipelineDynamicStateCreateInfo dynamic_state; - dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state.pNext = nullptr; - dynamic_state.flags = 0; - dynamic_state.dynamicStateCount = 3; - VkDynamicState dynamic_state_array[3] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_DEPTH_BIAS }; - dynamic_state.pDynamicStates = dynamic_state_array; + VkPipelineDynamicStateCreateInfo dynamic_state; + dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state.pNext = nullptr; + dynamic_state.flags = 0; + dynamic_state.dynamicStateCount = 3; + VkDynamicState dynamic_state_array[3] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_DEPTH_BIAS }; + dynamic_state.pDynamicStates = dynamic_state_array; - VkGraphicsPipelineCreateInfo create_info; - create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.stageCount = static_cast(shader_stages_state.size()); - create_info.pStages = shader_stages_state.data(); - create_info.pVertexInputState = &vertex_input_state; - create_info.pInputAssemblyState = &input_assembly_state; - create_info.pTessellationState = nullptr; - create_info.pViewportState = &viewport_state; - create_info.pRasterizationState = &rasterization_state; - create_info.pMultisampleState = &multisample_state; - create_info.pDepthStencilState = &depth_stencil_state; - create_info.pColorBlendState = &blend_state; - create_info.pDynamicState = &dynamic_state; - create_info.layout = vk.pipeline_layout; - create_info.renderPass = vk.render_pass; - create_info.subpass = 0; - create_info.basePipelineHandle = VK_NULL_HANDLE; - create_info.basePipelineIndex = -1; + VkGraphicsPipelineCreateInfo create_info; + create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.stageCount = static_cast(shader_stages_state.size()); + create_info.pStages = shader_stages_state.data(); + create_info.pVertexInputState = &vertex_input_state; + create_info.pInputAssemblyState = &input_assembly_state; + create_info.pTessellationState = nullptr; + create_info.pViewportState = &viewport_state; + create_info.pRasterizationState = &rasterization_state; + create_info.pMultisampleState = &multisample_state; + create_info.pDepthStencilState = &depth_stencil_state; + create_info.pColorBlendState = &blend_state; + create_info.pDynamicState = &dynamic_state; + create_info.layout = vk.pipeline_layout; + create_info.renderPass = vk.render_pass; + create_info.subpass = 0; + create_info.basePipelineHandle = VK_NULL_HANDLE; + create_info.basePipelineIndex = -1; - VkPipeline pipeline; - VK_CHECK(vkCreateGraphicsPipelines(vk.device, VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline)); - return pipeline; + VkPipeline pipeline; + VK_CHECK(vkCreateGraphicsPipelines(vk.device, VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline)); + return pipeline; } struct Timer { - using Clock = std::chrono::high_resolution_clock; - using Second = std::chrono::duration>; + using Clock = std::chrono::high_resolution_clock; + using Second = std::chrono::duration>; - Clock::time_point start = Clock::now(); - double Elapsed_Seconds() const { - const auto duration = Clock::now() - start; - double seconds = std::chrono::duration_cast(duration).count(); - return seconds; - } + Clock::time_point start = Clock::now(); + double Elapsed_Seconds() const { + const auto duration = Clock::now() - start; + double seconds = std::chrono::duration_cast(duration).count(); + return seconds; + } }; VkSampler vk_find_sampler(const Vk_Sampler_Def& def) { - // Look for sampler among existing samplers. - for (int i = 0; i < vk_resources.num_samplers; i++) { - const auto& cur_def = vk_resources.sampler_defs[i]; + // Look for sampler among existing samplers. + for (int i = 0; i < vk_resources.num_samplers; i++) { + const auto& cur_def = vk_resources.sampler_defs[i]; - if (cur_def.repeat_texture == def.repeat_texture && - cur_def.gl_mag_filter == def.gl_mag_filter && - cur_def.gl_min_filter == def.gl_min_filter) - { - return vk_resources.samplers[i]; - } - } + if (cur_def.repeat_texture == def.repeat_texture && + cur_def.gl_mag_filter == def.gl_mag_filter && + cur_def.gl_min_filter == def.gl_min_filter) + { + return vk_resources.samplers[i]; + } + } - // Create new sampler. - if (vk_resources.num_samplers >= MAX_VK_SAMPLERS) { - ri.Error(ERR_DROP, "vk_find_sampler: MAX_VK_SAMPLERS hit\n"); - } + // Create new sampler. + if (vk_resources.num_samplers >= MAX_VK_SAMPLERS) { + ri.Error(ERR_DROP, "vk_find_sampler: MAX_VK_SAMPLERS hit\n"); + } - VkSamplerAddressMode address_mode = def.repeat_texture ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + VkSamplerAddressMode address_mode = def.repeat_texture ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - VkFilter mag_filter; - if (def.gl_mag_filter == GL_NEAREST) { - mag_filter = VK_FILTER_NEAREST; - } else if (def.gl_mag_filter == GL_LINEAR) { - mag_filter = VK_FILTER_LINEAR; - } else { - ri.Error(ERR_FATAL, "vk_find_sampler: invalid gl_mag_filter"); - } + VkFilter mag_filter; + if (def.gl_mag_filter == GL_NEAREST) { + mag_filter = VK_FILTER_NEAREST; + } else if (def.gl_mag_filter == GL_LINEAR) { + mag_filter = VK_FILTER_LINEAR; + } else { + ri.Error(ERR_FATAL, "vk_find_sampler: invalid gl_mag_filter"); + } - VkFilter min_filter; - VkSamplerMipmapMode mipmap_mode; - bool max_lod_0_25 = false; // used to emulate OpenGL's GL_LINEAR/GL_NEAREST minification filter - if (def.gl_min_filter == GL_NEAREST) { - min_filter = VK_FILTER_NEAREST; - mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - max_lod_0_25 = true; - } else if (def.gl_min_filter == GL_LINEAR) { - min_filter = VK_FILTER_LINEAR; - mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - max_lod_0_25 = true; - } else if (def.gl_min_filter == GL_NEAREST_MIPMAP_NEAREST) { - min_filter = VK_FILTER_NEAREST; - mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - } else if (def.gl_min_filter == GL_LINEAR_MIPMAP_NEAREST) { - min_filter = VK_FILTER_LINEAR; - mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - } else if (def.gl_min_filter == GL_NEAREST_MIPMAP_LINEAR) { - min_filter = VK_FILTER_NEAREST; - mipmap_mode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - } else if (def.gl_min_filter == GL_LINEAR_MIPMAP_LINEAR) { - min_filter = VK_FILTER_LINEAR; - mipmap_mode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - } else { - ri.Error(ERR_FATAL, "vk_find_sampler: invalid gl_min_filter"); - } + VkFilter min_filter; + VkSamplerMipmapMode mipmap_mode; + bool max_lod_0_25 = false; // used to emulate OpenGL's GL_LINEAR/GL_NEAREST minification filter + if (def.gl_min_filter == GL_NEAREST) { + min_filter = VK_FILTER_NEAREST; + mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + max_lod_0_25 = true; + } else if (def.gl_min_filter == GL_LINEAR) { + min_filter = VK_FILTER_LINEAR; + mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + max_lod_0_25 = true; + } else if (def.gl_min_filter == GL_NEAREST_MIPMAP_NEAREST) { + min_filter = VK_FILTER_NEAREST; + mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + } else if (def.gl_min_filter == GL_LINEAR_MIPMAP_NEAREST) { + min_filter = VK_FILTER_LINEAR; + mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + } else if (def.gl_min_filter == GL_NEAREST_MIPMAP_LINEAR) { + min_filter = VK_FILTER_NEAREST; + mipmap_mode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } else if (def.gl_min_filter == GL_LINEAR_MIPMAP_LINEAR) { + min_filter = VK_FILTER_LINEAR; + mipmap_mode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } else { + ri.Error(ERR_FATAL, "vk_find_sampler: invalid gl_min_filter"); + } - VkSamplerCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.magFilter = mag_filter; - desc.minFilter = min_filter; - desc.mipmapMode = mipmap_mode; - desc.addressModeU = address_mode; - desc.addressModeV = address_mode; - desc.addressModeW = address_mode; - desc.mipLodBias = 0.0f; - desc.anisotropyEnable = VK_TRUE; - desc.maxAnisotropy = 1; - desc.compareEnable = VK_FALSE; - desc.compareOp = VK_COMPARE_OP_ALWAYS; - desc.minLod = 0.0f; - desc.maxLod = max_lod_0_25 ? 0.25f : 12.0f; - desc.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - desc.unnormalizedCoordinates = VK_FALSE; + VkSamplerCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.magFilter = mag_filter; + desc.minFilter = min_filter; + desc.mipmapMode = mipmap_mode; + desc.addressModeU = address_mode; + desc.addressModeV = address_mode; + desc.addressModeW = address_mode; + desc.mipLodBias = 0.0f; + desc.anisotropyEnable = VK_TRUE; + desc.maxAnisotropy = 1; + desc.compareEnable = VK_FALSE; + desc.compareOp = VK_COMPARE_OP_ALWAYS; + desc.minLod = 0.0f; + desc.maxLod = max_lod_0_25 ? 0.25f : 12.0f; + desc.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + desc.unnormalizedCoordinates = VK_FALSE; - VkSampler sampler; - VK_CHECK(vkCreateSampler(vk.device, &desc, nullptr, &sampler)); + VkSampler sampler; + VK_CHECK(vkCreateSampler(vk.device, &desc, nullptr, &sampler)); - vk_resources.sampler_defs[vk_resources.num_samplers] = def; - vk_resources.samplers[vk_resources.num_samplers] = sampler; - vk_resources.num_samplers++; - return sampler; + vk_resources.sampler_defs[vk_resources.num_samplers] = def; + vk_resources.samplers[vk_resources.num_samplers] = sampler; + vk_resources.num_samplers++; + return sampler; } VkPipeline vk_find_pipeline(const Vk_Pipeline_Def& def) { - for (int i = 0; i < vk_resources.num_pipelines; i++) { - const auto& cur_def = vk_resources.pipeline_defs[i]; + for (int i = 0; i < vk_resources.num_pipelines; i++) { + const auto& cur_def = vk_resources.pipeline_defs[i]; - if (cur_def.shader_type == def.shader_type && - cur_def.state_bits == def.state_bits && - cur_def.face_culling == def.face_culling && - cur_def.polygon_offset == def.polygon_offset && - cur_def.clipping_plane == def.clipping_plane && - cur_def.mirror == def.mirror && + if (cur_def.shader_type == def.shader_type && + cur_def.state_bits == def.state_bits && + cur_def.face_culling == def.face_culling && + cur_def.polygon_offset == def.polygon_offset && + cur_def.clipping_plane == def.clipping_plane && + cur_def.mirror == def.mirror && cur_def.line_primitives == def.line_primitives && cur_def.shadow_phase == def.shadow_phase) - { - return vk_resources.pipelines[i]; - } - } + { + return vk_resources.pipelines[i]; + } + } - if (vk_resources.num_pipelines >= MAX_VK_PIPELINES) { - ri.Error(ERR_DROP, "vk_find_pipeline: MAX_VK_PIPELINES hit\n"); - } + if (vk_resources.num_pipelines >= MAX_VK_PIPELINES) { + ri.Error(ERR_DROP, "vk_find_pipeline: MAX_VK_PIPELINES hit\n"); + } - Timer t; - VkPipeline pipeline = create_pipeline(def); - vk_resources.pipeline_create_time += t.Elapsed_Seconds(); + Timer t; + VkPipeline pipeline = create_pipeline(def); + vk_resources.pipeline_create_time += t.Elapsed_Seconds(); - vk_resources.pipeline_defs[vk_resources.num_pipelines] = def; - vk_resources.pipelines[vk_resources.num_pipelines] = pipeline; - vk_resources.num_pipelines++; - return pipeline; + vk_resources.pipeline_defs[vk_resources.num_pipelines] = def; + vk_resources.pipelines[vk_resources.num_pipelines] = pipeline; + vk_resources.num_pipelines++; + return pipeline; } void vk_clear_attachments(bool clear_depth_stencil, bool clear_color, vec4_t color) { - if (!vk.active) - return; + if (!vk.active) + return; if (!clear_depth_stencil && !clear_color) return; - VkClearAttachment attachments[2]; + VkClearAttachment attachments[2]; uint32_t attachment_count = 0; if (clear_depth_stencil) { @@ -1936,54 +1936,54 @@ void vk_clear_attachments(bool clear_depth_stencil, bool clear_color, vec4_t col attachment_count++; } - VkClearRect clear_rect[2]; - clear_rect[0].rect = vk_get_scissor_rect(); - clear_rect[0].baseArrayLayer = 0; - clear_rect[0].layerCount = 1; - int rect_count = 1; + VkClearRect clear_rect[2]; + clear_rect[0].rect = vk_get_scissor_rect(); + clear_rect[0].baseArrayLayer = 0; + clear_rect[0].layerCount = 1; + int rect_count = 1; - // Split viewport rectangle into two non-overlapping rectangles. - // It's a HACK to prevent Vulkan validation layer's performance warning: - // "vkCmdClearAttachments() issued on command buffer object XXX prior to any Draw Cmds. - // It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw." - // + // Split viewport rectangle into two non-overlapping rectangles. + // It's a HACK to prevent Vulkan validation layer's performance warning: + // "vkCmdClearAttachments() issued on command buffer object XXX prior to any Draw Cmds. + // It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw." + // // NOTE: we don't use LOAD_OP_CLEAR for color attachment when we begin renderpass // since at that point we don't know whether we need collor buffer clear (usually we don't). - if (clear_color) { - uint32_t h = clear_rect[0].rect.extent.height / 2; - clear_rect[0].rect.extent.height = h; - clear_rect[1] = clear_rect[0]; - clear_rect[1].rect.offset.y = h; - rect_count = 2; - } + if (clear_color) { + uint32_t h = clear_rect[0].rect.extent.height / 2; + clear_rect[0].rect.extent.height = h; + clear_rect[1] = clear_rect[0]; + clear_rect[1].rect.offset.y = h; + rect_count = 2; + } - vkCmdClearAttachments(vk.command_buffer, attachment_count, attachments, rect_count, clear_rect); + vkCmdClearAttachments(vk.command_buffer, attachment_count, attachments, rect_count, clear_rect); } static VkRect2D get_viewport_rect() { - VkRect2D r; - if (backEnd.projection2D) { - r.offset.x = 0.0f; - r.offset.y = 0.0f; - r.extent.width = glConfig.vidWidth; - r.extent.height = glConfig.vidHeight; - } else { - r.offset.x = backEnd.viewParms.viewportX; - r.offset.y = glConfig.vidHeight - (backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight); - r.extent.width = backEnd.viewParms.viewportWidth; - r.extent.height = backEnd.viewParms.viewportHeight; - } - return r; + VkRect2D r; + if (backEnd.projection2D) { + r.offset.x = 0.0f; + r.offset.y = 0.0f; + r.extent.width = glConfig.vidWidth; + r.extent.height = glConfig.vidHeight; + } else { + r.offset.x = backEnd.viewParms.viewportX; + r.offset.y = glConfig.vidHeight - (backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight); + r.extent.width = backEnd.viewParms.viewportWidth; + r.extent.height = backEnd.viewParms.viewportHeight; + } + return r; } static VkViewport get_viewport(Vk_Depth_Range depth_range) { - VkRect2D r = get_viewport_rect(); + VkRect2D r = get_viewport_rect(); - VkViewport viewport; - viewport.x = (float)r.offset.x; - viewport.y = (float)r.offset.y; - viewport.width = (float)r.extent.width; - viewport.height = (float)r.extent.height; + VkViewport viewport; + viewport.x = (float)r.offset.x; + viewport.y = (float)r.offset.y; + viewport.width = (float)r.extent.width; + viewport.height = (float)r.extent.height; if (depth_range == Vk_Depth_Range::force_zero) { viewport.minDepth = 0.0f; @@ -1998,181 +1998,181 @@ static VkViewport get_viewport(Vk_Depth_Range depth_range) { viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; } - return viewport; + return viewport; } VkRect2D vk_get_scissor_rect() { - VkRect2D r = get_viewport_rect(); + VkRect2D r = get_viewport_rect(); - if (r.offset.x < 0) - r.offset.x = 0; - if (r.offset.y < 0) - r.offset.y = 0; + if (r.offset.x < 0) + r.offset.x = 0; + if (r.offset.y < 0) + r.offset.y = 0; - if (r.offset.x + r.extent.width > glConfig.vidWidth) - r.extent.width = glConfig.vidWidth - r.offset.x; - if (r.offset.y + r.extent.height > glConfig.vidHeight) - r.extent.height = glConfig.vidHeight - r.offset.y; + if (r.offset.x + r.extent.width > glConfig.vidWidth) + r.extent.width = glConfig.vidWidth - r.offset.x; + if (r.offset.y + r.extent.height > glConfig.vidHeight) + r.extent.height = glConfig.vidHeight - r.offset.y; - return r; + return r; } static void get_mvp_transform(float* mvp) { - if (backEnd.projection2D) { - float mvp0 = 2.0f / glConfig.vidWidth; - float mvp5 = 2.0f / glConfig.vidHeight; + if (backEnd.projection2D) { + float mvp0 = 2.0f / glConfig.vidWidth; + float mvp5 = 2.0f / glConfig.vidHeight; - mvp[0] = mvp0; mvp[1] = 0.0f; mvp[2] = 0.0f; mvp[3] = 0.0f; - mvp[4] = 0.0f; mvp[5] = mvp5; mvp[6] = 0.0f; mvp[7] = 0.0f; - mvp[8] = 0.0f; mvp[9] = 0.0f; mvp[10] = 1.0f; mvp[11] = 0.0f; - mvp[12] = -1.0f; mvp[13] = -1.0f; mvp[14] = 0.0f; mvp[15] = 1.0f; + mvp[0] = mvp0; mvp[1] = 0.0f; mvp[2] = 0.0f; mvp[3] = 0.0f; + mvp[4] = 0.0f; mvp[5] = mvp5; mvp[6] = 0.0f; mvp[7] = 0.0f; + mvp[8] = 0.0f; mvp[9] = 0.0f; mvp[10] = 1.0f; mvp[11] = 0.0f; + mvp[12] = -1.0f; mvp[13] = -1.0f; mvp[14] = 0.0f; mvp[15] = 1.0f; - } else { - const float* p = backEnd.viewParms.projectionMatrix; + } else { + const float* p = backEnd.viewParms.projectionMatrix; - // update q3's proj matrix (opengl) to vulkan conventions: z - [0, 1] instead of [-1, 1] and invert y direction - float zNear = r_znear->value; - float zFar = backEnd.viewParms.zFar; - float P10 = -zFar / (zFar - zNear); - float P14 = -zFar*zNear / (zFar - zNear); - float P5 = -p[5]; + // update q3's proj matrix (opengl) to vulkan conventions: z - [0, 1] instead of [-1, 1] and invert y direction + float zNear = r_znear->value; + float zFar = backEnd.viewParms.zFar; + float P10 = -zFar / (zFar - zNear); + float P14 = -zFar*zNear / (zFar - zNear); + float P5 = -p[5]; - float proj[16] = { - p[0], p[1], p[2], p[3], - p[4], P5, p[6], p[7], - p[8], p[9], P10, p[11], - p[12], p[13], P14, p[15] - }; + float proj[16] = { + p[0], p[1], p[2], p[3], + p[4], P5, p[6], p[7], + p[8], p[9], P10, p[11], + p[12], p[13], P14, p[15] + }; myGlMultMatrix(vk_resources.modelview_transform, proj, mvp); - } + } } void vk_bind_geometry() { if (!vk.active) return; - // xyz stream - { - if ((vk.xyz_elements + tess.numVertexes) * sizeof(vec4_t) > XYZ_SIZE) - ri.Error(ERR_DROP, "vk_bind_geometry: vertex buffer overflow (xyz)\n"); + // xyz stream + { + if ((vk.xyz_elements + tess.numVertexes) * sizeof(vec4_t) > XYZ_SIZE) + ri.Error(ERR_DROP, "vk_bind_geometry: vertex buffer overflow (xyz)\n"); - byte* dst = vk.vertex_buffer_ptr + XYZ_OFFSET + vk.xyz_elements * sizeof(vec4_t); - Com_Memcpy(dst, tess.xyz, tess.numVertexes * sizeof(vec4_t)); + byte* dst = vk.vertex_buffer_ptr + XYZ_OFFSET + vk.xyz_elements * sizeof(vec4_t); + Com_Memcpy(dst, tess.xyz, tess.numVertexes * sizeof(vec4_t)); VkDeviceSize xyz_offset = XYZ_OFFSET + vk.xyz_elements * sizeof(vec4_t); vkCmdBindVertexBuffers(vk.command_buffer, 0, 1, &vk.vertex_buffer, &xyz_offset); vk.xyz_elements += tess.numVertexes; - } + } - // indexes stream - { + // indexes stream + { std::size_t indexes_size = tess.numIndexes * sizeof(uint32_t); - if (vk.index_buffer_offset + indexes_size > INDEX_BUFFER_SIZE) - ri.Error(ERR_DROP, "vk_bind_geometry: index buffer overflow\n"); + if (vk.index_buffer_offset + indexes_size > INDEX_BUFFER_SIZE) + ri.Error(ERR_DROP, "vk_bind_geometry: index buffer overflow\n"); - byte* dst = vk.index_buffer_ptr + vk.index_buffer_offset; - Com_Memcpy(dst, tess.indexes, indexes_size); + byte* dst = vk.index_buffer_ptr + vk.index_buffer_offset; + Com_Memcpy(dst, tess.indexes, indexes_size); vkCmdBindIndexBuffer(vk.command_buffer, vk.index_buffer, vk.index_buffer_offset, VK_INDEX_TYPE_UINT32); vk.index_buffer_offset += indexes_size; - } + } - // - // Specify push constants. - // - float push_constants[16 + 12 + 4]; // mvp transform + eye transform + clipping plane in eye space + // + // Specify push constants. + // + float push_constants[16 + 12 + 4]; // mvp transform + eye transform + clipping plane in eye space - get_mvp_transform(push_constants); - int push_constants_size = 64; + get_mvp_transform(push_constants); + int push_constants_size = 64; - if (backEnd.viewParms.isPortal) { - // Eye space transform. - // NOTE: backEnd.or.modelMatrix incorporates s_flipMatrix, so it should be taken into account - // when computing clipping plane too. - float* eye_xform = push_constants + 16; - for (int i = 0; i < 12; i++) { - eye_xform[i] = backEnd.or.modelMatrix[(i%4)*4 + i/4 ]; - } + if (backEnd.viewParms.isPortal) { + // Eye space transform. + // NOTE: backEnd.or.modelMatrix incorporates s_flipMatrix, so it should be taken into account + // when computing clipping plane too. + float* eye_xform = push_constants + 16; + for (int i = 0; i < 12; i++) { + eye_xform[i] = backEnd.or.modelMatrix[(i%4)*4 + i/4 ]; + } - // Clipping plane in eye coordinates. - float world_plane[4]; - world_plane[0] = backEnd.viewParms.portalPlane.normal[0]; - world_plane[1] = backEnd.viewParms.portalPlane.normal[1]; - world_plane[2] = backEnd.viewParms.portalPlane.normal[2]; - world_plane[3] = backEnd.viewParms.portalPlane.dist; + // Clipping plane in eye coordinates. + float world_plane[4]; + world_plane[0] = backEnd.viewParms.portalPlane.normal[0]; + world_plane[1] = backEnd.viewParms.portalPlane.normal[1]; + world_plane[2] = backEnd.viewParms.portalPlane.normal[2]; + world_plane[3] = backEnd.viewParms.portalPlane.dist; - float eye_plane[4]; - eye_plane[0] = DotProduct (backEnd.viewParms.or.axis[0], world_plane); - eye_plane[1] = DotProduct (backEnd.viewParms.or.axis[1], world_plane); - eye_plane[2] = DotProduct (backEnd.viewParms.or.axis[2], world_plane); - eye_plane[3] = DotProduct (world_plane, backEnd.viewParms.or.origin) - world_plane[3]; + float eye_plane[4]; + eye_plane[0] = DotProduct (backEnd.viewParms.or.axis[0], world_plane); + eye_plane[1] = DotProduct (backEnd.viewParms.or.axis[1], world_plane); + eye_plane[2] = DotProduct (backEnd.viewParms.or.axis[2], world_plane); + eye_plane[3] = DotProduct (world_plane, backEnd.viewParms.or.origin) - world_plane[3]; - // Apply s_flipMatrix to be in the same coordinate system as eye_xfrom. - push_constants[28] = -eye_plane[1]; - push_constants[29] = eye_plane[2]; - push_constants[30] = -eye_plane[0]; - push_constants[31] = eye_plane[3]; + // Apply s_flipMatrix to be in the same coordinate system as eye_xfrom. + push_constants[28] = -eye_plane[1]; + push_constants[29] = eye_plane[2]; + push_constants[30] = -eye_plane[0]; + push_constants[31] = eye_plane[3]; - push_constants_size += 64; - } - vkCmdPushConstants(vk.command_buffer, vk.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, push_constants_size, push_constants); + push_constants_size += 64; + } + vkCmdPushConstants(vk.command_buffer, vk.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, push_constants_size, push_constants); } void vk_shade_geometry(VkPipeline pipeline, bool multitexture, Vk_Depth_Range depth_range, bool indexed) { - // color - { - if ((vk.color_st_elements + tess.numVertexes) * sizeof(color4ub_t) > COLOR_SIZE) - ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (color)\n"); + // color + { + if ((vk.color_st_elements + tess.numVertexes) * sizeof(color4ub_t) > COLOR_SIZE) + ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (color)\n"); - byte* dst = vk.vertex_buffer_ptr + COLOR_OFFSET + vk.color_st_elements * sizeof(color4ub_t); - Com_Memcpy(dst, tess.svars.colors, tess.numVertexes * sizeof(color4ub_t)); - } - // st0 - { - if ((vk.color_st_elements + tess.numVertexes) * sizeof(vec2_t) > ST0_SIZE) - ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (st0)\n"); + byte* dst = vk.vertex_buffer_ptr + COLOR_OFFSET + vk.color_st_elements * sizeof(color4ub_t); + Com_Memcpy(dst, tess.svars.colors, tess.numVertexes * sizeof(color4ub_t)); + } + // st0 + { + if ((vk.color_st_elements + tess.numVertexes) * sizeof(vec2_t) > ST0_SIZE) + ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (st0)\n"); - byte* dst = vk.vertex_buffer_ptr + ST0_OFFSET + vk.color_st_elements * sizeof(vec2_t); - Com_Memcpy(dst, tess.svars.texcoords[0], tess.numVertexes * sizeof(vec2_t)); - } - // st1 - if (multitexture) { - if ((vk.color_st_elements + tess.numVertexes) * sizeof(vec2_t) > ST1_SIZE) - ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (st1)\n"); + byte* dst = vk.vertex_buffer_ptr + ST0_OFFSET + vk.color_st_elements * sizeof(vec2_t); + Com_Memcpy(dst, tess.svars.texcoords[0], tess.numVertexes * sizeof(vec2_t)); + } + // st1 + if (multitexture) { + if ((vk.color_st_elements + tess.numVertexes) * sizeof(vec2_t) > ST1_SIZE) + ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (st1)\n"); - byte* dst = vk.vertex_buffer_ptr + ST1_OFFSET + vk.color_st_elements * sizeof(vec2_t); - Com_Memcpy(dst, tess.svars.texcoords[1], tess.numVertexes * sizeof(vec2_t)); - } + byte* dst = vk.vertex_buffer_ptr + ST1_OFFSET + vk.color_st_elements * sizeof(vec2_t); + Com_Memcpy(dst, tess.svars.texcoords[1], tess.numVertexes * sizeof(vec2_t)); + } - // configure vertex data stream - VkBuffer bufs[3] = { vk.vertex_buffer, vk.vertex_buffer, vk.vertex_buffer }; - VkDeviceSize offs[3] = { - COLOR_OFFSET + vk.color_st_elements * sizeof(color4ub_t), - ST0_OFFSET + vk.color_st_elements * sizeof(vec2_t), - ST1_OFFSET + vk.color_st_elements * sizeof(vec2_t) - }; - vkCmdBindVertexBuffers(vk.command_buffer, 1, multitexture ? 3 : 2, bufs, offs); - vk.color_st_elements += tess.numVertexes; + // configure vertex data stream + VkBuffer bufs[3] = { vk.vertex_buffer, vk.vertex_buffer, vk.vertex_buffer }; + VkDeviceSize offs[3] = { + COLOR_OFFSET + vk.color_st_elements * sizeof(color4ub_t), + ST0_OFFSET + vk.color_st_elements * sizeof(vec2_t), + ST1_OFFSET + vk.color_st_elements * sizeof(vec2_t) + }; + vkCmdBindVertexBuffers(vk.command_buffer, 1, multitexture ? 3 : 2, bufs, offs); + vk.color_st_elements += tess.numVertexes; - // bind descriptor sets - uint32_t set_count = multitexture ? 2 : 1; - vkCmdBindDescriptorSets(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk.pipeline_layout, 0, set_count, vk_resources.current_descriptor_sets, 0, nullptr); + // bind descriptor sets + uint32_t set_count = multitexture ? 2 : 1; + vkCmdBindDescriptorSets(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk.pipeline_layout, 0, set_count, vk_resources.current_descriptor_sets, 0, nullptr); - // bind pipeline - vkCmdBindPipeline(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + // bind pipeline + vkCmdBindPipeline(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - // configure pipeline's dynamic state - VkRect2D scissor_rect = vk_get_scissor_rect(); - vkCmdSetScissor(vk.command_buffer, 0, 1, &scissor_rect); + // configure pipeline's dynamic state + VkRect2D scissor_rect = vk_get_scissor_rect(); + vkCmdSetScissor(vk.command_buffer, 0, 1, &scissor_rect); - VkViewport viewport = get_viewport(depth_range); - vkCmdSetViewport(vk.command_buffer, 0, 1, &viewport); + VkViewport viewport = get_viewport(depth_range); + vkCmdSetViewport(vk.command_buffer, 0, 1, &viewport); - if (tess.shader->polygonOffset) { - vkCmdSetDepthBias(vk.command_buffer, r_offsetUnits->value, 0.0f, r_offsetFactor->value); - } + if (tess.shader->polygonOffset) { + vkCmdSetDepthBias(vk.command_buffer, r_offsetUnits->value, 0.0f, r_offsetFactor->value); + } // issue draw call if (indexed) @@ -2184,13 +2184,13 @@ void vk_shade_geometry(VkPipeline pipeline, bool multitexture, Vk_Depth_Range de } void vk_begin_frame() { - if (!vk.active) - return; + if (!vk.active) + return; - VK_CHECK(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, vk.image_acquired, VK_NULL_HANDLE, &vk.swapchain_image_index)); + VK_CHECK(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, vk.image_acquired, VK_NULL_HANDLE, &vk.swapchain_image_index)); - VK_CHECK(vkWaitForFences(vk.device, 1, &vk.rendering_finished_fence, VK_FALSE, 1e9)); - VK_CHECK(vkResetFences(vk.device, 1, &vk.rendering_finished_fence)); + VK_CHECK(vkWaitForFences(vk.device, 1, &vk.rendering_finished_fence, VK_FALSE, 1e9)); + VK_CHECK(vkResetFences(vk.device, 1, &vk.rendering_finished_fence)); VkCommandBufferBeginInfo begin_info; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -2198,7 +2198,7 @@ void vk_begin_frame() { begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; begin_info.pInheritanceInfo = nullptr; - VK_CHECK(vkBeginCommandBuffer(vk.command_buffer, &begin_info)); + VK_CHECK(vkBeginCommandBuffer(vk.command_buffer, &begin_info)); // Ensure visibility of geometry buffers writes. record_buffer_memory_barrier(vk.command_buffer, vk.vertex_buffer, @@ -2227,43 +2227,43 @@ void vk_begin_frame() { vkCmdBeginRenderPass(vk.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); - vk_resources.dirty_attachments = false; + vk_resources.dirty_attachments = false; vk.xyz_elements = 0; vk.color_st_elements = 0; vk.index_buffer_offset = 0; } void vk_end_frame() { - if (!vk.active) - return; + if (!vk.active) + return; - vkCmdEndRenderPass(vk.command_buffer); - VK_CHECK(vkEndCommandBuffer(vk.command_buffer)); + vkCmdEndRenderPass(vk.command_buffer); + VK_CHECK(vkEndCommandBuffer(vk.command_buffer)); - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = nullptr; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &vk.image_acquired; - submit_info.pWaitDstStageMask = &wait_dst_stage_mask; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &vk.command_buffer; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &vk.rendering_finished; + VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = &vk.image_acquired; + submit_info.pWaitDstStageMask = &wait_dst_stage_mask; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &vk.command_buffer; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &vk.rendering_finished; - VK_CHECK(vkQueueSubmit(vk.queue, 1, &submit_info, vk.rendering_finished_fence)); + VK_CHECK(vkQueueSubmit(vk.queue, 1, &submit_info, vk.rendering_finished_fence)); - VkPresentInfoKHR present_info; - present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - present_info.pNext = nullptr; - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &vk.rendering_finished; - present_info.swapchainCount = 1; - present_info.pSwapchains = &vk.swapchain; - present_info.pImageIndices = &vk.swapchain_image_index; - present_info.pResults = nullptr; - VK_CHECK(vkQueuePresentKHR(vk.queue, &present_info)); + VkPresentInfoKHR present_info; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.pNext = nullptr; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &vk.rendering_finished; + present_info.swapchainCount = 1; + present_info.pSwapchains = &vk.swapchain; + present_info.pImageIndices = &vk.swapchain_image_index; + present_info.pResults = nullptr; + VK_CHECK(vkQueuePresentKHR(vk.queue, &present_info)); } void vk_read_pixels(byte* buffer) { diff --git a/src/engine/renderer/vk.h b/src/engine/renderer/vk.h index df733f5..b61378c 100644 --- a/src/engine/renderer/vk.h +++ b/src/engine/renderer/vk.h @@ -17,15 +17,15 @@ const int IMAGE_CHUNK_SIZE = 32 * 1024 * 1024; const int MAX_IMAGE_CHUNKS = 16; #define VK_CHECK(function_call) { \ - VkResult result = function_call; \ - if (result < 0) \ - ri.Error(ERR_FATAL, "Vulkan error: function %s, error code %d", #function_call, result); \ + VkResult result = function_call; \ + if (result < 0) \ + ri.Error(ERR_FATAL, "Vulkan error: function %s, error code %d", #function_call, result); \ } enum class Vk_Shader_Type { - single_texture, - multi_texture_mul, - multi_texture_add + single_texture, + multi_texture_mul, + multi_texture_add }; // used with cg_shadows == 2 @@ -43,29 +43,29 @@ enum class Vk_Depth_Range { }; struct Vk_Sampler_Def { - bool repeat_texture = false; // clamp/repeat texture addressing mode - int gl_mag_filter = 0; // GL_XXX mag filter - int gl_min_filter = 0; // GL_XXX min filter + bool repeat_texture = false; // clamp/repeat texture addressing mode + int gl_mag_filter = 0; // GL_XXX mag filter + int gl_min_filter = 0; // GL_XXX min filter }; struct Vk_Pipeline_Def { - Vk_Shader_Type shader_type = Vk_Shader_Type::single_texture; - unsigned int state_bits = 0; // GLS_XXX flags - int face_culling = 0;// cullType_t - bool polygon_offset = false; - bool clipping_plane = false; - bool mirror = false; + Vk_Shader_Type shader_type = Vk_Shader_Type::single_texture; + unsigned int state_bits = 0; // GLS_XXX flags + int face_culling = 0;// cullType_t + bool polygon_offset = false; + bool clipping_plane = false; + bool mirror = false; bool line_primitives = false; Vk_Shadow_Phase shadow_phase = Vk_Shadow_Phase::disabled; }; struct Vk_Image { - VkImage handle = VK_NULL_HANDLE; - VkImageView view = VK_NULL_HANDLE; + VkImage handle = VK_NULL_HANDLE; + VkImageView view = VK_NULL_HANDLE; - // Descriptor set that contains single descriptor used to access the given image. - // It is updated only once during image initialization. - VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + // Descriptor set that contains single descriptor used to access the given image. + // It is updated only once during image initialization. + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; }; // @@ -106,77 +106,77 @@ void vk_read_pixels(byte* buffer); // Vulkan specific structures used by the engine. struct Vk_Instance { - bool active = false; - VkInstance instance = VK_NULL_HANDLE; - VkPhysicalDevice physical_device = VK_NULL_HANDLE; - VkSurfaceKHR surface = VK_NULL_HANDLE; - VkSurfaceFormatKHR surface_format = {}; + bool active = false; + 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; + 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]; + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + uint32_t swapchain_image_count = 0; + VkImage swapchain_images[MAX_SWAPCHAIN_IMAGES]; + VkImageView swapchain_image_views[MAX_SWAPCHAIN_IMAGES]; - VkCommandPool command_pool = VK_NULL_HANDLE; - VkCommandBuffer command_buffer = VK_NULL_HANDLE; + VkCommandPool command_pool = VK_NULL_HANDLE; + VkCommandBuffer command_buffer = VK_NULL_HANDLE; - VkImage depth_image = VK_NULL_HANDLE; - VkDeviceMemory depth_image_memory = VK_NULL_HANDLE; - VkImageView depth_image_view = VK_NULL_HANDLE; + VkImage depth_image = VK_NULL_HANDLE; + VkDeviceMemory depth_image_memory = VK_NULL_HANDLE; + VkImageView depth_image_view = VK_NULL_HANDLE; - VkRenderPass render_pass = VK_NULL_HANDLE; - VkFramebuffer framebuffers[MAX_SWAPCHAIN_IMAGES]; + VkRenderPass render_pass = VK_NULL_HANDLE; + VkFramebuffer framebuffers[MAX_SWAPCHAIN_IMAGES]; - VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; - VkDescriptorSetLayout set_layout = VK_NULL_HANDLE; - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; + VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; + VkDescriptorSetLayout set_layout = VK_NULL_HANDLE; + VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - VkBuffer vertex_buffer = VK_NULL_HANDLE; - byte* vertex_buffer_ptr = nullptr; // pointer to mapped vertex buffer - int xyz_elements = 0; - int color_st_elements = 0; + VkBuffer vertex_buffer = VK_NULL_HANDLE; + byte* vertex_buffer_ptr = nullptr; // pointer to mapped vertex buffer + int xyz_elements = 0; + int color_st_elements = 0; - VkBuffer index_buffer = VK_NULL_HANDLE; - byte* index_buffer_ptr = nullptr; // pointer to mapped index buffer - VkDeviceSize index_buffer_offset = 0; + VkBuffer index_buffer = VK_NULL_HANDLE; + byte* index_buffer_ptr = nullptr; // pointer to mapped index buffer + VkDeviceSize index_buffer_offset = 0; - // host visible memory that holds both vertex and index data - VkDeviceMemory geometry_buffer_memory = VK_NULL_HANDLE; + // host visible memory that holds both vertex and index data + VkDeviceMemory geometry_buffer_memory = VK_NULL_HANDLE; - VkSemaphore image_acquired = VK_NULL_HANDLE; - uint32_t swapchain_image_index = -1; + VkSemaphore image_acquired = VK_NULL_HANDLE; + uint32_t swapchain_image_index = -1; - VkSemaphore rendering_finished = VK_NULL_HANDLE; - VkFence rendering_finished_fence = VK_NULL_HANDLE; + VkSemaphore rendering_finished = VK_NULL_HANDLE; + VkFence rendering_finished_fence = VK_NULL_HANDLE; - VkShaderModule single_texture_vs = VK_NULL_HANDLE; - VkShaderModule single_texture_clipping_plane_vs = VK_NULL_HANDLE; - VkShaderModule single_texture_fs = VK_NULL_HANDLE; - VkShaderModule multi_texture_vs = VK_NULL_HANDLE; - VkShaderModule multi_texture_clipping_plane_vs = VK_NULL_HANDLE; - VkShaderModule multi_texture_mul_fs = VK_NULL_HANDLE; - VkShaderModule multi_texture_add_fs = VK_NULL_HANDLE; + VkShaderModule single_texture_vs = VK_NULL_HANDLE; + VkShaderModule single_texture_clipping_plane_vs = VK_NULL_HANDLE; + VkShaderModule single_texture_fs = VK_NULL_HANDLE; + VkShaderModule multi_texture_vs = VK_NULL_HANDLE; + VkShaderModule multi_texture_clipping_plane_vs = VK_NULL_HANDLE; + VkShaderModule multi_texture_mul_fs = VK_NULL_HANDLE; + VkShaderModule multi_texture_add_fs = VK_NULL_HANDLE; - VkPipeline skybox_pipeline = VK_NULL_HANDLE; + VkPipeline skybox_pipeline = VK_NULL_HANDLE; // dim 0: 0 - front side, 1 - back size // dim 1: 0 - normal view, 1 - mirror view VkPipeline shadow_volume_pipelines[2][2]; VkPipeline shadow_finish_pipeline; - // dim 0 is based on fogPass_t: 0 - corresponds to FP_EQUAL, 1 - corresponds to FP_LE. - // dim 1 is directly a cullType_t enum value. - // dim 2 is a polygon offset value (0 - off, 1 - on). - VkPipeline fog_pipelines[2][3][2]; + // dim 0 is based on fogPass_t: 0 - corresponds to FP_EQUAL, 1 - corresponds to FP_LE. + // dim 1 is directly a cullType_t enum value. + // dim 2 is a polygon offset value (0 - off, 1 - on). + VkPipeline fog_pipelines[2][3][2]; - // dim 0 is based on dlight additive flag: 0 - not additive, 1 - additive - // dim 1 is directly a cullType_t enum value. - // dim 2 is a polygon offset value (0 - off, 1 - on). - VkPipeline dlight_pipelines[2][3][2]; + // dim 0 is based on dlight additive flag: 0 - not additive, 1 - additive + // dim 1 is directly a cullType_t enum value. + // dim 2 is a polygon offset value (0 - off, 1 - on). + VkPipeline dlight_pipelines[2][3][2]; VkPipeline tris_debug_pipeline; VkPipeline tris_mirror_debug_pipeline; @@ -187,48 +187,48 @@ struct Vk_Instance { }; struct Vk_Resources { - // - // Resources. - // - int num_samplers = 0; - Vk_Sampler_Def sampler_defs[MAX_VK_SAMPLERS]; - VkSampler samplers[MAX_VK_SAMPLERS]; + // + // Resources. + // + int num_samplers = 0; + Vk_Sampler_Def sampler_defs[MAX_VK_SAMPLERS]; + VkSampler samplers[MAX_VK_SAMPLERS]; - int num_pipelines = 0; - Vk_Pipeline_Def pipeline_defs[MAX_VK_PIPELINES]; - VkPipeline pipelines[MAX_VK_PIPELINES]; + int num_pipelines = 0; + Vk_Pipeline_Def pipeline_defs[MAX_VK_PIPELINES]; + VkPipeline pipelines[MAX_VK_PIPELINES]; float pipeline_create_time; - Vk_Image images[MAX_VK_IMAGES]; + Vk_Image images[MAX_VK_IMAGES]; - // - // Memory allocations. - // - struct Chunk { - VkDeviceMemory memory = VK_NULL_HANDLE; - VkDeviceSize used = 0; - }; + // + // Memory allocations. + // + struct Chunk { + VkDeviceMemory memory = VK_NULL_HANDLE; + VkDeviceSize used = 0; + }; - int num_image_chunks = 0; - Chunk image_chunks[MAX_IMAGE_CHUNKS]; + int num_image_chunks = 0; + Chunk image_chunks[MAX_IMAGE_CHUNKS]; - // Host visible memory used to copy image data to device local memory. - VkBuffer staging_buffer = VK_NULL_HANDLE; - VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE; - VkDeviceSize staging_buffer_size = 0; - byte* staging_buffer_ptr = nullptr; // pointer to mapped staging buffer + // Host visible memory used to copy image data to device local memory. + VkBuffer staging_buffer = VK_NULL_HANDLE; + VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE; + VkDeviceSize staging_buffer_size = 0; + byte* staging_buffer_ptr = nullptr; // pointer to mapped staging buffer - // - // State. - // + // + // State. + // - // Descriptor sets corresponding to bound texture images. - VkDescriptorSet current_descriptor_sets[2]; + // Descriptor sets corresponding to bound texture images. + VkDescriptorSet current_descriptor_sets[2]; - // This flag is used to decide whether framebuffer's attachments should be cleared - // with vmCmdClearAttachment (dirty_attachments == true), or they have just been - // cleared by render pass instance clear op (dirty_attachments == false). - bool dirty_attachments; + // This flag is used to decide whether framebuffer's attachments should be cleared + // with vmCmdClearAttachment (dirty_attachments == true), or they have just been + // cleared by render pass instance clear op (dirty_attachments == false). + bool dirty_attachments; float modelview_transform[16]; };