From df7bf0ecc61c46dbb33694f876dc2b7b1d15e02d Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 14 May 2026 19:30:38 +0200 Subject: [PATCH 01/22] WIP: Testing performance regressions Android revert [shader_recompiler] handle dynamic texture descriptor strides (#3898) this fixes dynamic texture descriptors that are not laid out as simple 8-byte entries tested on steam deck/amd --------------- Performance and graphical issues started from this point and forward, testing is required. notes - DynamicDescriptorSizeShift called twice because i moved it away from the struct but doing it this way keeps the patch just in this single file than adding a new derived field in the shared struct (i also think its just a cheap recomputation anyways) - removed cbuf scanning because i figured out how to do a bounds check statically credits: - Mythrax (identified the 1024 descriptor cap fix in #3897) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3898 Reviewed-by: crueter From dd79368c3e3b6994ad3a32ec12349f47b9188e46 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 14 May 2026 13:35:16 -0400 Subject: [PATCH 02/22] Revert "[shader_recompiler] handle dynamic texture descriptor strides (#3898)" --- src/shader_recompiler/host_translate_info.h | 6 - src/shader_recompiler/ir_opt/texture_pass.cpp | 129 ++---------------- .../renderer_vulkan/vk_compute_pipeline.cpp | 5 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 3 - src/video_core/vulkan_common/vulkan_device.h | 12 -- 5 files changed, 15 insertions(+), 140 deletions(-) diff --git a/src/shader_recompiler/host_translate_info.h b/src/shader_recompiler/host_translate_info.h index 4a9261d5f5..1b53404fcc 100644 --- a/src/shader_recompiler/host_translate_info.h +++ b/src/shader_recompiler/host_translate_info.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -20,9 +17,6 @@ struct HostTranslateInfo { bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS u32 min_ssbo_alignment{}; ///< Minimum alignment supported by the device for SSBOs - u32 max_per_stage_descriptor_sampled_images{1024}; ///< maximum sampled descriptors per stage - u32 max_per_stage_resources{4096}; ///< maximum resources per stage - u32 max_descriptor_set_sampled_images{1024}; ///< maximum sampled descriptors per set bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry ///< passthrough shaders bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index 55b6f7213c..20b8591072 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -32,71 +32,6 @@ using TextureInstVector = boost::container::small_vector; constexpr u32 DESCRIPTOR_SIZE = 8; constexpr u32 DESCRIPTOR_SIZE_SHIFT = static_cast(std::countr_zero(DESCRIPTOR_SIZE)); -constexpr u32 DYNAMIC_DESCRIPTOR_CBUF_BYTES = 16 * 1024; -constexpr u32 MAX_DYNAMIC_DESCRIPTOR_COUNT = 1024; - -u32 DynamicDescriptorSizeShift(const IR::U32& dynamic_offset) { - const IR::Inst* const inst{dynamic_offset.InstRecursive()}; - if (!inst || inst->GetOpcode() != IR::Opcode::ShiftLeftLogical32) { - return DESCRIPTOR_SIZE_SHIFT; - } - const IR::Value shift{inst->Arg(1)}; - if (!shift.IsImmediate()) { - return DESCRIPTOR_SIZE_SHIFT; - } - const u32 size_shift{shift.U32()}; - return size_shift >= DESCRIPTOR_SIZE_SHIFT && size_shift < 31 ? size_shift - : DESCRIPTOR_SIZE_SHIFT; -} - -u32 DynamicDescriptorCount(u32 base_offset, u32 size_shift) { - if (size_shift >= 31 || base_offset >= DYNAMIC_DESCRIPTOR_CBUF_BYTES) { - return 1; - } - const u32 stride{1U << size_shift}; - const u32 available{DYNAMIC_DESCRIPTOR_CBUF_BYTES - base_offset}; - if (available < DESCRIPTOR_SIZE) { - return 1; - } - const u32 available_count{1U + (available - DESCRIPTOR_SIZE) / stride}; - return std::min(MAX_DYNAMIC_DESCRIPTOR_COUNT, available_count); -} - -u32 SaturatingSub(u32 lhs, u32 rhs) { - return lhs > rhs ? lhs - rhs : 0; -} - -template -u32 StaticDescriptorCount(const Descriptors& descriptors) { - u32 count{}; - for (const auto& desc : descriptors) { - if (desc.count <= 1) { - count += desc.count; - } - } - return count; -} - -u32 DynamicSampledTextureCap(const Info& info, const HostTranslateInfo& host_info, - u32 dynamic_arrays) { - if (dynamic_arrays == 0) { - return MAX_DYNAMIC_DESCRIPTOR_COUNT; - } - const u32 sampled_static_count{StaticDescriptorCount(info.texture_buffer_descriptors) + - StaticDescriptorCount(info.texture_descriptors)}; - const u32 resource_static_count{ - NumDescriptors(info.constant_buffer_descriptors) + - NumDescriptors(info.storage_buffers_descriptors) + sampled_static_count + - NumDescriptors(info.image_buffer_descriptors) + NumDescriptors(info.image_descriptors)}; - const u32 sampled_limit{std::min(host_info.max_per_stage_descriptor_sampled_images, - host_info.max_descriptor_set_sampled_images)}; - const u32 sampled_budget{SaturatingSub(sampled_limit, sampled_static_count)}; - const u32 resource_budget{SaturatingSub(host_info.max_per_stage_resources, - resource_static_count)}; - const u32 sampled_cap{sampled_budget / dynamic_arrays}; - const u32 resource_cap{resource_budget / dynamic_arrays}; - return std::max(1U, std::min({MAX_DYNAMIC_DESCRIPTOR_COUNT, sampled_cap, resource_cap})); -} IR::Opcode IndexedInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { @@ -174,39 +109,6 @@ IR::Opcode IndexedInstruction(const IR::Inst& inst) { } } -bool IsStorageImageOpcode(IR::Opcode opcode) { - switch (opcode) { - case IR::Opcode::ImageRead: - case IR::Opcode::ImageAtomicIAdd32: - case IR::Opcode::ImageAtomicSMin32: - case IR::Opcode::ImageAtomicUMin32: - case IR::Opcode::ImageAtomicSMax32: - case IR::Opcode::ImageAtomicUMax32: - case IR::Opcode::ImageAtomicInc32: - case IR::Opcode::ImageAtomicDec32: - case IR::Opcode::ImageAtomicAnd32: - case IR::Opcode::ImageAtomicOr32: - case IR::Opcode::ImageAtomicXor32: - case IR::Opcode::ImageAtomicExchange32: - case IR::Opcode::ImageWrite: - return true; - default: - return false; - } -} - -u32 DynamicSampledTextureArrayCount(const TextureInstVector& to_replace) { - u32 count{}; - for (const TextureInst& inst : to_replace) { - const auto flags{inst.inst->Flags()}; - if (inst.cbuf.count > 1 && !IsStorageImageOpcode(IndexedInstruction(*inst.inst)) && - flags.type != TextureType::Buffer) { - ++count; - } - } - return count; -} - bool IsBindless(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::BindlessImageSampleImplicitLod: @@ -452,7 +354,6 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme } else { return std::nullopt; } - const u32 size_shift{DynamicDescriptorSizeShift(dynamic_offset)}; return ConstBufferAddr{ .index = index.U32(), .offset = base_offset, @@ -461,7 +362,7 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme .secondary_offset = 0, .secondary_shift_left = 0, .dynamic_offset = dynamic_offset, - .count = DynamicDescriptorCount(base_offset, size_shift), + .count = 8, .has_secondary = false, }; } @@ -688,8 +589,6 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo program.info.texture_descriptors, program.info.image_descriptors, }; - const u32 sampled_dynamic_cap{ - DynamicSampledTextureCap(program.info, host_info, DynamicSampledTextureArrayCount(to_replace))}; for (TextureInst& texture_inst : to_replace) { // TODO: Handle arrays IR::Inst* const inst{texture_inst.inst}; @@ -733,9 +632,6 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo break; } u32 index; - const u32 size_shift{cbuf.count > 1 ? DynamicDescriptorSizeShift(cbuf.dynamic_offset) - : DESCRIPTOR_SIZE_SHIFT}; - u32 count{cbuf.count}; switch (inst->GetOpcode()) { case IR::Opcode::ImageRead: case IR::Opcode::ImageAtomicIAdd32: @@ -764,8 +660,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, - .count = count, - .size_shift = size_shift, + .count = cbuf.count, + .size_shift = DESCRIPTOR_SIZE_SHIFT, }); } else { index = descriptors.Add(ImageDescriptor{ @@ -776,8 +672,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, - .count = count, - .size_shift = size_shift, + .count = cbuf.count, + .size_shift = DESCRIPTOR_SIZE_SHIFT, }); } break; @@ -792,11 +688,10 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .secondary_cbuf_index = cbuf.secondary_index, .secondary_cbuf_offset = cbuf.secondary_offset, .secondary_shift_left = cbuf.secondary_shift_left, - .count = count, - .size_shift = size_shift, + .count = cbuf.count, + .size_shift = DESCRIPTOR_SIZE_SHIFT, }); } else { - count = std::min(count, sampled_dynamic_cap); index = descriptors.Add(TextureDescriptor{ .type = flags.type, .is_depth = flags.is_depth != 0, @@ -808,8 +703,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .secondary_cbuf_index = cbuf.secondary_index, .secondary_cbuf_offset = cbuf.secondary_offset, .secondary_shift_left = cbuf.secondary_shift_left, - .count = count, - .size_shift = size_shift, + .count = cbuf.count, + .size_shift = DESCRIPTOR_SIZE_SHIFT, }); } break; @@ -817,12 +712,12 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo flags.descriptor_index.Assign(index); inst->SetFlags(flags); - if (count > 1) { + if (cbuf.count > 1) { const auto insert_point{IR::Block::InstructionList::s_iterator_to(*inst)}; IR::IREmitter ir{*texture_inst.block, insert_point}; - const IR::U32 shift{ir.Imm32(size_shift)}; + const IR::U32 shift{ir.Imm32(DESCRIPTOR_SIZE_SHIFT)}; inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift), - ir.Imm32(count - 1))); + ir.Imm32(DESCRIPTOR_SIZE - 1))); } else { inst->SetArg(0, IR::Value{}); } diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 490dd7acfe..1a62324c95 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -127,8 +127,9 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, texture_cache.SynchronizeComputeDescriptors(); - boost::container::small_vector views; - boost::container::small_vector samplers; + static constexpr size_t max_elements = 64; + boost::container::static_vector views; + boost::container::static_vector samplers; const auto& qmd{kepler_compute.launch_description}; const auto& cbufs{qmd.const_buffer_config}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d0f98091c1..37bce8e484 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -452,9 +452,6 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, .support_snorm_render_buffer = true, .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), .min_ssbo_alignment = static_cast(device.GetStorageBufferAlignment()), - .max_per_stage_descriptor_sampled_images = device.GetMaxPerStageDescriptorSampledImages(), - .max_per_stage_resources = device.GetMaxPerStageResources(), - .max_descriptor_set_sampled_images = device.GetMaxDescriptorSetSampledImages(), .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), .support_conditional_barrier = device.SupportsConditionalBarriers(), }; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 13fe1b371f..dec1de4dea 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -336,18 +336,6 @@ public: return properties.properties.limits.maxDescriptorSetUniformBuffersDynamic; } - u32 GetMaxPerStageDescriptorSampledImages() const { - return properties.properties.limits.maxPerStageDescriptorSampledImages; - } - - u32 GetMaxPerStageResources() const { - return properties.properties.limits.maxPerStageResources; - } - - u32 GetMaxDescriptorSetSampledImages() const { - return properties.properties.limits.maxDescriptorSetSampledImages; - } - /// Returns float control properties of the device. const VkPhysicalDeviceFloatControlsPropertiesKHR& FloatControlProperties() const { return properties.float_controls; From 84150336c293599684cdfe6a81363233e1e09be3 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 14 May 2026 14:12:05 -0400 Subject: [PATCH 03/22] Revert "[android] Fix crash on start any games for many handhelds (Ayaneo, Retroid etc) (#3647)" --- .../yuzu_emu/activities/EmulationActivity.kt | 46 +++---------------- 1 file changed, 7 insertions(+), 39 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index eab0fac705..949edc1ee3 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -15,7 +15,6 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.content.pm.PackageManager import android.content.res.Configuration import android.graphics.Rect import android.graphics.drawable.Icon @@ -101,7 +100,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager private var romSwapGeneration = 0 private var hasEmulationSession = processHasEmulationSession private val romSwapStopTimeoutRunnable = Runnable { onRomSwapStopTimeout() } - private val pictureInPictureFailureActions: MutableSet = mutableSetOf() private fun onRomSwapStopTimeout() { if (!isWaitingForRomSwapStop) { @@ -268,18 +266,12 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager } override fun onUserLeaveHint() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S || - !isPictureInPictureSupported() || - !BooleanSetting.PICTURE_IN_PICTURE.getBoolean() || - isInPictureInPictureMode - ) { - return - } - - val pictureInPictureParamsBuilder = PictureInPictureParams.Builder() - .getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder() - runPictureInPictureAction("enter picture-in-picture mode") { - enterPictureInPictureMode(pictureInPictureParamsBuilder.build()) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) { + val pictureInPictureParamsBuilder = PictureInPictureParams.Builder() + .getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder() + enterPictureInPictureMode(pictureInPictureParamsBuilder.build()) + } } } @@ -659,29 +651,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager return this.apply { setActions(pictureInPictureActions) } } - private fun isPictureInPictureSupported() = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && - packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) - - private fun runPictureInPictureAction(actionName: String, action: () -> Unit) { - try { - action() - } catch (e: IllegalStateException) { - if (pictureInPictureFailureActions.add(actionName)) { - Log.warning("[PiP] Failed to $actionName: ${e.message}") - } - } catch (e: UnsupportedOperationException) { - if (pictureInPictureFailureActions.add(actionName)) { - Log.warning("[PiP] Failed to $actionName: ${e.message}") - } - } - } - fun buildPictureInPictureParams() { - if (!isPictureInPictureSupported()) { - return - } - val pictureInPictureParamsBuilder = PictureInPictureParams.Builder() .getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { @@ -691,9 +661,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive ) } - runPictureInPictureAction("set picture-in-picture params") { - setPictureInPictureParams(pictureInPictureParamsBuilder.build()) - } + setPictureInPictureParams(pictureInPictureParamsBuilder.build()) } fun displayMultiplayerDialog() { From 3e6603135f98aebab8a636af4043f126ca728a38 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 14 May 2026 15:00:27 -0400 Subject: [PATCH 04/22] Revert "[spirv] mark sampled image descriptor indices non-uniform (#3900)" --- .../backend/spirv/emit_spirv_image.cpp | 51 ++----------------- src/shader_recompiler/profile.h | 4 -- .../renderer_vulkan/vk_pipeline_cache.cpp | 2 - src/video_core/vulkan_common/vulkan_device.h | 5 -- 4 files changed, 5 insertions(+), 57 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 62a82dce9d..c2511942d9 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -14,38 +14,6 @@ namespace Shader::Backend::SPIRV { namespace { -class DescriptorIndex { -public: - explicit DescriptorIndex(EmitContext& ctx, const IR::Value& index) - : id{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}, - is_non_uniform{ctx.profile.support_sampled_image_array_nonuniform_indexing && - !index.IsImmediate()} { - if (!is_non_uniform) { - return; - } - if (ctx.profile.supported_spirv < 0x00010400) { - ctx.AddExtension("SPV_EXT_descriptor_indexing"); - } - ctx.AddCapability(spv::Capability::ShaderNonUniform); - ctx.AddCapability(spv::Capability::SampledImageArrayNonUniformIndexing); - Decorate(ctx, id); - } - - Id Value() const { - return id; - } - - void Decorate(EmitContext& ctx, Id object) const { - if (is_non_uniform) { - ctx.Decorate(object, spv::Decoration::NonUniform); - } - } - -private: - Id id; - bool is_non_uniform; -}; - class ImageOperands { public: [[maybe_unused]] static constexpr bool ImageSampleOffsetAllowed = false; @@ -221,12 +189,8 @@ private: Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - const DescriptorIndex idx{ctx, index}; - const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, idx.Value())}; - idx.Decorate(ctx, pointer); - const Id object{ctx.OpLoad(def.sampled_type, pointer)}; - idx.Decorate(ctx, object); - return object; + const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; + return ctx.OpLoad(def.sampled_type, pointer); } else { return ctx.OpLoad(def.sampled_type, def.id); } @@ -244,14 +208,9 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind } else { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - const DescriptorIndex idx{ctx, index}; - const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx.Value())}; - idx.Decorate(ctx, ptr); - const Id object{ctx.OpLoad(def.sampled_type, ptr)}; - idx.Decorate(ctx, object); - const Id image{ctx.OpImage(def.image_type, object)}; - idx.Decorate(ctx, image); - return image; + const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}; + const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; + return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, ptr)); } return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); } diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index ff19f0710f..90e46bb1ba 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -48,7 +45,6 @@ struct Profile { bool support_scaled_attributes{}; bool support_multi_viewport{}; bool support_geometry_streams{}; - bool support_sampled_image_array_nonuniform_indexing{}; bool warp_size_potentially_larger_than_guest{}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 37bce8e484..9416e2f596 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -416,8 +416,6 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, .support_scaled_attributes = !device.MustEmulateScaledFormats(), .support_multi_viewport = device.SupportsMultiViewport(), .support_geometry_streams = device.AreTransformFeedbackGeometryStreamsSupported(), - .support_sampled_image_array_nonuniform_indexing = - device.IsSampledImageArrayNonUniformIndexingSupported(), .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index dec1de4dea..a8a89aee89 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -33,7 +33,6 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(KHR, VariablePointer, VARIABLE_POINTERS, variable_pointer) #define FOR_EACH_VK_FEATURE_1_2(FEATURE) \ - FEATURE(EXT, DescriptorIndexing, DESCRIPTOR_INDEXING, descriptor_indexing) \ FEATURE(EXT, HostQueryReset, HOST_QUERY_RESET, host_query_reset) \ FEATURE(KHR, 8BitStorage, 8BIT_STORAGE, bit8_storage) \ FEATURE(KHR, TimelineSemaphore, TIMELINE_SEMAPHORE, timeline_semaphore) @@ -356,10 +355,6 @@ public: return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; } - bool IsSampledImageArrayNonUniformIndexingSupported() const { - return features.descriptor_indexing.shaderSampledImageArrayNonUniformIndexing; - } - /// Returns true if the device supports float64 natively. bool IsFloat64Supported() const { return features.features.shaderFloat64; From e5584e57f690a83a8b3bd13d99931e5181293bf8 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 02:21:18 -0400 Subject: [PATCH 05/22] Quick depth clamp removal test --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 9416e2f596..05941b8335 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -487,7 +487,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, device.IsExtExtendedDynamicState3BlendingSupported(); dynamic_features.has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported(); - dynamic_features.has_dynamic_state3_depth_clamp_enable = + dynamic_features.has_dynamic_state3_depth_clamp_enable = false; device.SupportsDynamicState3DepthClampEnable(); dynamic_features.has_dynamic_state3_logic_op_enable = device.SupportsDynamicState3LogicOpEnable(); From af5167a9bee432a9493deaa0f61885da995a1e85 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 17:21:09 -0400 Subject: [PATCH 06/22] Small change to fix wrong blittering --- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 6 +----- src/video_core/renderer_vulkan/vk_blit_screen.cpp | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2deec13ace..25178acac8 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -172,11 +172,7 @@ try RendererVulkan::~RendererVulkan() { scheduler.RegisterOnSubmit([] {}); - scheduler.Finish(); - { - std::scoped_lock lock{scheduler.submit_mutex}; - void(device.GetLogical().WaitIdle()); - } + void(device.GetLogical().WaitIdle()); } void RendererVulkan::Composite(std::span framebuffers) { diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 75a8c3bf91..516bb4e99c 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -31,11 +31,7 @@ BlitScreen::~BlitScreen() = default; void BlitScreen::WaitIdle() { present_manager.WaitPresent(); - scheduler.Finish(); - { - std::scoped_lock lock{scheduler.submit_mutex}; - device.GetLogical().WaitIdle(); - } + void(device.GetLogical().WaitIdle()); } void BlitScreen::SetWindowAdaptPass() { From d875e3d220dee44475d221df36c29e24eb95d3f8 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 18:31:23 -0400 Subject: [PATCH 07/22] Revert "Small change to fix wrong blittering" --- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 6 +++++- src/video_core/renderer_vulkan/vk_blit_screen.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 25178acac8..2deec13ace 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -172,7 +172,11 @@ try RendererVulkan::~RendererVulkan() { scheduler.RegisterOnSubmit([] {}); - void(device.GetLogical().WaitIdle()); + scheduler.Finish(); + { + std::scoped_lock lock{scheduler.submit_mutex}; + void(device.GetLogical().WaitIdle()); + } } void RendererVulkan::Composite(std::span framebuffers) { diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 516bb4e99c..75a8c3bf91 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -31,7 +31,11 @@ BlitScreen::~BlitScreen() = default; void BlitScreen::WaitIdle() { present_manager.WaitPresent(); - void(device.GetLogical().WaitIdle()); + scheduler.Finish(); + { + std::scoped_lock lock{scheduler.submit_mutex}; + device.GetLogical().WaitIdle(); + } } void BlitScreen::SetWindowAdaptPass() { From ba1351452b46c9ca955479da09cf033fd9dbb99e Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 18:35:13 -0400 Subject: [PATCH 08/22] Return QCOM to presync workaround --- src/video_core/renderer_vulkan/vk_query_cache.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 98062a78dc..66bafc3092 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -221,7 +221,8 @@ public: } PauseCounter(); const auto driver_id = device.GetDriverID(); - if (driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { + if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || + driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { pending_sync.clear(); sync_values_stash.clear(); return; From 8da4fdd8189c3089e42fff2986a5dfbe541617da Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 19:19:05 -0400 Subject: [PATCH 09/22] adjusting to query reset pool --- src/video_core/renderer_vulkan/vk_query_cache.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 66bafc3092..10a23caa4a 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -156,12 +156,13 @@ public: ReserveHostQuery(); + scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([query_pool = current_query_pool, - query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { + query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { const bool use_precise = Settings::IsGPULevelHigh(); cmdbuf.ResetQueryPool(query_pool, static_cast(query_index), 1); cmdbuf.BeginQuery(query_pool, static_cast(query_index), - use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); + use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); }); has_started = true; @@ -221,8 +222,7 @@ public: } PauseCounter(); const auto driver_id = device.GetDriverID(); - if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || - driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { + if (driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { pending_sync.clear(); sync_values_stash.clear(); return; From 18225180a22f082ce228fca49bcc5076357e04c8 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 19:46:11 -0400 Subject: [PATCH 10/22] another change --- .../renderer_vulkan/vk_query_cache.cpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 10a23caa4a..931016975e 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -155,15 +155,17 @@ public: } ReserveHostQuery(); - - scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([query_pool = current_query_pool, - query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { - const bool use_precise = Settings::IsGPULevelHigh(); - cmdbuf.ResetQueryPool(query_pool, static_cast(query_index), 1); - cmdbuf.BeginQuery(query_pool, static_cast(query_index), - use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); - }); + + { + const VkQueryPool qp = current_query_pool; + const u32 qi = static_cast(current_bank_slot); + device.GetLogical().ResetQueryPool(qp, qi, 1); + scheduler.Record([query_pool = qp, query_index = qi](vk::CommandBuffer cmdbuf) { + const bool use_precise = Settings::IsGPULevelHigh(); + cmdbuf.BeginQuery(query_pool, static_cast(query_index), + use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); + }); + } has_started = true; } From b5dc68ec39f68d1a32a5a4935ef7f2bad46eb757 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 20:09:02 -0400 Subject: [PATCH 11/22] Revert "another change" --- .../renderer_vulkan/vk_query_cache.cpp | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 931016975e..10a23caa4a 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -155,17 +155,15 @@ public: } ReserveHostQuery(); - - { - const VkQueryPool qp = current_query_pool; - const u32 qi = static_cast(current_bank_slot); - device.GetLogical().ResetQueryPool(qp, qi, 1); - scheduler.Record([query_pool = qp, query_index = qi](vk::CommandBuffer cmdbuf) { - const bool use_precise = Settings::IsGPULevelHigh(); - cmdbuf.BeginQuery(query_pool, static_cast(query_index), - use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); - }); - } + + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([query_pool = current_query_pool, + query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { + const bool use_precise = Settings::IsGPULevelHigh(); + cmdbuf.ResetQueryPool(query_pool, static_cast(query_index), 1); + cmdbuf.BeginQuery(query_pool, static_cast(query_index), + use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); + }); has_started = true; } From bd3c321aed8d27bcd0c22301c0850ba1621a9fe0 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 20:09:41 -0400 Subject: [PATCH 12/22] Revert "adjusting to query reset pool" --- src/video_core/renderer_vulkan/vk_query_cache.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 10a23caa4a..66bafc3092 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -156,13 +156,12 @@ public: ReserveHostQuery(); - scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([query_pool = current_query_pool, - query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { + query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { const bool use_precise = Settings::IsGPULevelHigh(); cmdbuf.ResetQueryPool(query_pool, static_cast(query_index), 1); cmdbuf.BeginQuery(query_pool, static_cast(query_index), - use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); + use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); }); has_started = true; @@ -222,7 +221,8 @@ public: } PauseCounter(); const auto driver_id = device.GetDriverID(); - if (driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { + if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || + driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { pending_sync.clear(); sync_values_stash.clear(); return; From 1da1bf92603df11eac8a4a970ba092fb043fe2cd Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 15 May 2026 20:11:28 -0400 Subject: [PATCH 13/22] Revert "[vulkan] Adjustment ResetQueryPool" --- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 7 +------ src/video_core/renderer_vulkan/vk_blit_screen.cpp | 6 +----- src/video_core/renderer_vulkan/vk_query_cache.cpp | 3 +-- src/video_core/vulkan_common/vulkan_wrapper.cpp | 1 - src/video_core/vulkan_common/vulkan_wrapper.h | 5 ----- 5 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2deec13ace..010cfd225d 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -172,11 +171,7 @@ try RendererVulkan::~RendererVulkan() { scheduler.RegisterOnSubmit([] {}); - scheduler.Finish(); - { - std::scoped_lock lock{scheduler.submit_mutex}; - void(device.GetLogical().WaitIdle()); - } + void(device.GetLogical().WaitIdle()); } void RendererVulkan::Composite(std::span framebuffers) { diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 75a8c3bf91..bb7eb9bdaa 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -8,7 +8,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include #include "video_core/framebuffer_config.h" #include "video_core/present.h" #include "video_core/renderer_vulkan/present/filters.h" @@ -32,10 +31,7 @@ BlitScreen::~BlitScreen() = default; void BlitScreen::WaitIdle() { present_manager.WaitPresent(); scheduler.Finish(); - { - std::scoped_lock lock{scheduler.submit_mutex}; - device.GetLogical().WaitIdle(); - } + device.GetLogical().WaitIdle(); } void BlitScreen::SetWindowAdaptPass() { diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 66bafc3092..ffb318c935 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -157,9 +157,8 @@ public: ReserveHostQuery(); scheduler.Record([query_pool = current_query_pool, - query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { + query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { const bool use_precise = Settings::IsGPULevelHigh(); - cmdbuf.ResetQueryPool(query_pool, static_cast(query_index), 1); cmdbuf.BeginQuery(query_pool, static_cast(query_index), use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); }); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 871ce52678..f59ac7d6bc 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -123,7 +123,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdEndDebugUtilsLabelEXT); X(vkCmdFillBuffer); X(vkCmdPipelineBarrier); - X(vkCmdResetQueryPool); X(vkCmdPushConstants); X(vkCmdPushDescriptorSetWithTemplateKHR); X(vkCmdSetBlendConstants); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 4a3baad2c4..aaff66359e 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -225,7 +225,6 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{}; PFN_vkCmdFillBuffer vkCmdFillBuffer{}; PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{}; - PFN_vkCmdResetQueryPool vkCmdResetQueryPool{}; PFN_vkCmdPushConstants vkCmdPushConstants{}; PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{}; PFN_vkCmdResolveImage vkCmdResolveImage{}; @@ -1169,10 +1168,6 @@ public: dld->vkCmdEndQuery(handle, query_pool, query); } - void ResetQueryPool(VkQueryPool query_pool, u32 first_query, u32 query_count) const noexcept { - dld->vkCmdResetQueryPool(handle, query_pool, first_query, query_count); - } - void BindDescriptorSets(VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 first, Span sets, Span dynamic_offsets) const noexcept { dld->vkCmdBindDescriptorSets(handle, bind_point, layout, first, sets.size(), sets.data(), From e91f934f1328fd0012fe5fa259d42d1d59a42daf Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 17 May 2026 05:18:04 +0000 Subject: [PATCH 14/22] fix camile wanted for fragments --- src/video_core/renderer_vulkan/vk_scheduler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index fdaf9baacc..bfdc4e3c8a 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -270,8 +270,8 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, }; - upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER); + upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, WRITE_BARRIER); upload_cmdbuf.End(); cmdbuf.End(); From 1ae24bc298fae55cc1f56fbe226323f658148b6b Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 17 May 2026 15:23:46 -0400 Subject: [PATCH 15/22] Fix licenses --- src/shader_recompiler/host_translate_info.h | 3 +++ src/shader_recompiler/profile.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/shader_recompiler/host_translate_info.h b/src/shader_recompiler/host_translate_info.h index 1b53404fcc..7e7127c5b8 100644 --- a/src/shader_recompiler/host_translate_info.h +++ b/src/shader_recompiler/host_translate_info.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 90e46bb1ba..35fcad3843 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later From dac80444b220bc572c9ffeafe72270eb5e79ecc1 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 17 May 2026 19:24:58 -0400 Subject: [PATCH 16/22] small change --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 05941b8335..f927c69d48 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -488,7 +488,6 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, dynamic_features.has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported(); dynamic_features.has_dynamic_state3_depth_clamp_enable = false; - device.SupportsDynamicState3DepthClampEnable(); dynamic_features.has_dynamic_state3_logic_op_enable = device.SupportsDynamicState3LogicOpEnable(); dynamic_features.has_dynamic_state3_line_stipple_enable = From e9280c603ea54a0edd8987d441adcaa492c3b05e Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 18 May 2026 02:39:20 +0200 Subject: [PATCH 17/22] [vk] tomodachi toggle for hotfix PR (#3974) mostly just tomo toggle so no konflict Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3974 --- src/common/settings.h | 2 + .../backend/spirv/emit_spirv_image.cpp | 62 +++++++- src/shader_recompiler/host_translate_info.h | 3 + src/shader_recompiler/ir_opt/texture_pass.cpp | 132 ++++++++++++++++-- src/shader_recompiler/profile.h | 1 + .../renderer_vulkan/vk_compute_pipeline.cpp | 5 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 5 + src/video_core/vulkan_common/vulkan_device.h | 17 +++ 8 files changed, 206 insertions(+), 21 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index e10f5105a1..08005bb7a4 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -591,6 +591,8 @@ struct Values { SwitchableSetting gpu_unswizzle_enabled{linkage, false, "gpu_unswizzle_enabled", Category::RendererHacks}; + SwitchableSetting legacy_descriptor_indices{linkage, true, "legacy_descriptor_indices", Category::RendererHacks}; + SwitchableSetting dyna_state{linkage, #if defined(ANDROID) ExtendedDynamicState::Disabled, diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index c2511942d9..7745a73fb9 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -14,6 +14,38 @@ namespace Shader::Backend::SPIRV { namespace { +class DescriptorIndex { +public: + explicit DescriptorIndex(EmitContext& ctx, const IR::Value& index) + : id{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}, + is_non_uniform{ctx.profile.support_sampled_image_array_nonuniform_indexing && + !index.IsImmediate()} { + if (!is_non_uniform) { + return; + } + if (ctx.profile.supported_spirv < 0x00010400) { + ctx.AddExtension("SPV_EXT_descriptor_indexing"); + } + ctx.AddCapability(spv::Capability::ShaderNonUniform); + ctx.AddCapability(spv::Capability::SampledImageArrayNonUniformIndexing); + Decorate(ctx, id); + } + + Id Value() const { + return id; + } + + void Decorate(EmitContext& ctx, Id object) const { + if (is_non_uniform) { + ctx.Decorate(object, spv::Decoration::NonUniform); + } + } + +private: + Id id; + bool is_non_uniform; +}; + class ImageOperands { public: [[maybe_unused]] static constexpr bool ImageSampleOffsetAllowed = false; @@ -189,8 +221,17 @@ private: Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; - return ctx.OpLoad(def.sampled_type, pointer); + if (Settings::values.legacy_descriptor_indices.GetValue()) { + const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; + return ctx.OpLoad(def.sampled_type, pointer); + } else { + const DescriptorIndex idx{ctx, index}; + const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, idx.Value())}; + idx.Decorate(ctx, pointer); + const Id object{ctx.OpLoad(def.sampled_type, pointer)}; + idx.Decorate(ctx, object); + return object; + } } else { return ctx.OpLoad(def.sampled_type, def.id); } @@ -208,9 +249,20 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind } else { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}; - const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; - return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, ptr)); + if (Settings::values.legacy_descriptor_indices.GetValue()) { + const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}; + const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; + return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, ptr)); + } else { + const DescriptorIndex idx{ctx, index}; + const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx.Value())}; + idx.Decorate(ctx, ptr); + const Id object{ctx.OpLoad(def.sampled_type, ptr)}; + idx.Decorate(ctx, object); + const Id image{ctx.OpImage(def.image_type, object)}; + idx.Decorate(ctx, image); + return image; + } } return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); } diff --git a/src/shader_recompiler/host_translate_info.h b/src/shader_recompiler/host_translate_info.h index 7e7127c5b8..4a9261d5f5 100644 --- a/src/shader_recompiler/host_translate_info.h +++ b/src/shader_recompiler/host_translate_info.h @@ -20,6 +20,9 @@ struct HostTranslateInfo { bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS u32 min_ssbo_alignment{}; ///< Minimum alignment supported by the device for SSBOs + u32 max_per_stage_descriptor_sampled_images{1024}; ///< maximum sampled descriptors per stage + u32 max_per_stage_resources{4096}; ///< maximum resources per stage + u32 max_descriptor_set_sampled_images{1024}; ///< maximum sampled descriptors per set bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry ///< passthrough shaders bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index 20b8591072..2366996292 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -12,6 +12,7 @@ #include #include +#include "common/settings.h" #include "shader_recompiler/environment.h" #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/breadth_first_search.h" @@ -32,6 +33,71 @@ using TextureInstVector = boost::container::small_vector; constexpr u32 DESCRIPTOR_SIZE = 8; constexpr u32 DESCRIPTOR_SIZE_SHIFT = static_cast(std::countr_zero(DESCRIPTOR_SIZE)); +constexpr u32 DYNAMIC_DESCRIPTOR_CBUF_BYTES = 16 * 1024; +constexpr u32 MAX_DYNAMIC_DESCRIPTOR_COUNT = 1024; + +u32 DynamicDescriptorSizeShift(const IR::U32& dynamic_offset) { + const IR::Inst* const inst{dynamic_offset.InstRecursive()}; + if (!inst || inst->GetOpcode() != IR::Opcode::ShiftLeftLogical32) { + return DESCRIPTOR_SIZE_SHIFT; + } + const IR::Value shift{inst->Arg(1)}; + if (!shift.IsImmediate()) { + return DESCRIPTOR_SIZE_SHIFT; + } + const u32 size_shift{shift.U32()}; + return size_shift >= DESCRIPTOR_SIZE_SHIFT && size_shift < 31 ? size_shift + : DESCRIPTOR_SIZE_SHIFT; +} + +u32 DynamicDescriptorCount(u32 base_offset, u32 size_shift) { + if (size_shift >= 31 || base_offset >= DYNAMIC_DESCRIPTOR_CBUF_BYTES) { + return 1; + } + const u32 stride{1U << size_shift}; + const u32 available{DYNAMIC_DESCRIPTOR_CBUF_BYTES - base_offset}; + if (available < DESCRIPTOR_SIZE) { + return 1; + } + const u32 available_count{1U + (available - DESCRIPTOR_SIZE) / stride}; + return std::min(MAX_DYNAMIC_DESCRIPTOR_COUNT, available_count); +} + +u32 SaturatingSub(u32 lhs, u32 rhs) { + return lhs > rhs ? lhs - rhs : 0; +} + +template +u32 StaticDescriptorCount(const Descriptors& descriptors) { + u32 count{}; + for (const auto& desc : descriptors) { + if (desc.count <= 1) { + count += desc.count; + } + } + return count; +} + +u32 DynamicSampledTextureCap(const Info& info, const HostTranslateInfo& host_info, + u32 dynamic_arrays) { + if (dynamic_arrays == 0) { + return MAX_DYNAMIC_DESCRIPTOR_COUNT; + } + const u32 sampled_static_count{StaticDescriptorCount(info.texture_buffer_descriptors) + + StaticDescriptorCount(info.texture_descriptors)}; + const u32 resource_static_count{ + NumDescriptors(info.constant_buffer_descriptors) + + NumDescriptors(info.storage_buffers_descriptors) + sampled_static_count + + NumDescriptors(info.image_buffer_descriptors) + NumDescriptors(info.image_descriptors)}; + const u32 sampled_limit{std::min(host_info.max_per_stage_descriptor_sampled_images, + host_info.max_descriptor_set_sampled_images)}; + const u32 sampled_budget{SaturatingSub(sampled_limit, sampled_static_count)}; + const u32 resource_budget{SaturatingSub(host_info.max_per_stage_resources, + resource_static_count)}; + const u32 sampled_cap{sampled_budget / dynamic_arrays}; + const u32 resource_cap{resource_budget / dynamic_arrays}; + return std::max(1U, std::min({MAX_DYNAMIC_DESCRIPTOR_COUNT, sampled_cap, resource_cap})); +} IR::Opcode IndexedInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { @@ -109,6 +175,39 @@ IR::Opcode IndexedInstruction(const IR::Inst& inst) { } } +bool IsStorageImageOpcode(IR::Opcode opcode) { + switch (opcode) { + case IR::Opcode::ImageRead: + case IR::Opcode::ImageAtomicIAdd32: + case IR::Opcode::ImageAtomicSMin32: + case IR::Opcode::ImageAtomicUMin32: + case IR::Opcode::ImageAtomicSMax32: + case IR::Opcode::ImageAtomicUMax32: + case IR::Opcode::ImageAtomicInc32: + case IR::Opcode::ImageAtomicDec32: + case IR::Opcode::ImageAtomicAnd32: + case IR::Opcode::ImageAtomicOr32: + case IR::Opcode::ImageAtomicXor32: + case IR::Opcode::ImageAtomicExchange32: + case IR::Opcode::ImageWrite: + return true; + default: + return false; + } +} + +u32 DynamicSampledTextureArrayCount(const TextureInstVector& to_replace) { + u32 count{}; + for (const TextureInst& inst : to_replace) { + const auto flags{inst.inst->Flags()}; + if (inst.cbuf.count > 1 && !IsStorageImageOpcode(IndexedInstruction(*inst.inst)) && + flags.type != TextureType::Buffer) { + ++count; + } + } + return count; +} + bool IsBindless(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::BindlessImageSampleImplicitLod: @@ -354,6 +453,7 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme } else { return std::nullopt; } + const u32 size_shift{DynamicDescriptorSizeShift(dynamic_offset)}; return ConstBufferAddr{ .index = index.U32(), .offset = base_offset, @@ -362,7 +462,7 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme .secondary_offset = 0, .secondary_shift_left = 0, .dynamic_offset = dynamic_offset, - .count = 8, + .count = Settings::values.legacy_descriptor_indices.GetValue() ? 8 : DynamicDescriptorCount(base_offset, size_shift), .has_secondary = false, }; } @@ -589,6 +689,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo program.info.texture_descriptors, program.info.image_descriptors, }; + const u32 sampled_dynamic_cap{ + DynamicSampledTextureCap(program.info, host_info, DynamicSampledTextureArrayCount(to_replace))}; for (TextureInst& texture_inst : to_replace) { // TODO: Handle arrays IR::Inst* const inst{texture_inst.inst}; @@ -632,6 +734,10 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo break; } u32 index; + u32 size_shift = cbuf.count > 1 ? DynamicDescriptorSizeShift(cbuf.dynamic_offset) : DESCRIPTOR_SIZE_SHIFT; + if (Settings::values.legacy_descriptor_indices.GetValue()) + size_shift = DESCRIPTOR_SIZE_SHIFT; + u32 count = cbuf.count; switch (inst->GetOpcode()) { case IR::Opcode::ImageRead: case IR::Opcode::ImageAtomicIAdd32: @@ -660,8 +766,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, - .count = cbuf.count, - .size_shift = DESCRIPTOR_SIZE_SHIFT, + .count = count, + .size_shift = size_shift, }); } else { index = descriptors.Add(ImageDescriptor{ @@ -672,8 +778,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, - .count = cbuf.count, - .size_shift = DESCRIPTOR_SIZE_SHIFT, + .count = count, + .size_shift = size_shift, }); } break; @@ -688,10 +794,11 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .secondary_cbuf_index = cbuf.secondary_index, .secondary_cbuf_offset = cbuf.secondary_offset, .secondary_shift_left = cbuf.secondary_shift_left, - .count = cbuf.count, - .size_shift = DESCRIPTOR_SIZE_SHIFT, + .count = count, + .size_shift = size_shift, }); } else { + count = std::min(count, sampled_dynamic_cap); index = descriptors.Add(TextureDescriptor{ .type = flags.type, .is_depth = flags.is_depth != 0, @@ -703,8 +810,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .secondary_cbuf_index = cbuf.secondary_index, .secondary_cbuf_offset = cbuf.secondary_offset, .secondary_shift_left = cbuf.secondary_shift_left, - .count = cbuf.count, - .size_shift = DESCRIPTOR_SIZE_SHIFT, + .count = count, + .size_shift = size_shift, }); } break; @@ -712,12 +819,11 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo flags.descriptor_index.Assign(index); inst->SetFlags(flags); - if (cbuf.count > 1) { + if (count > 1) { const auto insert_point{IR::Block::InstructionList::s_iterator_to(*inst)}; IR::IREmitter ir{*texture_inst.block, insert_point}; - const IR::U32 shift{ir.Imm32(DESCRIPTOR_SIZE_SHIFT)}; - inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift), - ir.Imm32(DESCRIPTOR_SIZE - 1))); + const IR::U32 shift{ir.Imm32(size_shift)}; + inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift), ir.Imm32(count - 1))); } else { inst->SetArg(0, IR::Value{}); } diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 35fcad3843..ff19f0710f 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -48,6 +48,7 @@ struct Profile { bool support_scaled_attributes{}; bool support_multi_viewport{}; bool support_geometry_streams{}; + bool support_sampled_image_array_nonuniform_indexing{}; bool warp_size_potentially_larger_than_guest{}; diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 1a62324c95..490dd7acfe 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -127,9 +127,8 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, texture_cache.SynchronizeComputeDescriptors(); - static constexpr size_t max_elements = 64; - boost::container::static_vector views; - boost::container::static_vector samplers; + boost::container::small_vector views; + boost::container::small_vector samplers; const auto& qmd{kepler_compute.launch_description}; const auto& cbufs{qmd.const_buffer_config}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index f927c69d48..5345bdc306 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -416,6 +416,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, .support_scaled_attributes = !device.MustEmulateScaledFormats(), .support_multi_viewport = device.SupportsMultiViewport(), .support_geometry_streams = device.AreTransformFeedbackGeometryStreamsSupported(), + .support_sampled_image_array_nonuniform_indexing = + device.IsSampledImageArrayNonUniformIndexingSupported(), .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), @@ -450,6 +452,9 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, .support_snorm_render_buffer = true, .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), .min_ssbo_alignment = static_cast(device.GetStorageBufferAlignment()), + .max_per_stage_descriptor_sampled_images = device.GetMaxPerStageDescriptorSampledImages(), + .max_per_stage_resources = device.GetMaxPerStageResources(), + .max_descriptor_set_sampled_images = device.GetMaxDescriptorSetSampledImages(), .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), .support_conditional_barrier = device.SupportsConditionalBarriers(), }; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index a8a89aee89..13fe1b371f 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -33,6 +33,7 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(KHR, VariablePointer, VARIABLE_POINTERS, variable_pointer) #define FOR_EACH_VK_FEATURE_1_2(FEATURE) \ + FEATURE(EXT, DescriptorIndexing, DESCRIPTOR_INDEXING, descriptor_indexing) \ FEATURE(EXT, HostQueryReset, HOST_QUERY_RESET, host_query_reset) \ FEATURE(KHR, 8BitStorage, 8BIT_STORAGE, bit8_storage) \ FEATURE(KHR, TimelineSemaphore, TIMELINE_SEMAPHORE, timeline_semaphore) @@ -335,6 +336,18 @@ public: return properties.properties.limits.maxDescriptorSetUniformBuffersDynamic; } + u32 GetMaxPerStageDescriptorSampledImages() const { + return properties.properties.limits.maxPerStageDescriptorSampledImages; + } + + u32 GetMaxPerStageResources() const { + return properties.properties.limits.maxPerStageResources; + } + + u32 GetMaxDescriptorSetSampledImages() const { + return properties.properties.limits.maxDescriptorSetSampledImages; + } + /// Returns float control properties of the device. const VkPhysicalDeviceFloatControlsPropertiesKHR& FloatControlProperties() const { return properties.float_controls; @@ -355,6 +368,10 @@ public: return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; } + bool IsSampledImageArrayNonUniformIndexingSupported() const { + return features.descriptor_indexing.shaderSampledImageArrayNonUniformIndexing; + } + /// Returns true if the device supports float64 natively. bool IsFloat64Supported() const { return features.features.shaderFloat64; From 85d2f62d7e6f30c51228b436f6115eb3769d51a4 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 17 May 2026 21:33:35 -0400 Subject: [PATCH 18/22] test another change --- src/video_core/renderer_vulkan/vk_query_cache.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index ffb318c935..43316b7356 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -1443,7 +1443,8 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo const u32 resolve_size = compare_to_zero ? 8 : 24; { std::scoped_lock lk(impl->buffer_cache.mutex); - const auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize; + const auto sync_info = compare_to_zero ? VideoCommon::ObtainBufferSynchronize::FullSynchronize + : VideoCommon::ObtainBufferSynchronize::NoSynchronize; const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing; const auto [buffer, offset] = impl->buffer_cache.ObtainCPUBuffer(address, resolve_size, sync_info, post_op); From abca69759f1d16fac97e4ca102ebb8b4d28ab390 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 17 May 2026 23:02:01 -0400 Subject: [PATCH 19/22] Revert "test another change" --- src/video_core/renderer_vulkan/vk_query_cache.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 43316b7356..ffb318c935 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -1443,8 +1443,7 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo const u32 resolve_size = compare_to_zero ? 8 : 24; { std::scoped_lock lk(impl->buffer_cache.mutex); - const auto sync_info = compare_to_zero ? VideoCommon::ObtainBufferSynchronize::FullSynchronize - : VideoCommon::ObtainBufferSynchronize::NoSynchronize; + const auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize; const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing; const auto [buffer, offset] = impl->buffer_cache.ObtainCPUBuffer(address, resolve_size, sync_info, post_op); From 1f228f31b58637c7ad85c61f7b36e929e7d0985f Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 17 May 2026 23:12:33 -0400 Subject: [PATCH 20/22] another change --- src/video_core/vulkan_common/vulkan_device.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 6e55306079..3435c4d88f 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -486,11 +486,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR CollectToolingInfo(); if (is_qualcomm) { - // Qualcomm Adreno GPUs doesn't handle scaled vertex attributes; keep emulation enabled + LOG_WARNING(Render_Vulkan, + "Qualcomm drivers require scaled vertex format emulation"); must_emulate_scaled_formats = true; LOG_WARNING(Render_Vulkan, - "Qualcomm drivers require scaled vertex format emulation; forcing fallback"); - + "Qualcomm drivers have broken provoking vertex"); + RemoveExtension(extensions.provoking_vertex, VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME); + LOG_WARNING(Render_Vulkan, + "Qualcomm drivers have slow push descriptor implementation"); + RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); LOG_WARNING(Render_Vulkan, "Disabling shader float controls and 64-bit integer features on Qualcomm proprietary drivers"); RemoveExtension(extensions.shader_float_controls, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); From 8d45f7d80c69da25ca2fdf8a32912577b51d1843 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 18 May 2026 07:03:59 +0200 Subject: [PATCH 21/22] hotfix-performance: lizzie/togleless-approach-tomo32 (#3975) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3975 --- src/common/settings.h | 2 - .../backend/spirv/emit_spirv.cpp | 7 ++ .../backend/spirv/emit_spirv_image.cpp | 71 +++++-------------- src/shader_recompiler/ir_opt/texture_pass.cpp | 4 +- 4 files changed, 24 insertions(+), 60 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index 08005bb7a4..e10f5105a1 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -591,8 +591,6 @@ struct Values { SwitchableSetting gpu_unswizzle_enabled{linkage, false, "gpu_unswizzle_enabled", Category::RendererHacks}; - SwitchableSetting legacy_descriptor_indices{linkage, true, "legacy_descriptor_indices", Category::RendererHacks}; - SwitchableSetting dyna_state{linkage, #if defined(ANDROID) ExtendedDynamicState::Disabled, diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index fc102cadac..0447dfe90d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -462,6 +462,13 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct ctx.AddCapability(spv::Capability::ImageGatherExtended); ctx.AddCapability(spv::Capability::ImageQuery); ctx.AddCapability(spv::Capability::SampledBuffer); + // TODO: this usage needs to be tracked properly + if (ctx.profile.support_sampled_image_array_nonuniform_indexing) { + if (ctx.profile.supported_spirv < 0x00010400) + ctx.AddExtension("SPV_EXT_descriptor_indexing"); + ctx.AddCapability(spv::Capability::ShaderNonUniform); + ctx.AddCapability(spv::Capability::SampledImageArrayNonUniformIndexing); + } } void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 7745a73fb9..139cd51cc6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -14,37 +14,10 @@ namespace Shader::Backend::SPIRV { namespace { -class DescriptorIndex { -public: - explicit DescriptorIndex(EmitContext& ctx, const IR::Value& index) - : id{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}, - is_non_uniform{ctx.profile.support_sampled_image_array_nonuniform_indexing && - !index.IsImmediate()} { - if (!is_non_uniform) { - return; - } - if (ctx.profile.supported_spirv < 0x00010400) { - ctx.AddExtension("SPV_EXT_descriptor_indexing"); - } - ctx.AddCapability(spv::Capability::ShaderNonUniform); - ctx.AddCapability(spv::Capability::SampledImageArrayNonUniformIndexing); - Decorate(ctx, id); - } - Id Value() const { - return id; - } - - void Decorate(EmitContext& ctx, Id object) const { - if (is_non_uniform) { - ctx.Decorate(object, spv::Decoration::NonUniform); - } - } - -private: - Id id; - bool is_non_uniform; -}; +[[nodiscard]] bool IsNonUniformDescriptor(EmitContext& ctx, const IR::Value& index) noexcept { + return ctx.profile.support_sampled_image_array_nonuniform_indexing && !index.IsImmediate(); +} class ImageOperands { public: @@ -221,17 +194,12 @@ private: Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - if (Settings::values.legacy_descriptor_indices.GetValue()) { - const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; - return ctx.OpLoad(def.sampled_type, pointer); - } else { - const DescriptorIndex idx{ctx, index}; - const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, idx.Value())}; - idx.Decorate(ctx, pointer); - const Id object{ctx.OpLoad(def.sampled_type, pointer)}; - idx.Decorate(ctx, object); - return object; - } + auto const idx = index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index); + const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; + const Id object{ctx.OpLoad(def.sampled_type, pointer)}; + if (IsNonUniformDescriptor(ctx, index)) + ctx.Decorate(idx, spv::Decoration::NonUniform); + return object; } else { return ctx.OpLoad(def.sampled_type, def.id); } @@ -249,20 +217,13 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind } else { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - if (Settings::values.legacy_descriptor_indices.GetValue()) { - const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}; - const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; - return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, ptr)); - } else { - const DescriptorIndex idx{ctx, index}; - const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx.Value())}; - idx.Decorate(ctx, ptr); - const Id object{ctx.OpLoad(def.sampled_type, ptr)}; - idx.Decorate(ctx, object); - const Id image{ctx.OpImage(def.image_type, object)}; - idx.Decorate(ctx, image); - return image; - } + auto const idx = index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index); + const Id ptr = ctx.OpAccessChain(def.pointer_type, def.id, idx); + const Id object = ctx.OpLoad(def.sampled_type, ptr); + const Id image = ctx.OpImage(def.image_type, object); + if (IsNonUniformDescriptor(ctx, index)) + ctx.Decorate(idx, spv::Decoration::NonUniform); + return image; } return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); } diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index 2366996292..c500b53ff7 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -462,7 +462,7 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme .secondary_offset = 0, .secondary_shift_left = 0, .dynamic_offset = dynamic_offset, - .count = Settings::values.legacy_descriptor_indices.GetValue() ? 8 : DynamicDescriptorCount(base_offset, size_shift), + .count = DynamicDescriptorCount(base_offset, size_shift), .has_secondary = false, }; } @@ -735,8 +735,6 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo } u32 index; u32 size_shift = cbuf.count > 1 ? DynamicDescriptorSizeShift(cbuf.dynamic_offset) : DESCRIPTOR_SIZE_SHIFT; - if (Settings::values.legacy_descriptor_indices.GetValue()) - size_shift = DESCRIPTOR_SIZE_SHIFT; u32 count = cbuf.count; switch (inst->GetOpcode()) { case IR::Opcode::ImageRead: From 3ad5257adc5cf4f5f57a5f3ae9e97f11e6a02a41 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Mon, 18 May 2026 01:40:56 -0400 Subject: [PATCH 22/22] [TEST] Conformity to all barriers flags. --- src/video_core/renderer_vulkan/blit_image.cpp | 2 +- .../renderer_vulkan/present/util.cpp | 6 +-- .../renderer_vulkan/vk_buffer_cache.cpp | 12 ++--- .../renderer_vulkan/vk_compute_pass.cpp | 14 +++--- .../renderer_vulkan/vk_present_manager.cpp | 2 +- .../renderer_vulkan/vk_query_cache.cpp | 6 +-- .../renderer_vulkan/vk_rasterizer.cpp | 2 +- .../renderer_vulkan/vk_scheduler.cpp | 2 +- .../renderer_vulkan/vk_texture_cache.cpp | 44 +++++++++---------- src/video_core/vulkan_common/vulkan_wrapper.h | 12 +++++ 10 files changed, 57 insertions(+), 45 deletions(-) diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 789f4da2ed..2bca1ba28f 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -436,7 +436,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo .layerCount = 1, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, barrier); } diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index a2c4727703..2b83902bc0 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp @@ -69,7 +69,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo .layerCount = 1, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, barrier); } @@ -171,10 +171,10 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe .imageOffset{.x = 0, .y = 0, .z = 0}, .imageExtent{extent}, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, read_barrier); cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, copy); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, memory_write_barrier, nullptr, image_write_barrier); } diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index a359502046..7bd0a260b3 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -437,13 +437,13 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer, scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) { if (barrier) { - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER); } cmdbuf.CopyBuffer(src_buffer, dst_buffer, VideoCommon::FixSmallVectorADL(vk_copies)); if (barrier) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER); + vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, WRITE_BARRIER); } }); } @@ -457,7 +457,7 @@ void BufferCacheRuntime::PreCopyBarrier() { }; scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([](vk::CommandBuffer cmdbuf) { - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER); }); } @@ -471,7 +471,7 @@ void BufferCacheRuntime::PostCopyBarrier() { }; scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([](vk::CommandBuffer cmdbuf) { - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, WRITE_BARRIER); }); } @@ -495,10 +495,10 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) { - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER); cmdbuf.FillBuffer(dest_buffer, offset, size, value); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, WRITE_BARRIER); }); } diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index f198b65d69..2a94543ea6 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -454,8 +454,8 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_ const VkDescriptorSet set = descriptor_allocator.Commit(); device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier); + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms); @@ -537,7 +537,7 @@ void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffe cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms); cmdbuf.Dispatch(1, 1, 1); cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier); + vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, write_barrier); }); } } @@ -589,9 +589,9 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, .layerCount = VK_REMAINING_ARRAY_LAYERS, }, }; - cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT - : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); + cmdbuf.PipelineBarrier(is_initialized ? vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER + : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); }); for (const VideoCommon::SwizzleParameters& swizzle : swizzles) { @@ -648,7 +648,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, }, }; cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, image_barrier); + vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, image_barrier); }); scheduler.Finish(); } diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index de854554c7..010bc9b7d4 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -429,7 +429,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) { }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, {}, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, {}, {}, {}, pre_barriers); if (blit_supported) { diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index ffb318c935..f0c704b700 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -846,7 +846,7 @@ public: scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER); + vk::PIPELINE_STAGE_HOST, 0, WRITE_BARRIER); }); std::scoped_lock lk(flush_guard); @@ -1587,13 +1587,13 @@ void QueryCacheRuntime::Barriers(bool is_prebarrier) { impl->scheduler.RequestOutsideRenderPassOperationContext(); if (is_prebarrier) { impl->scheduler.Record([](vk::CommandBuffer cmdbuf) { - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER); }); } else { impl->scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER); + vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST, 0, WRITE_BARRIER); }); } } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 3c3367cfd8..379511e8d0 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -580,7 +580,7 @@ void RasterizerVulkan::DispatchCompute() { .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, }; - scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, READ_BARRIER); }); scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); }); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index bfdc4e3c8a..fbc42875d4 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -375,7 +375,7 @@ void Scheduler::EndRenderPass() } cmdbuf.EndRenderPass(); cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, nullptr, nullptr, vk::Span(barriers.data(), num_images)); }); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index f099db74cb..7cd6aa3e7c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -860,12 +860,12 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const .subresourceRange = subresource_range, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, nullptr, nullptr, read_barriers); + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, nullptr, nullptr, read_barriers); cmdbuf.BlitImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions, vk_filter); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - 0, nullptr, nullptr, write_barriers); + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, + 0, nullptr, nullptr, write_barriers); }); } } // Anonymous namespace @@ -1123,19 +1123,19 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, {}, {}, pre_barriers); + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, {}, {}, pre_barriers); cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer, vk_in_copies); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - 0, WRITE_BARRIER, nullptr, middle_in_barrier); + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, + 0, WRITE_BARRIER, nullptr, middle_in_barrier); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, READ_BARRIER, {}, middle_out_barrier); + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, READ_BARRIER, {}, middle_out_barrier); cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - 0, {}, {}, post_barriers); + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, + 0, {}, {}, post_barriers); }); } @@ -1261,8 +1261,8 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst .layerCount = VK_REMAINING_ARRAY_LAYERS, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, nullptr, nullptr, read_barriers); + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, nullptr, nullptr, read_barriers); if (is_resolve) { cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, @@ -1274,8 +1274,8 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, MakeImageBlit(dst_region, src_region, dst_layers, src_layers), vk_filter); } - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - 0, write_barrier); + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, + 0, write_barrier); }); } @@ -1852,7 +1852,7 @@ void Image::DownloadMemory(std::span buffers_span, std::span o .layerCount = VK_REMAINING_ARRAY_LAYERS, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, read_barrier); for (size_t index = 0; index < buffers.size(); index++) { @@ -1884,7 +1884,7 @@ void Image::DownloadMemory(std::span buffers_span, std::span o .layerCount = VK_REMAINING_ARRAY_LAYERS, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, memory_write_barrier, nullptr, image_write_barrier); }); return; @@ -1919,7 +1919,7 @@ void Image::DownloadMemory(std::span buffers_span, std::span o .layerCount = VK_REMAINING_ARRAY_LAYERS, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, read_barrier); for (size_t index = 0; index < buffers.size(); index++) { @@ -1951,7 +1951,7 @@ void Image::DownloadMemory(std::span buffers_span, std::span o .layerCount = VK_REMAINING_ARRAY_LAYERS, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, memory_write_barrier, nullptr, image_write_barrier); }); } @@ -2524,8 +2524,8 @@ void TextureCacheRuntime::TransitionImageLayout(Image& image) { }; scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([barrier](vk::CommandBuffer cmdbuf) { - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, barrier); + cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, + vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, barrier); }); } } diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index aaff66359e..860cdff20e 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -146,6 +146,18 @@ inline VkResult Filter(VkResult result) { return result; } +inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE = + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + +inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER = + PIPELINE_STAGE_GRAPHICS_COMPUTE | VK_PIPELINE_STAGE_TRANSFER_BIT; + +inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST = + PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER | VK_PIPELINE_STAGE_HOST_BIT; + +inline constexpr VkPipelineStageFlags PIPELINE_STAGE_HOST = VK_PIPELINE_STAGE_HOST_BIT; + + /// Table holding Vulkan instance function pointers. struct InstanceDispatch { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{};