SuperTuxKart 1.5 upstream source (from official release tarball)

This commit is contained in:
Benjamin
2026-06-11 20:04:02 +02:00
commit 2957e51aaa
8551 changed files with 1801800 additions and 0 deletions
@@ -0,0 +1,391 @@
#include "ge_vulkan_hiz_depth.hpp"
#include "ge_main.hpp"
#include "ge_vulkan_array_texture.hpp"
#include "ge_vulkan_attachment_texture.hpp"
#include "ge_vulkan_camera_scene_node.hpp"
#include "ge_vulkan_deferred_fbo.hpp"
#include "ge_vulkan_driver.hpp"
#include "ge_vulkan_shader_manager.hpp"
#include <algorithm>
#include <stdexcept>
namespace GE
{
// ----------------------------------------------------------------------------
GEVulkanHiZDepth::GEVulkanHiZDepth(GEVulkanDriver* vk)
: m_vk(vk), m_hiz_depth(NULL),
m_descriptor_layout(VK_NULL_HANDLE),
m_pipeline_layout(VK_NULL_HANDLE),
m_pipeline(VK_NULL_HANDLE),
m_descriptor_pool(VK_NULL_HANDLE),
m_rendering_descriptor_pool(VK_NULL_HANDLE),
m_rendering_descriptor_set(VK_NULL_HANDLE)
{
} // GEVulkanHiZDepth
// ----------------------------------------------------------------------------
GEVulkanHiZDepth::~GEVulkanHiZDepth()
{
destroy();
} // ~GEVulkanHiZDepth
// ----------------------------------------------------------------------------
void GEVulkanHiZDepth::prepare(GEVulkanCameraSceneNode* cam)
{
irr::core::recti hiz_size(irr::core::position2di(
cam->getUBOData()->m_viewport.UpperLeftCorner.X,
cam->getUBOData()->m_viewport.UpperLeftCorner.Y),
irr::core::dimension2du(
cam->getUBOData()->m_viewport.LowerRightCorner.X,
cam->getUBOData()->m_viewport.LowerRightCorner.Y));
if (m_hiz_size != hiz_size)
{
m_hiz_size = hiz_size;
destroy();
init();
}
} // prepare
// ----------------------------------------------------------------------------
void GEVulkanHiZDepth::init()
{
m_hiz_depth = new GEVulkanArrayTexture(VK_FORMAT_R32_SFLOAT,
VK_IMAGE_VIEW_TYPE_2D,
irr::core::dimension2du(m_hiz_size.getWidth(), m_hiz_size.getHeight()),
1, irr::video::SColor(0), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {};
// Input depth buffer
bindings[0].binding = 0;
bindings[0].descriptorCount = 1;
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
// Output storage image
bindings[1].binding = 1;
bindings[1].descriptorCount = 1;
bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
VkDescriptorSetLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layout_info.bindingCount = bindings.size();
layout_info.pBindings = bindings.data();
VkDevice device = m_vk->getDevice();
if (vkCreateDescriptorSetLayout(device, &layout_info, NULL,
&m_descriptor_layout) != VK_SUCCESS)
{
throw std::runtime_error("Failed to create descriptor set layout for "
"HiZ depth");
}
VkPushConstantRange push_constant = {};
push_constant.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
push_constant.offset = 0;
push_constant.size = sizeof(uint32_t) * 3;
VkPipelineLayoutCreateInfo pipeline_layout_info = {};
pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_layout_info.setLayoutCount = 1;
pipeline_layout_info.pSetLayouts = &m_descriptor_layout;
pipeline_layout_info.pushConstantRangeCount = 1;
pipeline_layout_info.pPushConstantRanges = &push_constant;
if (vkCreatePipelineLayout(device, &pipeline_layout_info, NULL,
&m_pipeline_layout) != VK_SUCCESS)
{
throw std::runtime_error("Failed to create pipeline layout for HiZ "
"depth");
}
VkComputePipelineCreateInfo pipeline_info = {};
pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
pipeline_info.stage.module = GEVulkanShaderManager::getShader("hiz_depth.comp");
pipeline_info.stage.pName = "main";
pipeline_info.layout = m_pipeline_layout;
if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1,
&pipeline_info, NULL, &m_pipeline) != VK_SUCCESS)
{
throw std::runtime_error("Failed to create compute pipeline for HiZ "
"depth");
}
// Create descriptor pool
const uint32_t mip_levels = m_hiz_depth->getMipmapLevels();
std::array<VkDescriptorPoolSize, 2> pool_sizes = {};
pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
pool_sizes[0].descriptorCount = mip_levels;
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
pool_sizes[1].descriptorCount = mip_levels;
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.maxSets = mip_levels;
pool_info.poolSizeCount = pool_sizes.size();
pool_info.pPoolSizes = pool_sizes.data();
if (vkCreateDescriptorPool(device, &pool_info, NULL,
&m_descriptor_pool) != VK_SUCCESS)
{
throw std::runtime_error("Failed to create descriptor pool for HiZ depth");
}
// Create descriptor sets for each mip level
m_descriptor_sets.resize(mip_levels);
std::vector<VkDescriptorSetLayout> layouts(mip_levels,
m_descriptor_layout);
VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = m_descriptor_pool;
alloc_info.descriptorSetCount = m_descriptor_sets.size();
alloc_info.pSetLayouts = layouts.data();
if (vkAllocateDescriptorSets(device, &alloc_info,
m_descriptor_sets.data()) != VK_SUCCESS)
{
throw std::runtime_error("Failed to allocate descriptor sets for HiZ "
"depth");
}
// Create image views for each mip level
m_hiz_views.resize(mip_levels);
for (uint32_t i = 0; i < m_hiz_views.size(); i++)
{
VkImageViewCreateInfo view_info = {};
view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_info.image = m_hiz_depth->getImage();
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
view_info.format = m_hiz_depth->getInternalFormat();
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
view_info.subresourceRange.baseMipLevel = i;
view_info.subresourceRange.levelCount = 1;
view_info.subresourceRange.baseArrayLayer = 0;
view_info.subresourceRange.layerCount = 1;
if (vkCreateImageView(device, &view_info, NULL,
&m_hiz_views[i]) != VK_SUCCESS)
{
throw std::runtime_error("Failed to create image view for HiZ "
"depth");
}
}
GEVulkanDeferredFBO* dfbo =
static_cast<GEVulkanDeferredFBO*>(m_vk->getRTTTexture());
for (uint32_t i = 0; i < mip_levels; i++)
{
VkDescriptorImageInfo input_info = {};
input_info.imageLayout = i == 0 ?
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL :
VK_IMAGE_LAYOUT_GENERAL;
input_info.imageView = i == 0 ?
(VkImageView)dfbo->getDepthTexture()->getTextureHandler() :
(VkImageView)m_hiz_depth->getTextureHandler();
input_info.sampler = m_vk->getSampler(GVS_SKYBOX);
VkDescriptorImageInfo output_info = {};
output_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
output_info.imageView = m_hiz_views[i];
std::array<VkWriteDescriptorSet, 2> descriptor_writes = {};
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_writes[0].dstSet = m_descriptor_sets[i];
descriptor_writes[0].dstBinding = 0;
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptor_writes[0].descriptorCount = 1;
descriptor_writes[0].pImageInfo = &input_info;
descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_writes[1].dstSet = m_descriptor_sets[i];
descriptor_writes[1].dstBinding = 1;
descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
descriptor_writes[1].descriptorCount = 1;
descriptor_writes[1].pImageInfo = &output_info;
vkUpdateDescriptorSets(m_vk->getDevice(), descriptor_writes.size(),
descriptor_writes.data(), 0, NULL);
}
loadRenderingDescriptor();
} // init
// ----------------------------------------------------------------------------
void GEVulkanHiZDepth::loadRenderingDescriptor()
{
const size_t displace_binding_count = 3;
VkDescriptorPoolSize pool_size;
pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
pool_size.descriptorCount = displace_binding_count;
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = 0;
pool_info.maxSets = 1;
pool_info.poolSizeCount = 1;
pool_info.pPoolSizes = &pool_size;
if (vkCreateDescriptorPool(m_vk->getDevice(), &pool_info, NULL,
&m_rendering_descriptor_pool) != VK_SUCCESS)
{
throw std::runtime_error("vkCreateDescriptorPool failed for "
"m_rendering_descriptor_pool in GEVulkanHiZDepth");
}
GEVulkanDeferredFBO* dfbo =
static_cast<GEVulkanDeferredFBO*>(m_vk->getRTTTexture());
std::vector<VkDescriptorSetLayout> layouts(1,
dfbo->getDescriptorSetLayout(GVDFP_DISPLACE_COLOR));
VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = m_rendering_descriptor_pool;
alloc_info.descriptorSetCount = layouts.size();
alloc_info.pSetLayouts = layouts.data();
if (vkAllocateDescriptorSets(m_vk->getDevice(), &alloc_info,
&m_rendering_descriptor_set) != VK_SUCCESS)
{
throw std::runtime_error("vkAllocateDescriptorSets failed for "
"m_rendering_descriptor_set in GEVulkanHiZDepth");
}
std::array<VkDescriptorImageInfo, displace_binding_count> image_infos = {};
image_infos[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
image_infos[0].imageView =
(VkImageView)
dfbo->getAttachment<GVDFT_DISPLACE_COLOR>()->getTextureHandler();
image_infos[0].sampler = m_vk->getSampler(GVS_NEAREST);
image_infos[1].imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
image_infos[1].imageView =
(VkImageView)dfbo->getDepthTexture()->getTextureHandler();
image_infos[1].sampler = m_vk->getSampler(GVS_SHADOW);
image_infos[2].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
image_infos[2].imageView =
(VkImageView)m_hiz_depth->getTextureHandler();
image_infos[2].sampler = m_vk->getSampler(GVS_SKYBOX);
VkWriteDescriptorSet write_descriptor_set = {};
write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor_set.dstBinding = 0;
write_descriptor_set.dstArrayElement = 0;
write_descriptor_set.descriptorType =
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write_descriptor_set.descriptorCount = image_infos.size();
write_descriptor_set.pBufferInfo = 0;
write_descriptor_set.dstSet = m_rendering_descriptor_set;
write_descriptor_set.pImageInfo = image_infos.data();
vkUpdateDescriptorSets(m_vk->getDevice(), 1, &write_descriptor_set, 0,
NULL);
} // loadRenderingDescriptor
// ----------------------------------------------------------------------------
void GEVulkanHiZDepth::destroy()
{
delete m_hiz_depth;
m_hiz_depth = NULL;
VkDevice device = m_vk->getDevice();
if (m_pipeline != VK_NULL_HANDLE)
vkDestroyPipeline(device, m_pipeline, NULL);
m_pipeline = VK_NULL_HANDLE;
if (m_pipeline_layout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(device, m_pipeline_layout, NULL);
m_pipeline_layout = VK_NULL_HANDLE;
if (m_rendering_descriptor_pool != VK_NULL_HANDLE)
vkDestroyDescriptorPool(device, m_rendering_descriptor_pool, NULL);
m_rendering_descriptor_pool = VK_NULL_HANDLE;
m_rendering_descriptor_set = VK_NULL_HANDLE;
if (m_descriptor_pool != VK_NULL_HANDLE)
vkDestroyDescriptorPool(device, m_descriptor_pool, NULL);
m_descriptor_pool = VK_NULL_HANDLE;
if (m_descriptor_layout != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(device, m_descriptor_layout, NULL);
m_descriptor_layout = VK_NULL_HANDLE;
for (VkImageView view : m_hiz_views)
vkDestroyImageView(device, view, NULL);
m_hiz_views.clear();
m_descriptor_sets.clear();
} // destroy
// ----------------------------------------------------------------------------
void GEVulkanHiZDepth::generate(VkCommandBuffer cmd)
{
const uint32_t mip_levels = m_hiz_depth->getMipmapLevels();
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = m_hiz_depth->getImage();
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = mip_levels;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(cmd,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0, NULL, 0, NULL, 1, &barrier);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
vkCmdPushConstants(cmd, m_pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(uint32_t) * 2, &m_hiz_size.UpperLeftCorner.X);
for (uint32_t i = 0; i < mip_levels; i++)
{
// Bind descriptor set and push mip level constant
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE,
m_pipeline_layout, 0, 1, &m_descriptor_sets[i], 0, NULL);
vkCmdPushConstants(cmd, m_pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT,
sizeof(uint32_t) * 2, sizeof(uint32_t), &i);
// Calculate dispatch size based on current mip level dimensions
const uint32_t width = m_hiz_depth->getSize().Width >> i;
const uint32_t height = m_hiz_depth->getSize().Height >> i;
const uint32_t group_size_x = std::max(1u, (width + 15) / 16);
const uint32_t group_size_y = std::max(1u, (height + 15) / 16);
vkCmdDispatch(cmd, group_size_x, group_size_y, 1);
// Add memory barrier between mip level generations
if (i < mip_levels - 1)
{
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.subresourceRange.baseMipLevel = i;
barrier.subresourceRange.levelCount = 1;
vkCmdPipelineBarrier(cmd,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0, NULL, 0, NULL, 1, &barrier);
}
}
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = mip_levels;
vkCmdPipelineBarrier(cmd,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
0, 0, NULL, 0, NULL, 1, &barrier);
} // generate
}