[Vulkan] Optional functionality usage improvements
Functional changes: - Enable only actually used features, as drivers may take more optimal paths when certain features are disabled. - Support VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE. - Fix the separateStencilMaskRef check doing the opposite. - Support shaderRoundingModeRTEFloat32. - Fix vkGetDeviceBufferMemoryRequirements pointer not passed to the Vulkan Memory Allocator. Stylistic changes: - Move all device extensions, properties and features to one structure, especially simplifying portability subset feature checks, and also making it easier to request new extension functionality in the future. - Remove extension suffixes from usage of promoted extensions.
This commit is contained in:
@@ -138,7 +138,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
|
||||
@@ -147,12 +148,12 @@ 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;
|
||||
@@ -160,14 +161,11 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
|
||||
// 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 =
|
||||
@@ -201,10 +199,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_;
|
||||
@@ -283,7 +280,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;
|
||||
|
||||
@@ -487,14 +484,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(
|
||||
@@ -509,16 +506,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 =
|
||||
@@ -2419,10 +2416,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;
|
||||
@@ -2446,8 +2441,8 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
// interlocks case completely - apply the viewport and the scissor offset
|
||||
// directly to pixel address and to things like ps_param_gen.
|
||||
draw_util::GetHostViewportInfo(
|
||||
regs, 1, 1, false, device_limits.maxViewportDimensions[0],
|
||||
device_limits.maxViewportDimensions[1], true, normalized_depth_control,
|
||||
regs, 1, 1, false, device_info.maxViewportDimensions[0],
|
||||
device_info.maxViewportDimensions[1], true, normalized_depth_control,
|
||||
false, host_render_targets_used,
|
||||
pixel_shader && pixel_shader->writes_depth(), viewport_info);
|
||||
|
||||
@@ -2461,7 +2456,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 &&
|
||||
@@ -3315,21 +3310,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;
|
||||
@@ -3681,12 +3671,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)) {
|
||||
@@ -3968,8 +3953,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))) {
|
||||
@@ -4348,8 +4333,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;
|
||||
|
||||
Reference in New Issue
Block a user