Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/xenia-project/xenia into …
Browse files Browse the repository at this point in the history
…canary_experimental
  • Loading branch information
Gliniak committed May 10, 2024
2 parents 2ca752c + a90f83d commit b115823
Show file tree
Hide file tree
Showing 20 changed files with 1,215 additions and 1,081 deletions.
7 changes: 7 additions & 0 deletions src/xenia/gpu/gpu_flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ DEFINE_bool(
"the real reason why they're invalid is found.",
"GPU");

DEFINE_bool(
non_seamless_cube_map, true,
"Disable filtering between cube map faces near edges where possible "
"(Vulkan with VK_EXT_non_seamless_cube_map) to reproduce the Direct3D 9 "
"behavior.",
"GPU");

// Extremely bright screen borders in 4D5307E6.
// Reading between texels with half-pixel offset in 58410954.
DEFINE_bool(
Expand Down
2 changes: 2 additions & 0 deletions src/xenia/gpu/gpu_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ DECLARE_uint64(framerate_limit);

DECLARE_bool(gpu_allow_invalid_fetch_constants);

DECLARE_bool(non_seamless_cube_map);

DECLARE_bool(half_pixel_offset);

DECLARE_int32(query_occlusion_fake_sample_count);
Expand Down
132 changes: 83 additions & 49 deletions src/xenia/gpu/registers.h

Large diffs are not rendered by default.

66 changes: 24 additions & 42 deletions src/xenia/gpu/spirv_shader_translator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,56 +37,32 @@ SpirvShaderTranslator::Features::Features(bool all)
full_draw_index_uint32(all),
image_view_format_swizzle(all),
signed_zero_inf_nan_preserve_float32(all),
denorm_flush_to_zero_float32(all) {}
denorm_flush_to_zero_float32(all),
rounding_mode_rte_float32(all) {}

SpirvShaderTranslator::Features::Features(
const ui::vulkan::VulkanProvider& provider)
: max_storage_buffer_range(
provider.device_properties().limits.maxStorageBufferRange),
clip_distance(provider.device_features().shaderClipDistance),
cull_distance(provider.device_features().shaderCullDistance),
demote_to_helper_invocation(
provider.device_extensions().ext_shader_demote_to_helper_invocation &&
provider.device_shader_demote_to_helper_invocation_features()
.shaderDemoteToHelperInvocation),
const ui::vulkan::VulkanProvider::DeviceInfo& device_info)
: max_storage_buffer_range(device_info.maxStorageBufferRange),
clip_distance(device_info.shaderClipDistance),
cull_distance(device_info.shaderCullDistance),
demote_to_helper_invocation(device_info.shaderDemoteToHelperInvocation),
fragment_shader_sample_interlock(
provider.device_extensions().ext_fragment_shader_interlock &&
provider.device_fragment_shader_interlock_features()
.fragmentShaderSampleInterlock),
full_draw_index_uint32(provider.device_features().fullDrawIndexUint32) {
uint32_t device_version = provider.device_properties().apiVersion;
const ui::vulkan::VulkanProvider::DeviceExtensions& device_extensions =
provider.device_extensions();
if (device_version >= VK_MAKE_VERSION(1, 2, 0)) {
device_info.fragmentShaderSampleInterlock),
full_draw_index_uint32(device_info.fullDrawIndexUint32),
image_view_format_swizzle(device_info.imageViewFormatSwizzle),
signed_zero_inf_nan_preserve_float32(
device_info.shaderSignedZeroInfNanPreserveFloat32),
denorm_flush_to_zero_float32(device_info.shaderDenormFlushToZeroFloat32),
rounding_mode_rte_float32(device_info.shaderRoundingModeRTEFloat32) {
if (device_info.apiVersion >= VK_MAKE_API_VERSION(0, 1, 2, 0)) {
spirv_version = spv::Spv_1_5;
} else if (device_extensions.khr_spirv_1_4) {
} else if (device_info.ext_1_2_VK_KHR_spirv_1_4) {
spirv_version = spv::Spv_1_4;
} else if (device_version >= VK_MAKE_VERSION(1, 1, 0)) {
} else if (device_info.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) {
spirv_version = spv::Spv_1_3;
} else {
spirv_version = spv::Spv_1_0;
}
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
device_portability_subset_features =
provider.device_portability_subset_features();
if (device_portability_subset_features) {
image_view_format_swizzle =
bool(device_portability_subset_features->imageViewFormatSwizzle);
} else {
image_view_format_swizzle = true;
}
if (spirv_version >= spv::Spv_1_4 ||
device_extensions.khr_shader_float_controls) {
const VkPhysicalDeviceFloatControlsPropertiesKHR&
float_controls_properties = provider.device_float_controls_properties();
signed_zero_inf_nan_preserve_float32 =
bool(float_controls_properties.shaderSignedZeroInfNanPreserveFloat32);
denorm_flush_to_zero_float32 =
bool(float_controls_properties.shaderDenormFlushToZeroFloat32);
} else {
signed_zero_inf_nan_preserve_float32 = false;
denorm_flush_to_zero_float32 = false;
}
}

uint64_t SpirvShaderTranslator::GetDefaultVertexShaderModification(
Expand Down Expand Up @@ -168,7 +144,8 @@ void SpirvShaderTranslator::StartTranslation() {
: spv::CapabilityShader);
if (features_.spirv_version < spv::Spv_1_4) {
if (features_.signed_zero_inf_nan_preserve_float32 ||
features_.denorm_flush_to_zero_float32) {
features_.denorm_flush_to_zero_float32 ||
features_.rounding_mode_rte_float32) {
builder_->addExtension("SPV_KHR_float_controls");
}
}
Expand Down Expand Up @@ -724,6 +701,11 @@ std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
builder_->addExecutionMode(function_main_,
spv::ExecutionModeSignedZeroInfNanPreserve, 32);
}
if (features_.rounding_mode_rte_float32) {
builder_->addCapability(spv::CapabilityRoundingModeRTE);
builder_->addExecutionMode(function_main_,
spv::ExecutionModeRoundingModeRTE, 32);
}
spv::Instruction* entry_point =
builder_->addEntryPoint(execution_model, function_main_, "main");
for (spv::Id interface_id : main_interface_) {
Expand Down
4 changes: 3 additions & 1 deletion src/xenia/gpu/spirv_shader_translator.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
static constexpr uint32_t kSpirvMagicToolId = 26;

struct Features {
explicit Features(const ui::vulkan::VulkanProvider& provider);
explicit Features(
const ui::vulkan::VulkanProvider::DeviceInfo& device_info);
explicit Features(bool all = false);
unsigned int spirv_version;
uint32_t max_storage_buffer_range;
Expand All @@ -332,6 +333,7 @@ class SpirvShaderTranslator : public ShaderTranslator {
bool image_view_format_swizzle;
bool signed_zero_inf_nan_preserve_float32;
bool denorm_flush_to_zero_float32;
bool rounding_mode_rte_float32;
};

SpirvShaderTranslator(const Features& features,
Expand Down
73 changes: 28 additions & 45 deletions src/xenia/gpu/vulkan/vulkan_command_processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ bool VulkanCommandProcessor::SetupContext() {
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
const VkPhysicalDeviceFeatures& device_features = provider.device_features();
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
provider.device_info();

// The unconditional inclusion of the vertex shader stage also covers the case
// of manual index / factor buffer fetch (the system constants and the shared
Expand All @@ -152,27 +153,24 @@ bool VulkanCommandProcessor::SetupContext() {
guest_shader_pipeline_stages_ = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
guest_shader_vertex_stages_ = VK_SHADER_STAGE_VERTEX_BIT;
if (device_features.tessellationShader) {
if (device_info.tessellationShader) {
guest_shader_pipeline_stages_ |=
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
guest_shader_vertex_stages_ |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
}
if (!device_features.vertexPipelineStoresAndAtomics) {
if (!device_info.vertexPipelineStoresAndAtomics) {
// For memory export from vertex shaders converted to compute shaders.
guest_shader_pipeline_stages_ |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
guest_shader_vertex_stages_ |= VK_SHADER_STAGE_COMPUTE_BIT;
}

// 16384 is bigger than any single uniform buffer that Xenia needs, but is the
// minimum maxUniformBufferRange, thus the safe minimum amount.
VkDeviceSize uniform_buffer_alignment = std::max(
provider.device_properties().limits.minUniformBufferOffsetAlignment,
VkDeviceSize(1));
uniform_buffer_pool_ = std::make_unique<ui::vulkan::VulkanUploadBufferPool>(
provider, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
xe::align(std::max(ui::GraphicsUploadBufferPool::kDefaultPageSize,
size_t(16384)),
size_t(uniform_buffer_alignment)));
size_t(device_info.minUniformBufferOffsetAlignment)));

// Descriptor set layouts that don't depend on the setup of other subsystems.
VkShaderStageFlags guest_shader_stages =
Expand Down Expand Up @@ -206,10 +204,9 @@ bool VulkanCommandProcessor::SetupContext() {
[SpirvShaderTranslator::kConstantBufferSystem]
.stageFlags =
guest_shader_stages |
(device_features.tessellationShader
? VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
: 0) |
(device_features.geometryShader ? VK_SHADER_STAGE_GEOMETRY_BIT : 0);
(device_info.tessellationShader ? VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
: 0) |
(device_info.geometryShader ? VK_SHADER_STAGE_GEOMETRY_BIT : 0);
descriptor_set_layout_bindings_constants
[SpirvShaderTranslator::kConstantBufferFloatVertex]
.stageFlags = guest_shader_vertex_stages_;
Expand Down Expand Up @@ -288,7 +285,7 @@ bool VulkanCommandProcessor::SetupContext() {

uint32_t shared_memory_binding_count_log2 =
SpirvShaderTranslator::GetSharedMemoryStorageBufferCountLog2(
provider.device_properties().limits.maxStorageBufferRange);
device_info.maxStorageBufferRange);
uint32_t shared_memory_binding_count = UINT32_C(1)
<< shared_memory_binding_count_log2;

Expand Down Expand Up @@ -492,14 +489,14 @@ bool VulkanCommandProcessor::SetupContext() {
&gamma_ramp_host_visible_buffer_memory_requirements);
uint32_t gamma_ramp_host_visible_buffer_memory_types =
gamma_ramp_host_visible_buffer_memory_requirements.memoryTypeBits &
(provider.memory_types_device_local() &
provider.memory_types_host_visible());
(device_info.memory_types_device_local &
device_info.memory_types_host_visible);
VkMemoryAllocateInfo gamma_ramp_host_visible_buffer_memory_allocate_info;
// Prefer a host-uncached (because it's write-only) memory type, but try a
// host-cached host-visible device-local one as well.
if (xe::bit_scan_forward(
gamma_ramp_host_visible_buffer_memory_types &
~provider.memory_types_host_cached(),
~device_info.memory_types_host_cached,
&(gamma_ramp_host_visible_buffer_memory_allocate_info
.memoryTypeIndex)) ||
xe::bit_scan_forward(
Expand All @@ -514,16 +511,16 @@ bool VulkanCommandProcessor::SetupContext() {
gamma_ramp_host_visible_buffer_memory_allocate_info.pNext = nullptr;
gamma_ramp_host_visible_buffer_memory_allocate_info.allocationSize =
gamma_ramp_host_visible_buffer_memory_requirements.size;
VkMemoryDedicatedAllocateInfoKHR
VkMemoryDedicatedAllocateInfo
gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info;
if (provider.device_extensions().khr_dedicated_allocation) {
if (device_info.ext_1_1_VK_KHR_dedicated_allocation) {
gamma_ramp_host_visible_buffer_memory_allocate_info_last->pNext =
&gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info;
gamma_ramp_host_visible_buffer_memory_allocate_info_last =
reinterpret_cast<VkMemoryAllocateInfo*>(
&gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info);
gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info.sType =
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info.pNext =
nullptr;
gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info.image =
Expand Down Expand Up @@ -2431,10 +2428,8 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
current_guest_graphics_pipeline_layout_ = pipeline_layout;
}

const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
const VkPhysicalDeviceFeatures& device_features = provider.device_features();
const VkPhysicalDeviceLimits& device_limits =
provider.device_properties().limits;
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
GetVulkanProvider().device_info();

bool host_render_targets_used = render_target_cache_->GetPath() ==
RenderTargetCache::Path::kHostRenderTargets;
Expand All @@ -2460,9 +2455,8 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
// directly to pixel address and to things like ps_param_gen.
draw_util::GetViewportInfoArgs gviargs{};
gviargs.Setup(1, 1, divisors::MagicDiv{1}, divisors::MagicDiv{1}, false,
device_limits.maxViewportDimensions[0],

device_limits.maxViewportDimensions[1], true,
device_info.maxViewportDimensions[0],
device_info.maxViewportDimensions[1], true,
normalized_depth_control, false, host_render_targets_used,
pixel_shader && pixel_shader->writes_depth());
gviargs.SetupRegisterValues(regs);
Expand All @@ -2479,7 +2473,7 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
// indirectly in the vertex shader if full 32-bit indices are not supported by
// the host.
bool shader_32bit_index_dma =
!device_features.fullDrawIndexUint32 &&
!device_info.fullDrawIndexUint32 &&
primitive_processing_result.index_buffer_type ==
PrimitiveProcessor::ProcessedIndexBufferType::kGuestDMA &&
vgt_draw_initiator.index_size == xenos::IndexFormat::kInt32 &&
Expand Down Expand Up @@ -3337,21 +3331,16 @@ void VulkanCommandProcessor::UpdateDynamicState(
if (normalized_depth_control.stencil_enable) {
Register stencil_ref_mask_front_reg, stencil_ref_mask_back_reg;
if (primitive_polygonal && normalized_depth_control.backface_enable) {
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
device_portability_subset_features =
provider.device_portability_subset_features();
if (!device_portability_subset_features ||
device_portability_subset_features->separateStencilMaskRef) {
if (GetVulkanProvider().device_info().separateStencilMaskRef) {
stencil_ref_mask_front_reg = XE_GPU_REG_RB_STENCILREFMASK;
stencil_ref_mask_back_reg = XE_GPU_REG_RB_STENCILREFMASK_BF;
} else {
// Choose the back face values only if drawing only back faces.
stencil_ref_mask_front_reg =
regs.Get<reg::PA_SU_SC_MODE_CNTL>().cull_front
? XE_GPU_REG_RB_STENCILREFMASK_BF
: XE_GPU_REG_RB_STENCILREFMASK;
stencil_ref_mask_back_reg = stencil_ref_mask_front_reg;
} else {
stencil_ref_mask_front_reg = XE_GPU_REG_RB_STENCILREFMASK;
stencil_ref_mask_back_reg = XE_GPU_REG_RB_STENCILREFMASK_BF;
}
} else {
stencil_ref_mask_front_reg = XE_GPU_REG_RB_STENCILREFMASK;
Expand Down Expand Up @@ -3703,12 +3692,7 @@ void VulkanCommandProcessor::UpdateSystemConstantValues(
}

// Texture host swizzle in the shader.
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
device_portability_subset_features =
provider.device_portability_subset_features();
if (device_portability_subset_features &&
!device_portability_subset_features->imageViewFormatSwizzle) {
if (!GetVulkanProvider().device_info().imageViewFormatSwizzle) {
uint32_t textures_remaining = used_texture_mask;
uint32_t texture_index;
while (xe::bit_scan_forward(textures_remaining, &texture_index)) {
Expand Down Expand Up @@ -3990,8 +3974,8 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
kAllConstantBuffersMask) {
current_graphics_descriptor_set_values_up_to_date_ &=
~(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetConstants);
size_t uniform_buffer_alignment = size_t(
provider.device_properties().limits.minUniformBufferOffsetAlignment);
size_t uniform_buffer_alignment =
size_t(provider.device_info().minUniformBufferOffsetAlignment);
// System constants.
if (!(current_constant_buffers_up_to_date_ &
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferSystem))) {
Expand Down Expand Up @@ -4370,8 +4354,7 @@ uint8_t* VulkanCommandProcessor::WriteTransientUniformBufferBinding(
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
uint8_t* mapping = uniform_buffer_pool_->Request(
frame_current_, size,
size_t(
provider.device_properties().limits.minUniformBufferOffsetAlignment),
size_t(provider.device_info().minUniformBufferOffsetAlignment),
descriptor_buffer_info_out.buffer, descriptor_buffer_info_out.offset);
if (!mapping) {
return nullptr;
Expand Down
Loading

0 comments on commit b115823

Please sign in to comment.