diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index da2d36e41e..8c93a92046 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -133,6 +133,11 @@ VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat offset = 0; size = 0; } + const u32 required = + static_cast(device->TexelBufferAlignment(VideoCore::Surface::BytesPerBlock(format))); + const u32 misalign = offset % required; + offset -= misalign; + size += misalign; const auto it{std::ranges::find_if(views, [offset, size, format](const BufferView& view) { return offset == view.offset && size == view.size && format == view.format; })}; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 1e15f05156..65194f647a 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1112,6 +1112,16 @@ bool Device::GetSuitability(bool requires_swapchain) { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES; SetNext(next, properties.subgroup_size_control); } + properties.texel_buffer_alignment.storageTexelBufferOffsetAlignmentBytes = + properties.properties.limits.minTexelBufferOffsetAlignment; + properties.texel_buffer_alignment.uniformTexelBufferOffsetAlignmentBytes = + properties.properties.limits.minTexelBufferOffsetAlignment; + if (features.texel_buffer_alignment.texelBufferAlignment == VK_TRUE || + instance_version >= VK_API_VERSION_1_3) { + properties.texel_buffer_alignment.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT; + SetNext(next, properties.texel_buffer_alignment); + } if (extensions.transform_feedback) { properties.transform_feedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 8b93aad373..916a78fd56 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -69,6 +70,7 @@ VK_DEFINE_HANDLE(VmaAllocator) primitive_topology_list_restart) \ FEATURE(EXT, ProvokingVertex, PROVOKING_VERTEX, provoking_vertex) \ FEATURE(EXT, Robustness2, ROBUSTNESS_2, robustness2) \ + FEATURE(EXT, TexelBufferAlignment, TEXEL_BUFFER_ALIGNMENT, texel_buffer_alignment) \ FEATURE(EXT, TransformFeedback, TRANSFORM_FEEDBACK, transform_feedback) \ FEATURE(EXT, VertexInputDynamicState, VERTEX_INPUT_DYNAMIC_STATE, vertex_input_dynamic_state) \ FEATURE(KHR, Maintenance5, MAINTENANCE_5, maintenance5) \ @@ -291,6 +293,23 @@ public: return properties.properties.apiVersion; } + VkDeviceSize TexelBufferAlignment(u32 texel_size) const { + VkDeviceSize texel = texel_size; + if (texel % 3 == 0) { + texel /= 3; + } + const auto& limits = properties.texel_buffer_alignment; + VkDeviceSize storage = limits.storageTexelBufferOffsetAlignmentBytes; + if (limits.storageTexelBufferOffsetSingleTexelAlignment != VK_FALSE) { + storage = (std::min)(storage, texel); + } + VkDeviceSize uniform = limits.uniformTexelBufferOffsetAlignmentBytes; + if (limits.uniformTexelBufferOffsetSingleTexelAlignment != VK_FALSE) { + uniform = (std::min)(uniform, texel); + } + return (std::max)((std::max)(storage, uniform), VkDeviceSize{1}); + } + /// Returns the current driver version provided in Vulkan-formatted version numbers. u32 GetDriverVersion() const { return properties.properties.driverVersion; @@ -1161,6 +1180,7 @@ private: VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor{}; VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer{}; VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{}; + VkPhysicalDeviceTexelBufferAlignmentProperties texel_buffer_alignment{}; VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{}; VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{}; VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve{};