Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental

This commit is contained in:
Gliniak
2025-08-15 15:37:50 +02:00
78 changed files with 3438 additions and 2888 deletions

View File

@@ -18,6 +18,7 @@
#include "xenia/gpu/texture_util.h"
#include "xenia/gpu/vulkan/deferred_command_buffer.h"
#include "xenia/gpu/vulkan/vulkan_command_processor.h"
#include "xenia/ui/vulkan/ui_samplers.h"
#include "xenia/ui/vulkan/vulkan_mem_alloc.h"
#include "xenia/ui/vulkan/vulkan_util.h"
@@ -419,10 +420,10 @@ constexpr VulkanTextureCache::HostFormatPair
true};
VulkanTextureCache::~VulkanTextureCache() {
const ui::vulkan::VulkanProvider& provider =
command_processor_.GetVulkanProvider();
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const ui::vulkan::VulkanDevice* const vulkan_device =
command_processor_.GetVulkanDevice();
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
const VkDevice device = vulkan_device->device();
for (const std::pair<const SamplerParameters, Sampler>& sampler_pair :
samplers_) {
@@ -519,9 +520,9 @@ void VulkanTextureCache::BeginSubmission(uint64_t new_submission_index) {
}
void VulkanTextureCache::RequestTextures(uint32_t used_texture_mask) {
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
SCOPE_profile_cpu_f("gpu");
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
TextureCache::RequestTextures(used_texture_mask);
@@ -714,10 +715,10 @@ VkSampler VulkanTextureCache::UseSampler(SamplerParameters parameters,
return sampler.second.sampler;
}
const ui::vulkan::VulkanProvider& provider =
command_processor_.GetVulkanProvider();
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const ui::vulkan::VulkanDevice* const vulkan_device =
command_processor_.GetVulkanDevice();
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
const VkDevice device = vulkan_device->device();
// See if an existing sampler can be destroyed to create space for the new
// one.
@@ -757,7 +758,7 @@ VkSampler VulkanTextureCache::UseSampler(SamplerParameters parameters,
// GetSamplerParameters.
VkSamplerCreateInfo sampler_create_info = {};
sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
if (provider.device_info().nonSeamlessCubeMap &&
if (vulkan_device->properties().nonSeamlessCubeMap &&
cvars::non_seamless_cube_map) {
sampler_create_info.flags |=
VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT;
@@ -936,17 +937,17 @@ uint32_t VulkanTextureCache::GetHostFormatSwizzle(TextureKey key) const {
uint32_t VulkanTextureCache::GetMaxHostTextureWidthHeight(
xenos::DataDimension dimension) const {
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
command_processor_.GetVulkanProvider().device_info();
const ui::vulkan::VulkanDevice::Properties& device_properties =
command_processor_.GetVulkanDevice()->properties();
switch (dimension) {
case xenos::DataDimension::k1D:
case xenos::DataDimension::k2DOrStacked:
// 1D and 2D are emulated as 2D arrays.
return device_info.maxImageDimension2D;
return device_properties.maxImageDimension2D;
case xenos::DataDimension::k3D:
return device_info.maxImageDimension3D;
return device_properties.maxImageDimension3D;
case xenos::DataDimension::kCube:
return device_info.maxImageDimensionCube;
return device_properties.maxImageDimensionCube;
default:
assert_unhandled_case(dimension);
return 0;
@@ -955,15 +956,15 @@ uint32_t VulkanTextureCache::GetMaxHostTextureWidthHeight(
uint32_t VulkanTextureCache::GetMaxHostTextureDepthOrArraySize(
xenos::DataDimension dimension) const {
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
command_processor_.GetVulkanProvider().device_info();
const ui::vulkan::VulkanDevice::Properties& device_properties =
command_processor_.GetVulkanDevice()->properties();
switch (dimension) {
case xenos::DataDimension::k1D:
case xenos::DataDimension::k2DOrStacked:
// 1D and 2D are emulated as 2D arrays.
return device_info.maxImageArrayLayers;
return device_properties.maxImageArrayLayers;
case xenos::DataDimension::k3D:
return device_info.maxImageDimension3D;
return device_properties.maxImageDimension3D;
case xenos::DataDimension::kCube:
// Not requesting the imageCubeArray feature, and the Xenos doesn't
// support cube map arrays.
@@ -1005,10 +1006,10 @@ std::unique_ptr<TextureCache::Texture> VulkanTextureCache::CreateTexture(
return nullptr;
}
const ui::vulkan::VulkanProvider& provider =
command_processor_.GetVulkanProvider();
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const ui::vulkan::VulkanDevice* const vulkan_device =
command_processor_.GetVulkanDevice();
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
const VkDevice device = vulkan_device->device();
bool is_3d = key.dimension == xenos::DataDimension::k3D;
uint32_t depth_or_array_size = key.GetDepthOrArraySize();
@@ -1045,7 +1046,7 @@ std::unique_ptr<TextureCache::Texture> VulkanTextureCache::CreateTexture(
image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageFormatListCreateInfo image_format_list_create_info;
if (formats[1] != VK_FORMAT_UNDEFINED &&
provider.device_info().ext_1_2_VK_KHR_image_format_list) {
vulkan_device->extensions().ext_1_2_KHR_image_format_list) {
image_create_info_last->pNext = &image_format_list_create_info;
image_create_info_last =
reinterpret_cast<VkImageCreateInfo*>(&image_format_list_create_info);
@@ -1220,10 +1221,10 @@ bool VulkanTextureCache::LoadTextureDataFromResidentMemoryImpl(Texture& texture,
// Begin loading.
// TODO(Triang3l): Going from one descriptor to another on per-array-layer
// or even per-8-depth-slices level to stay within maxStorageBufferRange.
const ui::vulkan::VulkanProvider& provider =
command_processor_.GetVulkanProvider();
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const ui::vulkan::VulkanDevice* const vulkan_device =
command_processor_.GetVulkanDevice();
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
const VkDevice device = vulkan_device->device();
VulkanSharedMemory& vulkan_shared_memory =
static_cast<VulkanSharedMemory&>(shared_memory());
std::array<VkWriteDescriptorSet, 3> write_descriptor_sets;
@@ -1586,10 +1587,10 @@ VulkanTextureCache::VulkanTexture::VulkanTexture(
VulkanTextureCache::VulkanTexture::~VulkanTexture() {
const VulkanTextureCache& vulkan_texture_cache =
static_cast<const VulkanTextureCache&>(texture_cache());
const ui::vulkan::VulkanProvider& provider =
vulkan_texture_cache.command_processor_.GetVulkanProvider();
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const ui::vulkan::VulkanDevice* const vulkan_device =
vulkan_texture_cache.command_processor_.GetVulkanDevice();
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
const VkDevice device = vulkan_device->device();
for (const auto& view_pair : views_) {
dfn.vkDestroyImageView(device, view_pair.second, nullptr);
}
@@ -1627,9 +1628,10 @@ VkImageView VulkanTextureCache::VulkanTexture::GetView(bool is_signed,
is_signed && (host_format_pair.format_signed.format !=
host_format_pair.format_unsigned.format);
const ui::vulkan::VulkanProvider& provider =
vulkan_texture_cache.command_processor_.GetVulkanProvider();
if (!provider.device_info().imageViewFormatSwizzle) {
const ui::vulkan::VulkanDevice* const vulkan_device =
vulkan_texture_cache.command_processor_.GetVulkanDevice();
if (!vulkan_device->properties().imageViewFormatSwizzle) {
host_swizzle = xenos::XE_GPU_TEXTURE_SWIZZLE_RGBA;
}
view_key.host_swizzle = host_swizzle;
@@ -1643,8 +1645,8 @@ VkImageView VulkanTextureCache::VulkanTexture::GetView(bool is_signed,
}
// Create a new view.
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
const VkDevice device = vulkan_device->device();
VkImageViewCreateInfo view_create_info;
view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_create_info.pNext = nullptr;
@@ -1700,18 +1702,19 @@ VulkanTextureCache::VulkanTextureCache(
}
bool VulkanTextureCache::Initialize() {
const ui::vulkan::VulkanProvider& provider =
command_processor_.GetVulkanProvider();
const ui::vulkan::VulkanProvider::InstanceFunctions& ifn = provider.ifn();
VkPhysicalDevice physical_device = provider.physical_device();
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
provider.device_info();
const ui::vulkan::VulkanDevice* const vulkan_device =
command_processor_.GetVulkanDevice();
const ui::vulkan::VulkanInstance::Functions& ifn =
vulkan_device->vulkan_instance()->functions();
const VkPhysicalDevice physical_device = vulkan_device->physical_device();
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
const VkDevice device = vulkan_device->device();
const ui::vulkan::VulkanDevice::Properties& device_properties =
vulkan_device->properties();
// Vulkan Memory Allocator.
vma_allocator_ = ui::vulkan::CreateVmaAllocator(provider, true);
vma_allocator_ = ui::vulkan::CreateVmaAllocator(vulkan_device, true);
if (vma_allocator_ == VK_NULL_HANDLE) {
return false;
}
@@ -2319,7 +2322,7 @@ bool VulkanTextureCache::Initialize() {
load_shader_code[i];
assert_not_null(current_load_shader_code.first);
load_pipelines_[i] = ui::vulkan::util::CreateComputePipeline(
provider, load_pipeline_layout_, current_load_shader_code.first,
vulkan_device, load_pipeline_layout_, current_load_shader_code.first,
current_load_shader_code.second);
if (load_pipelines_[i] == VK_NULL_HANDLE) {
XELOGE(
@@ -2333,7 +2336,7 @@ bool VulkanTextureCache::Initialize() {
current_load_shader_code_scaled = load_shader_code_scaled[i];
if (current_load_shader_code_scaled.first) {
load_pipelines_scaled_[i] = ui::vulkan::util::CreateComputePipeline(
provider, load_pipeline_layout_,
vulkan_device, load_pipeline_layout_,
current_load_shader_code_scaled.first,
current_load_shader_code_scaled.second);
if (load_pipelines_scaled_[i] == VK_NULL_HANDLE) {
@@ -2398,7 +2401,7 @@ bool VulkanTextureCache::Initialize() {
dfn.vkGetImageMemoryRequirements(device, null_image_3d_,
&null_image_memory_requirements_3d_);
uint32_t null_image_memory_type_common = ui::vulkan::util::ChooseMemoryType(
provider,
vulkan_device->memory_types(),
null_image_memory_requirements_2d_array_cube_.memoryTypeBits &
null_image_memory_requirements_3d_.memoryTypeBits,
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
@@ -2439,16 +2442,18 @@ bool VulkanTextureCache::Initialize() {
}
} else {
// Place each null image in separate allocations.
uint32_t null_image_memory_type_2d_array_cube_ =
const uint32_t null_image_memory_type_2d_array_cube =
ui::vulkan::util::ChooseMemoryType(
provider,
vulkan_device->memory_types(),
null_image_memory_requirements_2d_array_cube_.memoryTypeBits,
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
uint32_t null_image_memory_type_3d_ = ui::vulkan::util::ChooseMemoryType(
provider, null_image_memory_requirements_3d_.memoryTypeBits,
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
if (null_image_memory_type_2d_array_cube_ == UINT32_MAX ||
null_image_memory_type_3d_ == UINT32_MAX) {
const uint32_t null_image_memory_type_3d =
ui::vulkan::util::ChooseMemoryType(
vulkan_device->memory_types(),
null_image_memory_requirements_3d_.memoryTypeBits,
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
if (null_image_memory_type_2d_array_cube == UINT32_MAX ||
null_image_memory_type_3d == UINT32_MAX) {
XELOGE(
"VulkanTextureCache: Failed to get the memory types for the null "
"images");
@@ -2464,9 +2469,9 @@ bool VulkanTextureCache::Initialize() {
null_image_memory_allocate_info.allocationSize =
null_image_memory_requirements_2d_array_cube_.size;
null_image_memory_allocate_info.memoryTypeIndex =
null_image_memory_type_2d_array_cube_;
null_image_memory_type_2d_array_cube;
VkMemoryDedicatedAllocateInfo null_image_memory_dedicated_allocate_info;
if (device_info.ext_1_1_VK_KHR_dedicated_allocation) {
if (vulkan_device->extensions().ext_1_1_KHR_dedicated_allocation) {
null_image_memory_allocate_info_last->pNext =
&null_image_memory_dedicated_allocate_info;
null_image_memory_allocate_info_last =
@@ -2496,8 +2501,7 @@ bool VulkanTextureCache::Initialize() {
null_image_memory_allocate_info.allocationSize =
null_image_memory_requirements_3d_.size;
null_image_memory_allocate_info.memoryTypeIndex =
null_image_memory_type_3d_;
null_image_memory_allocate_info.memoryTypeIndex = null_image_memory_type_3d;
null_image_memory_dedicated_allocate_info.image = null_image_3d_;
if (dfn.vkAllocateMemory(device, &null_image_memory_allocate_info, nullptr,
&null_images_memory_[1]) != VK_SUCCESS) {
@@ -2527,8 +2531,8 @@ bool VulkanTextureCache::Initialize() {
// constant components instead of the real texels. The image will be cleared
// to (0, 0, 0, 0) anyway.
VkComponentSwizzle null_image_view_swizzle =
device_info.imageViewFormatSwizzle ? VK_COMPONENT_SWIZZLE_ZERO
: VK_COMPONENT_SWIZZLE_IDENTITY;
device_properties.imageViewFormatSwizzle ? VK_COMPONENT_SWIZZLE_ZERO
: VK_COMPONENT_SWIZZLE_IDENTITY;
null_image_view_create_info.components.r = null_image_view_swizzle;
null_image_view_create_info.components.g = null_image_view_swizzle;
null_image_view_create_info.components.b = null_image_view_swizzle;
@@ -2567,15 +2571,15 @@ bool VulkanTextureCache::Initialize() {
// VkDevice (true in a regular emulation scenario), so taking over all the
// allocation slots exclusively.
// Also leaving a few slots for use by things like overlay applications.
sampler_max_count_ =
device_info.maxSamplerAllocationCount -
uint32_t(ui::vulkan::VulkanProvider::HostSampler::kCount) - 16;
sampler_max_count_ = device_properties.maxSamplerAllocationCount -
ui::vulkan::UISamplers::kSamplerCount - 16;
if (device_info.samplerAnisotropy) {
if (device_properties.samplerAnisotropy) {
max_anisotropy_ = xenos::AnisoFilter(
uint32_t(xenos::AnisoFilter::kMax_1_1) +
(31 - xe::lzcnt(uint32_t(std::min(
16.0f, std::max(1.0f, device_info.maxSamplerAnisotropy))))));
(31 -
xe::lzcnt(uint32_t(std::min(
16.0f, std::max(1.0f, device_properties.maxSamplerAnisotropy))))));
} else {
max_anisotropy_ = xenos::AnisoFilter::kDisabled;
}
@@ -2639,8 +2643,8 @@ xenos::ClampMode VulkanTextureCache::NormalizeClampMode(
clamp_mode == xenos::ClampMode::kMirrorClampToHalfway ||
clamp_mode == xenos::ClampMode::kMirrorClampToBorder) {
// No equivalents for anything other than kMirrorClampToEdge in Vulkan.
return command_processor_.GetVulkanProvider()
.device_info()
return command_processor_.GetVulkanDevice()
->properties()
.samplerMirrorClampToEdge
? xenos::ClampMode::kMirrorClampToEdge
: xenos::ClampMode::kMirroredRepeat;