[vk, gl, spv] Opcode Promotion path emulation

This commit is contained in:
CamilleLaVey 2025-11-29 14:06:18 -04:00 committed by Caio Oliveira
parent 4cc99b9ff5
commit 178a0ce571
11 changed files with 391 additions and 75 deletions

View file

@ -207,6 +207,7 @@ ShaderCache::ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
device.HasNvViewportArray2() || device.HasVertexViewportLayer(),
.support_viewport_mask = device.HasNvViewportArray2(),
.support_typeless_image_loads = device.HasImageLoadFormatted(),
.support_sampled_1d = true,
.support_demote_to_helper_invocation = false,
.support_int64_atomics = false,
.support_derivative_control = device.HasDerivativeControl(),
@ -249,6 +250,7 @@ ShaderCache::ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
.needs_demote_reorder = device.IsAmd(),
.support_snorm_render_buffer = false,
.support_viewport_index_layer = device.HasVertexViewportLayer(),
.support_sampled_1d = true,
.min_ssbo_alignment = static_cast<u32>(device.GetShaderStorageBufferAlignment()),
.support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(),
.support_conditional_barrier = device.SupportsConditionalBarriers(),

View file

@ -401,6 +401,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
device.IsExtShaderViewportIndexLayerSupported(),
.support_viewport_mask = device.IsNvViewportArray2Supported(),
.support_typeless_image_loads = device.IsFormatlessImageLoadSupported(),
.support_sampled_1d = device.SupportsSampled1D(),
.support_demote_to_helper_invocation =
device.IsExtShaderDemoteToHelperInvocationSupported(),
.support_int64_atomics = device.IsExtShaderAtomicInt64Supported(),
@ -444,6 +445,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
driver_id == VK_DRIVER_ID_SAMSUNG_PROPRIETARY,
.support_snorm_render_buffer = true,
.support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(),
.support_sampled_1d = device.SupportsSampled1D(),
.min_ssbo_alignment = static_cast<u32>(device.GetStorageBufferAlignment()),
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
.support_conditional_barrier = device.SupportsConditionalBarriers(),

View file

@ -126,9 +126,18 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
return usage;
}
[[nodiscard]] bool Needs1DPromotion(const Device& device, ImageType type) {
return type == ImageType::e1D && !device.SupportsSampled1D();
}
[[nodiscard]] ImageType HostImageType(const Device& device, ImageType type) {
return Needs1DPromotion(device, type) ? ImageType::e2D : type;
}
[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) {
const auto format_info =
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, info.format);
const ImageType host_type = HostImageType(device, info.type);
VkImageCreateFlags flags{};
if (info.type == ImageType::e2D && info.resources.layers >= 6 &&
info.size.width == info.size.height && !device.HasBrokenCubeImageCompatibility()) {
@ -142,7 +151,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = nullptr,
.flags = flags,
.imageType = ConvertImageType(info.type),
.imageType = ConvertImageType(host_type),
.format = format_info.format,
.extent{
.width = info.size.width >> samples_x,
@ -273,10 +282,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
return VK_COMPONENT_SWIZZLE_ZERO;
}
[[nodiscard]] VkImageViewType ImageViewType(Shader::TextureType type) {
[[nodiscard]] VkImageViewType ImageViewType(const Device& device, Shader::TextureType type) {
const bool promote_1d = !device.SupportsSampled1D();
switch (type) {
case Shader::TextureType::Color1D:
return VK_IMAGE_VIEW_TYPE_1D;
return promote_1d ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_1D;
case Shader::TextureType::Color2D:
case Shader::TextureType::Color2DRect:
return VK_IMAGE_VIEW_TYPE_2D;
@ -285,7 +295,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
case Shader::TextureType::Color3D:
return VK_IMAGE_VIEW_TYPE_3D;
case Shader::TextureType::ColorArray1D:
return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
return promote_1d ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_1D_ARRAY;
case Shader::TextureType::ColorArray2D:
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
case Shader::TextureType::ColorArrayCube:
@ -2083,7 +2093,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
};
const auto create = [&](TextureType tex_type) {
VkImageViewCreateInfo ci{create_info};
ci.viewType = ImageViewType(tex_type);
ci.viewType = ImageViewType(*device, tex_type);
if (const auto override_layers = LayerCountOverride(tex_type)) {
ci.subresourceRange.layerCount = *override_layers;
}
@ -2304,7 +2314,7 @@ vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_
.pNext = nullptr,
.flags = 0,
.image = image_handle,
.viewType = ImageViewType(texture_type),
.viewType = ImageViewType(*device, texture_type),
.format = vk_format,
.components{
.r = VK_COMPONENT_SWIZZLE_IDENTITY,

View file

@ -440,6 +440,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP;
const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY;
// Qualcomm hardware (both proprietary and Turnip drivers) rejects Sampled1D capability.
supports_sampled_1d = !(is_qualcomm || is_turnip);
if (!is_suitable)
LOG_WARNING(Render_Vulkan, "Unsuitable driver - continuing anyways");

View file

@ -881,6 +881,10 @@ public:
return features2.features.multiViewport;
}
bool SupportsSampled1D() const {
return supports_sampled_1d;
}
/// Returns true if the device supports VK_KHR_maintenance1.
bool IsKhrMaintenance1Supported() const {
return extensions.maintenance1;
@ -1108,6 +1112,7 @@ private:
bool dynamic_state3_alpha_to_coverage{};
bool dynamic_state3_alpha_to_one{};
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
bool supports_sampled_1d{true}; ///< Supports declaring Sampled1D in shaders.
size_t sampler_heap_budget{}; ///< Sampler budget for buggy drivers (0 = unlimited).
VkDeviceSize uniform_buffer_alignment_minimum{}; ///< Minimum enforced UBO alignment.
VkDeviceSize storage_buffer_alignment_minimum{}; ///< Minimum enforced SSBO alignment.