From a720b28b7fd71ebd01558dc2cd6df025420f4dba Mon Sep 17 00:00:00 2001 From: nmzik Date: Thu, 23 Jul 2026 23:21:26 +0200 Subject: [PATCH] graphics: cleanup --- .../command_processor/commandProcessor.h | 4 - .../command_processor/pm4Handlers.cpp | 10 +- src/graphics/guest_gpu/graphicsRun.cpp | 4 - src/graphics/guest_gpu/graphicsRun.h | 1 - src/graphics/guest_gpu/tile.cpp | 94 +++++++++------ src/graphics/host_gpu/renderer/context.cpp | 16 ++- src/graphics/host_gpu/renderer/debug.cpp | 11 +- src/graphics/host_gpu/renderer/debug.h | 1 - src/graphics/host_gpu/renderer/render.h | 36 +++--- src/graphics/host_gpu/renderer/renderDraw.cpp | 2 - src/graphics/host_gpu/renderer/shaders.cpp | 11 +- src/graphics/host_gpu/transfer.cpp | 15 ++- src/graphics/presentation/renderDoc.cpp | 7 -- src/graphics/presentation/renderDoc.h | 1 - src/graphics/shader/recompiler/ImageOps.cpp | 99 +++++++++------ src/graphics/shader/recompiler/ImageOps.h | 2 - .../recompiler/ResourceMaterialization.cpp | 18 +-- .../shader/recompiler/ScalarProvenance.cpp | 36 +++--- .../shader/recompiler/ShaderRecompiler.cpp | 26 ++-- src/graphics/shader/recompiler/SrtPatcher.cpp | 10 +- .../shader/recompiler/VectorAluOps.cpp | 84 +++++-------- .../recompiler/shaderIR/ShaderIRMemory.cpp | 114 +++++++++++------- .../spirvEmitter/spirvEmitterAluOps.cpp | 63 ++++++---- .../spirvEmitter/spirvEmitterImageOps.cpp | 57 +++++---- .../spirvEmitter/spirvEmitterValues.cpp | 42 +++---- 25 files changed, 422 insertions(+), 342 deletions(-) diff --git a/src/graphics/guest_gpu/command_processor/commandProcessor.h b/src/graphics/guest_gpu/command_processor/commandProcessor.h index 44aabf828..c685988e0 100644 --- a/src/graphics/guest_gpu/command_processor/commandProcessor.h +++ b/src/graphics/guest_gpu/command_processor/commandProcessor.h @@ -120,11 +120,7 @@ public: void SetUserDataMarker(HW::UserSgprType type) { m_user_data_marker = type; } [[nodiscard]] HW::UserSgprType GetUserDataMarker() const { return m_user_data_marker; } - void SetEmbeddedDataMarker(const uint32_t* buffer, uint32_t num_dw, uint32_t align) {} - void PushMarker(const char* str) {} - void PopMarker() {} - void PrefetchL2(void* addr, uint32_t size) {} void ResetDeCe(); void SetCeComplete(bool complete) { m_ce_complete = complete; } void WaitCe(); diff --git a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp index 199f9d788..7a3fef8a1 100644 --- a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp +++ b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp @@ -2249,9 +2249,6 @@ KYTY_CP_OP_PARSER(CpOpDmaData) { const uint64_t dst = buffer[3] | (static_cast(buffer[4]) << 32u); if (control == 0x60000000 && dst == 0x0003022c && (control2 >> 21u) == 0x141u) { - auto* addr = reinterpret_cast(src); - - cp.PrefetchL2(addr, control2 & 0x1fffffu); return 6; } @@ -2799,11 +2796,10 @@ KYTY_CP_OP_PARSER(CpOpMarker) { // EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0001000); uint32_t id = buffer[0] & 0xfffu; - uint32_t align = (buffer[0] >> 12u) & 0xfu; uint32_t len_dw = ((cmd_id >> 16u) & 0x3fffu); switch (id) { - case 0x0: cp.SetEmbeddedDataMarker(buffer + 1, len_dw, align); break; + case 0x0: break; case 0x4: cp.SetUserDataMarker(HW::UserSgprType::Vsharp); break; case 0xd: cp.SetUserDataMarker(HW::UserSgprType::Region); break; case 0x777: { @@ -2875,8 +2871,6 @@ KYTY_CP_OP_PARSER(CpOpPopMarker) { LOGF("Pop marker\n"); } - cp.PopMarker(); - return dw_num + 1; } @@ -2892,8 +2886,6 @@ KYTY_CP_OP_PARSER(CpOpPushMarker) { LOGF("Push marker: %s\n", str); } - cp.PushMarker(str); - return dw_num + 1; } diff --git a/src/graphics/guest_gpu/graphicsRun.cpp b/src/graphics/guest_gpu/graphicsRun.cpp index 0626276d0..599bf4fb1 100644 --- a/src/graphics/guest_gpu/graphicsRun.cpp +++ b/src/graphics/guest_gpu/graphicsRun.cpp @@ -1538,10 +1538,6 @@ void GraphicsRunSubmitFlipPreparation() { g_gpu->SubmitFlipPreparation(); } -void GraphicsRunWait() { - GraphicsRunSubmissionLock lock; -} - GraphicsRunSubmissionLock::GraphicsRunSubmissionLock() { if (g_gpu == nullptr || g_current_processor != nullptr || g_submission_pause_depth == UINT32_MAX) { diff --git a/src/graphics/guest_gpu/graphicsRun.h b/src/graphics/guest_gpu/graphicsRun.h index 69c905676..cc1b4a41c 100644 --- a/src/graphics/guest_gpu/graphicsRun.h +++ b/src/graphics/guest_gpu/graphicsRun.h @@ -22,7 +22,6 @@ void GraphicsRunSubmit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t void GraphicsRunSubmitCompute(uint32_t queue, uint32_t* cmd_buffer, uint32_t num_dw, bool trigger_agc_interrupt_on_done = false); void GraphicsRunSubmitFlipPreparation(); -void GraphicsRunWait(); void GraphicsRunDone(); int GraphicsRunGetFrameNum(); [[nodiscard]] bool GraphicsRunIsCommandProcessorThread() noexcept; diff --git a/src/graphics/guest_gpu/tile.cpp b/src/graphics/guest_gpu/tile.cpp index 77cb328f3..1fb33feac 100644 --- a/src/graphics/guest_gpu/tile.cpp +++ b/src/graphics/guest_gpu/tile.cpp @@ -406,8 +406,8 @@ struct TextureBlockLayout { static bool GetTextureBlockLayout(uint32_t format, uint32_t tile, TextureBlockLayout& out) { uint32_t width_log2 = 0, height_log2 = 0; - if (tile == 1 && Gen5Standard256BLayout(format, &out.bytes, &out.texel_width, - &out.texel_height, &width_log2, &height_log2)) { + if (tile == 1 && Gen5Standard256BLayout(format, &out.bytes, &out.texel_width, &out.texel_height, + &width_log2, &height_log2)) { out.block_size = 256; } else if (tile == 5 && Gen5Standard4KBLayout(format, &out.bytes, &out.texel_width, &out.texel_height, &width_log2, &height_log2)) { @@ -524,7 +524,7 @@ static void SetMacroMipLayout(const TextureBlockLayout& block, uint32_t tile, ui } bool TileGetTextureVolumeLayout(uint32_t format, uint32_t width, uint32_t height, uint32_t depth, - uint32_t levels, uint32_t tile, TileVolumeLayout& out) { + uint32_t levels, uint32_t tile, TileVolumeLayout& out) { if (width == 0 || height == 0 || depth == 0 || levels == 0 || levels > 16) { return false; } @@ -543,21 +543,26 @@ bool TileGetTextureVolumeLayout(uint32_t format, uint32_t width, uint32_t height TileBlockLayout block {}; if (!TileGetBlockLayout(family, element.bytes, block)) return false; - out = {}; - out.family = family; - out.bytes_per_element = element.bytes; - out.texel_width = element.texel_width; - out.texel_height = element.texel_height; - out.block_depth = block.block_depth; - out.first_tail_level = levels; + out = {}; + out.family = family; + out.bytes_per_element = element.bytes; + out.texel_width = element.texel_width; + out.texel_height = element.texel_height; + out.block_depth = block.block_depth; + out.first_tail_level = levels; const uint32_t width0 = (width + element.texel_width - 1u) / element.texel_width; const uint32_t height0 = (height + element.texel_height - 1u) / element.texel_height; const bool thick4 = family == TileBlockFamily::Standard4KB3D; const bool thick64 = family == TileBlockFamily::Standard64KB3D || family == TileBlockFamily::Prt64KB3D; - const uint32_t max_tail = thick4 ? 5u : (thick64 ? 10u : 12u); - uint32_t tail_width = thick4 ? block.block_width : block.block_width >> 1u; - uint32_t tail_height = thick4 ? block.block_height >> 1u : block.block_height; + uint32_t max_tail = 12u; + if (thick4) { + max_tail = 5u; + } else if (thick64) { + max_tail = 10u; + } + uint32_t tail_width = thick4 ? block.block_width : block.block_width >> 1u; + uint32_t tail_height = thick4 ? block.block_height >> 1u : block.block_height; if (family == TileBlockFamily::Depth64KB && element.bytes < 4) { tail_width = 64; tail_height = 128; @@ -574,18 +579,23 @@ bool TileGetTextureVolumeLayout(uint32_t format, uint32_t width, uint32_t height } out.level_widths[level] = AlignUp(mip_width, block.block_width); out.level_heights[level] = AlignUp(mip_height, block.block_height); - out.level_sizes[level] = static_cast(block.block_depth) * - out.level_widths[level] * out.level_heights[level] * - element.bytes; + out.level_sizes[level] = static_cast(block.block_depth) * + out.level_widths[level] * out.level_heights[level] * element.bytes; out.block_slice_size += out.level_sizes[level]; } - const auto bytes_log2 = std::countr_zero(element.bytes); + const auto bytes_log2 = std::countr_zero(element.bytes); + const Gen5MipTailLocation* tail_locations = nullptr; + if (thick4) { + tail_locations = GEN5_MIP_TAIL_LOCATIONS_THICK_4KB[bytes_log2]; + } else if (thick64) { + tail_locations = GEN5_MIP_TAIL_LOCATIONS_THICK_64KB[bytes_log2]; + } else { + tail_locations = GEN5_MIP_TAIL_LOCATIONS_THIN_64KB[bytes_log2]; + } for (uint32_t level = out.first_tail_level; level < levels; ++level) { - const auto index = level - out.first_tail_level; - const auto tail = thick4 ? GEN5_MIP_TAIL_LOCATIONS_THICK_4KB[bytes_log2][index] - : (thick64 ? GEN5_MIP_TAIL_LOCATIONS_THICK_64KB[bytes_log2][index] - : GEN5_MIP_TAIL_LOCATIONS_THIN_64KB[bytes_log2][index]); + const auto index = level - out.first_tail_level; + const auto tail = tail_locations[index]; out.level_sizes[level] = block.block_size; out.level_widths[level] = block.block_width; out.level_heights[level] = block.block_height; @@ -1047,7 +1057,7 @@ static constexpr uint32_t Depth64KB64XOffsetBytes(uint32_t x); static constexpr uint32_t Depth64KB64YOffsetBytes(uint32_t y); bool TileGetBlockLayout(TileBlockFamily family, uint32_t bytes_per_element, - TileBlockLayout& layout) { + TileBlockLayout& layout) { if (!std::has_single_bit(bytes_per_element) || bytes_per_element > 16) { return false; } @@ -1067,13 +1077,25 @@ bool TileGetBlockLayout(TileBlockFamily family, uint32_t bytes_per_element, }; switch (family) { case TileBlockFamily::Standard256B: - result.block_size = 256; - result.block_width = bytes_per_element <= 2 ? 16 : (bytes_per_element <= 8 ? 8 : 4); + result.block_size = 256; + if (bytes_per_element <= 2) { + result.block_width = 16; + } else if (bytes_per_element <= 8) { + result.block_width = 8; + } else { + result.block_width = 4; + } result.block_height = result.block_size / (result.block_width * bytes_per_element); break; case TileBlockFamily::Standard4KB: - result.block_size = 4096; - result.block_width = bytes_per_element <= 2 ? 64 : (bytes_per_element <= 8 ? 32 : 16); + result.block_size = 4096; + if (bytes_per_element <= 2) { + result.block_width = 64; + } else if (bytes_per_element <= 8) { + result.block_width = 32; + } else { + result.block_width = 16; + } result.block_height = result.block_size / (result.block_width * bytes_per_element); break; case TileBlockFamily::Standard4KB3D: { @@ -1126,7 +1148,7 @@ bool TileGetBlockLayout(TileBlockFamily family, uint32_t bytes_per_element, } bool TileGetBlockOffset(const TileBlockLayout& layout, uint32_t x, uint32_t y, uint32_t z, - uint32_t& byte_offset) { + uint32_t& byte_offset) { TileBlockLayout expected {}; if (!TileGetBlockLayout(layout.family, layout.bytes_per_element, expected) || layout.block_size != expected.block_size || layout.block_width != expected.block_width || @@ -1226,12 +1248,12 @@ bool TileGetBlockOffset(const TileBlockLayout& layout, uint32_t x, uint32_t y, u } bool TileGetBlockXor(const TileBlockLayout& layout, uint32_t block_x, uint32_t block_y, - uint32_t& byte_offset) { + uint32_t& byte_offset) { return TileGetBlockXor(layout, block_x, block_y, 0, byte_offset); } bool TileGetBlockXor(const TileBlockLayout& layout, uint32_t block_x, uint32_t block_y, - uint32_t block_z, uint32_t& byte_offset) { + uint32_t block_z, uint32_t& byte_offset) { TileBlockLayout expected {}; if (!TileGetBlockLayout(layout.family, layout.bytes_per_element, expected) || layout.block_size != expected.block_size || layout.block_width != expected.block_width || @@ -1377,8 +1399,8 @@ bool TileGetHtileSize(uint32_t width, uint32_t height, TileSizeAlign& htile_size } bool TileGetDepthSize(uint32_t width, uint32_t height, uint32_t pitch, uint32_t z_format, - uint32_t stencil_format, bool htile, TileSizeAlign& stencil_size, - TileSizeAlign& htile_size, TileSizeAlign& depth_size, + uint32_t stencil_format, bool htile, TileSizeAlign& stencil_size, + TileSizeAlign& htile_size, TileSizeAlign& depth_size, uint32_t num_fragments_log2) { EXIT_IF(pitch != 0); // Prospero derives uncompressed depth/stencil as independent 64 KiB block surfaces. @@ -1410,8 +1432,8 @@ bool TileGetDepthSize(uint32_t width, uint32_t height, uint32_t pitch, uint32_t if (depth_bytes_total <= UINT32_MAX && stencil_bytes_total <= UINT32_MAX && htile_valid) { depth_size = {static_cast(depth_bytes_total), 65536}; stencil_size = stencil_format == 1 - ? TileSizeAlign {static_cast(stencil_bytes_total), 65536} - : TileSizeAlign {}; + ? TileSizeAlign {static_cast(stencil_bytes_total), 65536} + : TileSizeAlign {}; htile_size = calculated_htile; return true; } @@ -1441,7 +1463,7 @@ uint32_t TileGetDepthPitch(uint32_t width, uint32_t bytes_per_element, } bool TileGetRenderTargetSize(uint32_t width, uint32_t height, uint32_t pitch, - uint32_t bytes_per_element, TileSizeAlign& total_size, + uint32_t bytes_per_element, TileSizeAlign& total_size, uint32_t num_fragments_log2) { total_size = {}; uint32_t block_width = 0; @@ -1466,7 +1488,7 @@ bool TileGetRenderTargetSize(uint32_t width, uint32_t height, uint32_t pitch, bool TileGetRenderTargetMipLayout(uint32_t width, uint32_t height, uint32_t pitch, uint32_t bytes_per_element, uint32_t levels, - TileSizeAlign& total_size, TileSizeOffset* level_sizes, + TileSizeAlign& total_size, TileSizeOffset* level_sizes, TilePaddedSize* padded_size) { total_size = {}; if (width == 0 || height == 0 || levels == 0 || levels > 16 || @@ -1578,7 +1600,7 @@ void TileGetTextureSize(uint32_t format, uint32_t width, uint32_t height, uint32 void TileGetTextureTotalSize(uint32_t format, uint32_t width, uint32_t height, uint32_t depth, uint32_t pitch, uint32_t levels, uint32_t tile, bool volume_texture, - TileSizeAlign& total_size) { + TileSizeAlign& total_size) { EXIT_NOT_IMPLEMENTED(depth == 0); if (volume_texture) { TileVolumeLayout volume {}; diff --git a/src/graphics/host_gpu/renderer/context.cpp b/src/graphics/host_gpu/renderer/context.cpp index dbf55ce76..b28e8a343 100644 --- a/src/graphics/host_gpu/renderer/context.cpp +++ b/src/graphics/host_gpu/renderer/context.cpp @@ -100,6 +100,10 @@ CommandBuffer::CommandBuffer() : m_graphics(GetRenderContext().GetGraphics()), m_slot(g_command_pool.Allocate()), m_host_stream(m_graphics) {} +CommandBuffer::~CommandBuffer() { + Release(); +} + void ThreadCommandPool::Create() { auto& graphics = GetRenderContext().GetGraphics(); EXIT_IF(m_pool != nullptr || graphics.queue_family == static_cast(-1)); @@ -200,8 +204,11 @@ void CommandBuffer::Release() { EXIT_NOT_IMPLEMENTED(!IsInvalid()); } -void CommandBuffer::DeleteAfterFence(VulkanBuffer& buffer) { - m_delete_after_fence.push_back(&buffer); +void CommandBuffer::RetireBufferAfterFence(std::unique_ptr buffer) { + if (IsInvalid() || m_execute || buffer == nullptr || buffer->buffer == nullptr) { + EXIT("cannot retire a buffer on an invalid or submitted command buffer\n"); + } + m_retired_buffers.push_back(std::move(buffer)); } void CommandBuffer::RetainResourceUntilFence(std::shared_ptr resource) { @@ -375,11 +382,10 @@ void CommandBuffer::ReleaseResourcesAfterFence() { } void CommandBuffer::DeleteBuffersAfterFence() { - for (auto* buffer: m_delete_after_fence) { + for (const auto& buffer: m_retired_buffers) { GetRenderContext().GetGraphics().DeleteBuffer(*buffer); - delete buffer; } - m_delete_after_fence.clear(); + m_retired_buffers.clear(); } void CommandBuffer::BeginRenderPass(VulkanFramebuffer& framebuffer, RenderColorInfo* colors, diff --git a/src/graphics/host_gpu/renderer/debug.cpp b/src/graphics/host_gpu/renderer/debug.cpp index e566bd197..0760e8d43 100644 --- a/src/graphics/host_gpu/renderer/debug.cpp +++ b/src/graphics/host_gpu/renderer/debug.cpp @@ -9,6 +9,7 @@ #include "graphics/guest_gpu/hardwareContext.h" #include "graphics/host_gpu/renderer/render.h" +#include #include #include #include @@ -100,8 +101,6 @@ void sh_print(const char* func, const HW::Shader& /*uc*/) { LOGF("%s\n", func); } -void sh_check(const HW::Shader& /*uc*/) {} - std::vector rt_print(const char* func, const HW::RenderTarget& rt) { std::vector dst; dst.reserve(53); @@ -1135,10 +1134,10 @@ static ScissorRect ScissorRectClamp(ScissorRect r, uint32_t width, uint32_t heig int max_right = static_cast(width); int max_bottom = static_cast(height); - r.left = (r.left < 0 ? 0 : (r.left > max_right ? max_right : r.left)); - r.right = (r.right < 0 ? 0 : (r.right > max_right ? max_right : r.right)); - r.top = (r.top < 0 ? 0 : (r.top > max_bottom ? max_bottom : r.top)); - r.bottom = (r.bottom < 0 ? 0 : (r.bottom > max_bottom ? max_bottom : r.bottom)); + r.left = std::clamp(r.left, 0, max_right); + r.right = std::clamp(r.right, 0, max_right); + r.top = std::clamp(r.top, 0, max_bottom); + r.bottom = std::clamp(r.bottom, 0, max_bottom); if (!ScissorRectValid(r)) { r.right = r.left; diff --git a/src/graphics/host_gpu/renderer/debug.h b/src/graphics/host_gpu/renderer/debug.h index 53d3de2ee..b06022f56 100644 --- a/src/graphics/host_gpu/renderer/debug.h +++ b/src/graphics/host_gpu/renderer/debug.h @@ -33,7 +33,6 @@ bool graphics_debug_dump_enabled(); void uc_print(const char* func, const HW::UserConfig& uc); void uc_check(const HW::UserConfig& uc); void sh_print(const char* func, const HW::Shader& uc); -void sh_check(const HW::Shader& uc); std::vector rt_print(const char* func, const HW::RenderTarget& rt); bool RenderIsColorTileModeLinear(uint32_t tile_mode); void hw_print(const RenderCommandBuffer& buffer); diff --git a/src/graphics/host_gpu/renderer/render.h b/src/graphics/host_gpu/renderer/render.h index a62802415..35cc56942 100644 --- a/src/graphics/host_gpu/renderer/render.h +++ b/src/graphics/host_gpu/renderer/render.h @@ -69,7 +69,7 @@ private: class CommandBuffer { public: CommandBuffer(); - ~CommandBuffer() { Release(); } + ~CommandBuffer(); KYTY_CLASS_NO_COPY(CommandBuffer); @@ -88,7 +88,7 @@ public: void WaitForFenceOnly(); void WaitForFence(); void WaitForFenceAndReset(); - void DeleteAfterFence(VulkanBuffer& buffer); + void RetireBufferAfterFence(std::unique_ptr buffer); void RetainResourceUntilFence(std::shared_ptr resource); void RecycleDescriptorAfterFence(VulkanDescriptorSet& set); @@ -107,22 +107,22 @@ private: void DeleteBuffersAfterFence(); void RecycleDescriptorsAfterFence(); - GraphicContext& m_graphics; - CommandSlot* m_slot = nullptr; - bool m_execute = false; - bool m_fence_waited = false; - uint64_t m_submit_seq = 0; - uint32_t m_debug_op = 0; - uint64_t m_debug_submit_id = 0; - uint32_t m_debug_arg0 = 0; - uint32_t m_debug_arg1 = 0; - uint32_t m_debug_arg2 = 0; - uint32_t m_debug_arg3 = 0; - uint64_t m_debug_arg4 = 0; - std::vector m_delete_after_fence; - FenceResourceRetainer m_fence_resources; - std::vector m_descriptor_sets_after_fence; - HostStreamBuffer m_host_stream; + GraphicContext& m_graphics; + CommandSlot* m_slot = nullptr; + bool m_execute = false; + bool m_fence_waited = false; + uint64_t m_submit_seq = 0; + uint32_t m_debug_op = 0; + uint64_t m_debug_submit_id = 0; + uint32_t m_debug_arg0 = 0; + uint32_t m_debug_arg1 = 0; + uint32_t m_debug_arg2 = 0; + uint32_t m_debug_arg3 = 0; + uint64_t m_debug_arg4 = 0; + std::vector> m_retired_buffers; + FenceResourceRetainer m_fence_resources; + std::vector m_descriptor_sets_after_fence; + HostStreamBuffer m_host_stream; }; class RenderCommandBuffer final: public CommandBuffer { diff --git a/src/graphics/host_gpu/renderer/renderDraw.cpp b/src/graphics/host_gpu/renderer/renderDraw.cpp index b57a344df..d946ab735 100644 --- a/src/graphics/host_gpu/renderer/renderDraw.cpp +++ b/src/graphics/host_gpu/renderer/renderDraw.cpp @@ -1120,7 +1120,6 @@ void RenderDrawIndex(uint64_t submit_id, RenderCommandBuffer& buffer, uint32_t i instance_count, render_target_slice_offset, static_cast(vertex_offset_add), first_instance); } - sh_check(sh_ctx); uc_check(ucfg); @@ -1248,7 +1247,6 @@ void RenderDrawIndexAuto(uint64_t submit_id, RenderCommandBuffer& buffer, uint32 index_count, flags, render_target_slice_offset, instance_count, first_vertex, first_instance); } - sh_check(sh_ctx); uc_check(ucfg); diff --git a/src/graphics/host_gpu/renderer/shaders.cpp b/src/graphics/host_gpu/renderer/shaders.cpp index 880bebad8..dd959456c 100644 --- a/src/graphics/host_gpu/renderer/shaders.cpp +++ b/src/graphics/host_gpu/renderer/shaders.cpp @@ -620,10 +620,13 @@ void CreatePipelineInternal(PipelineCache::GraphicsPipeline& pipeline, vk::Rende break; } case 3: { - auto swizzle = vs_input_info.resources[index].DstSelXYZ(); - auto expected = - (attr_size == 1 ? DstSel(4, 0, 0) - : (attr_size == 2 ? DstSel(4, 5, 0) : DstSel(4, 5, 6))); + auto swizzle = vs_input_info.resources[index].DstSelXYZ(); + auto expected = DstSel(4, 5, 6); + switch (attr_size) { + case 1: expected = DstSel(4, 0, 0); break; + case 2: expected = DstSel(4, 5, 0); break; + default: break; + } if (swizzle != expected) { log_unsupported_vertex_swizzle(swizzle, expected); } diff --git a/src/graphics/host_gpu/transfer.cpp b/src/graphics/host_gpu/transfer.cpp index 299dfa58b..5ce812409 100644 --- a/src/graphics/host_gpu/transfer.cpp +++ b/src/graphics/host_gpu/transfer.cpp @@ -774,14 +774,16 @@ void CopyImage(CommandBuffer& buffer, std::span regions, compressed_copy_size = std::max(compressed_copy_size, CompressedImageCopyBufferSize(r, dst_image)); } - VulkanBuffer* compressed_copy_buffer = nullptr; + std::unique_ptr compressed_copy_owner; + VulkanBuffer* compressed_copy_buffer = nullptr; if (compressed_copy_size != 0) { - compressed_copy_buffer = new VulkanBuffer; + compressed_copy_owner = std::make_unique(); + compressed_copy_buffer = compressed_copy_owner.get(); compressed_copy_buffer->usage = vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst; compressed_copy_buffer->memory.property = {}; buffer.GetGraphics().CreateBuffer(compressed_copy_size, *compressed_copy_buffer); - buffer.DeleteAfterFence(*compressed_copy_buffer); + buffer.RetireBufferAfterFence(std::move(compressed_copy_owner)); } for (const auto& r: regions) { @@ -850,13 +852,14 @@ void CopyImageViaBuffer(CommandBuffer& buffer, VulkanImage& src_image, std::min(src_image.extent.height, MAX_COPY_BUFFER_SIZE / row_bytes)); const auto copy_buffer_size = row_bytes * rows_per_chunk; - auto& graphics = buffer.GetGraphics(); - auto* copy_buffer = new VulkanBuffer; + auto& graphics = buffer.GetGraphics(); + auto copy_buffer_owner = std::make_unique(); + auto* copy_buffer = copy_buffer_owner.get(); copy_buffer->usage = vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst; copy_buffer->memory.property = vk::MemoryPropertyFlagBits::eDeviceLocal; graphics.CreateBuffer(copy_buffer_size, *copy_buffer); - buffer.DeleteAfterFence(*copy_buffer); + buffer.RetireBufferAfterFence(std::move(copy_buffer_owner)); auto vk_buffer = buffer.Handle(); const auto src_layout = src_image.layout; diff --git a/src/graphics/presentation/renderDoc.cpp b/src/graphics/presentation/renderDoc.cpp index c6a4371e8..1c0f81ca0 100644 --- a/src/graphics/presentation/renderDoc.cpp +++ b/src/graphics/presentation/renderDoc.cpp @@ -187,10 +187,6 @@ void RenderDocInit() { } } -bool RenderDocIsLoaded() { - return g_api != nullptr; -} - void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window) { if (g_api == nullptr) { return; @@ -281,9 +277,6 @@ void RenderDocOnPresent() { #else void RenderDocInit() {} -bool RenderDocIsLoaded() { - return false; -} void RenderDocSetActiveWindow(vk::Instance /*instance*/, SDL_Window* /*window*/) {} void RenderDocRequestCapture() {} void RenderDocOnPresent() {} diff --git a/src/graphics/presentation/renderDoc.h b/src/graphics/presentation/renderDoc.h index c359cb3f0..ec275f04d 100644 --- a/src/graphics/presentation/renderDoc.h +++ b/src/graphics/presentation/renderDoc.h @@ -9,7 +9,6 @@ struct SDL_Window; namespace Libs::Graphics { void RenderDocInit(); -bool RenderDocIsLoaded(); void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window); void RenderDocRequestCapture(); void RenderDocOnPresent(); diff --git a/src/graphics/shader/recompiler/ImageOps.cpp b/src/graphics/shader/recompiler/ImageOps.cpp index 0e861b71b..610a228b9 100644 --- a/src/graphics/shader/recompiler/ImageOps.cpp +++ b/src/graphics/shader/recompiler/ImageOps.cpp @@ -212,6 +212,62 @@ const MimgAtomicInfo* LookupAtomic(uint32_t opcode) { return nullptr; } +Opcode DecodeMimgOpcode(uint32_t opcode, const MimgSampleInfo* sample, const MimgGatherInfo* gather, + const MimgAtomicInfo* atomic) { + if (sample != nullptr) { + return Opcode::ImageSample; + } + if (gather != nullptr) { + return gather->decoded; + } + if (atomic != nullptr) { + return atomic->decoded; + } + + switch (opcode) { + case 0x00u: return Opcode::ImageLoad; + case 0x01u: return Opcode::ImageLoadMip; + case 0x08u: return Opcode::ImageStore; + case 0x09u: return Opcode::ImageStoreMip; + case 0x0eu: return Opcode::ImageGetResinfo; + case 0x60u: return Opcode::ImageGetLod; + default: return Opcode::Unsupported; + } +} + +uint32_t DecodeMimgSampleFlags(const MimgSampleInfo* sample, const MimgGatherInfo* gather) { + if (sample != nullptr) { + return sample->flags; + } + if (gather != nullptr) { + return gather->flags; + } + return 0; +} + +uint32_t DecodeMimgAddressComponents(uint32_t opcode, ImageDimension dimension, + const MimgSampleInfo* sample, const MimgGatherInfo* gather, + const MimgAtomicInfo* atomic) { + if (sample != nullptr) { + return ImageSampleAddressComponents(sample->flags, dimension); + } + if (gather != nullptr) { + return ImageSampleAddressComponents(gather->flags, dimension); + } + if (atomic != nullptr) { + return 3u; + } + + switch (opcode) { + case 0x01u: + case 0x09u: return ImageCoordComponents(dimension) + 1u; + case 0x00u: + case 0x08u: + case 0x60u: return ImageCoordComponents(dimension); + default: return 0; + } +} + uint32_t CountDmaskComponents(uint32_t dmask) { uint32_t count = 0; for (uint32_t i = 0; i < 4u; i++) { @@ -262,39 +318,22 @@ bool DecodeMimg(uint32_t pc, std::span code, uint32_t word_index inst.word_count = word_count; inst.family = Family::MIMG; inst.opcode_id = opcode; - inst.opcode = (sample != nullptr ? Opcode::ImageSample - : gather != nullptr ? gather->decoded - : atomic != nullptr ? atomic->decoded - : opcode == 0x00u ? Opcode::ImageLoad - : opcode == 0x01u ? Opcode::ImageLoadMip - : opcode == 0x08u ? Opcode::ImageStore - : opcode == 0x09u ? Opcode::ImageStoreMip - : opcode == 0x0eu ? Opcode::ImageGetResinfo - : opcode == 0x60u ? Opcode::ImageGetLod - : Opcode::Unsupported); + inst.opcode = DecodeMimgOpcode(opcode, sample, gather, atomic); inst.dmask = (word0 >> 8u) & 0xfu; inst.data_dwords = gather != nullptr ? 4u : CountDmaskComponents(inst.dmask); inst.glc = ((word0 >> 13u) & 1u) != 0; inst.slc = ((word0 >> 25u) & 1u) != 0; - inst.image_sample_flags = (sample != nullptr ? sample->flags - : gather != nullptr ? gather->flags - : 0u) | - (a16 ? ImageSampleFlagA16 : 0u); - inst.image_dimension = dimension; - inst.image_nsa_dwords = nsa_dwords; + inst.image_sample_flags = DecodeMimgSampleFlags(sample, gather); + if (a16) { + inst.image_sample_flags |= ImageSampleFlagA16; + } + inst.image_dimension = dimension; + inst.image_nsa_dwords = nsa_dwords; for (uint32_t i = 0; i < nsa_dwords * 4u && i < MaxImageNsaAddressComponents; i++) { inst.image_nsa_addr[i] = (code[word_index + 2u + i / 4u] >> ((i % 4u) * 8u)) & 0xffu; } inst.image_address_components = - sample != nullptr ? ImageSampleAddressComponents(sample->flags, dimension) - : gather != nullptr ? ImageSampleAddressComponents(gather->flags, dimension) - : atomic != nullptr ? 3u - : opcode == 0x60u ? ImageCoordComponents(dimension) - : opcode == 0x01u ? ImageCoordComponents(dimension) + 1u - : opcode == 0x00u ? ImageCoordComponents(dimension) - : (opcode == 0x09u ? ImageCoordComponents(dimension) + 1u - : opcode == 0x08u ? ImageCoordComponents(dimension) - : 0u); + DecodeMimgAddressComponents(opcode, dimension, sample, gather, atomic); SetRawWords(inst, code, word_index, word_count); if (inst.opcode == Opcode::Unsupported) { @@ -318,14 +357,4 @@ const char* MimgSampleOpcodeName(uint32_t opcode) { return sample != nullptr ? sample->name : nullptr; } -uint32_t MimgSampleOpcodeFlags(uint32_t opcode) { - const auto* sample = LookupSample(opcode); - return sample != nullptr ? sample->flags : 0u; -} - -uint32_t MimgSampleAddressComponents(uint32_t opcode) { - const auto* sample = LookupSample(opcode); - return sample != nullptr ? sample->address_components : 0u; -} - } // namespace Libs::Graphics::ShaderRecompiler::Decoder diff --git a/src/graphics/shader/recompiler/ImageOps.h b/src/graphics/shader/recompiler/ImageOps.h index 62862b4ee..10bd28472 100644 --- a/src/graphics/shader/recompiler/ImageOps.h +++ b/src/graphics/shader/recompiler/ImageOps.h @@ -9,8 +9,6 @@ bool DecodeMimg(uint32_t pc, std::span code, uint32_t word_index std::string* error); const char* MimgSampleOpcodeName(uint32_t opcode); -uint32_t MimgSampleOpcodeFlags(uint32_t opcode); -uint32_t MimgSampleAddressComponents(uint32_t opcode); } // namespace Libs::Graphics::ShaderRecompiler::Decoder diff --git a/src/graphics/shader/recompiler/ResourceMaterialization.cpp b/src/graphics/shader/recompiler/ResourceMaterialization.cpp index da2008138..6fb8519d9 100644 --- a/src/graphics/shader/recompiler/ResourceMaterialization.cpp +++ b/src/graphics/shader/recompiler/ResourceMaterialization.cpp @@ -201,7 +201,7 @@ bool ValidateResourceSpecialization(const Program& program, const ResourceSnapsh } bool MaterializeResources(const Program& program, const SrtRuntime& runtime, - ResourceSnapshot& snapshot, std::string* error) { + ResourceSnapshot& snapshot, std::string* error) { if (!program.resource_tracking_complete) { if (error != nullptr) { *error = "shader resources were not tracked"; @@ -256,10 +256,12 @@ bool MaterializeResources(const Program& program, const SrtRuntime& runtime, base &= ~uint64_t {3}; } const auto before = static_cast(-static_cast(address.min_offset)); - const auto binding_base = address.kind == ResourceKind::Flat - ? base & ~(FlatAddressWindowSize - 1u) - : base >= before ? base - before - : 0; + uint64_t binding_base = 0; + if (address.kind == ResourceKind::Flat) { + binding_base = base & ~(FlatAddressWindowSize - 1u); + } else if (base >= before) { + binding_base = base - before; + } next.addresses.push_back({base, binding_base}); } else { if (!runtime.flat_memory_base.has_value()) { @@ -289,7 +291,7 @@ bool SpecializeResources(Program& program, const ResourceSnapshot& snapshot, std program.binding_layout_complete) { if (error != nullptr) { *error = !program.resource_tracking_complete ? "shader resources were not tracked" - : "resource specialization is too late"; + : "resource specialization is too late"; } return false; } @@ -347,8 +349,8 @@ bool SpecializeResources(Program& program, const ResourceSnapshot& snapshot, std } struct ImagePatch { std::reference_wrapper inst; - ResourceKind kind; - Decoder::ImageDimension dimension; + ResourceKind kind; + Decoder::ImageDimension dimension; }; std::vector patches; for (auto& block: program.blocks) { diff --git a/src/graphics/shader/recompiler/ScalarProvenance.cpp b/src/graphics/shader/recompiler/ScalarProvenance.cpp index 56771ae3f..fa3e8ec7e 100644 --- a/src/graphics/shader/recompiler/ScalarProvenance.cpp +++ b/src/graphics/shader/recompiler/ScalarProvenance.cpp @@ -392,7 +392,7 @@ private: void ClearVectorLanes(uint32_t reg, ScalarState& state) { const auto first = state.vector_lanes.lower_bound(VectorLaneKey(reg, 0)); - const auto last = state.vector_lanes.lower_bound((static_cast(reg) + 1u) << 32u); + const auto last = state.vector_lanes.lower_bound((static_cast(reg) + 1u) << 32u); state.vector_lanes.erase(first, last); } @@ -416,8 +416,8 @@ private: for (uint32_t i = 0; i < inst.src_count; i++) { uint32_t src_reg = 0; if (ScalarRegister(inst.src[i], src_reg) && - state.regs[src_reg] > ScalarProvenance::Unknown) { - address_base = state.regs[src_reg]; + state.regs[src_reg] > ScalarProvenance::Unknown) { + address_base = state.regs[src_reg]; break; } } @@ -529,16 +529,18 @@ private: if (inst.dst.kind == OperandKind::Register && inst.dst.reg.file == RegisterFile::Scc) { state.scc = inst.op == Opcode::MoveU32 && inst.src_count != 0 ? OperandValue(inst.src[0], state) - : ScalarProvenance::Unknown; + : ScalarProvenance::Unknown; return; } if (inst.dst.kind == OperandKind::Register && inst.dst.reg.file == RegisterFile::M0) { const auto before = state; const auto op = Operation(inst.op); - state.m0 = inst.op == Opcode::MoveU32 && inst.src_count != 0 - ? OperandValue(inst.src[0], before) - : op != ScalarValueOp::Unknown ? Define(inst, op, before) - : ScalarProvenance::Unknown; + state.m0 = ScalarProvenance::Unknown; + if (inst.op == Opcode::MoveU32 && inst.src_count != 0) { + state.m0 = OperandValue(inst.src[0], before); + } else if (op != ScalarValueOp::Unknown) { + state.m0 = Define(inst, op, before); + } UpdateScc(inst, before, state); return; } @@ -558,10 +560,14 @@ private: switch (inst.op) { case Opcode::MoveU32: case Opcode::MoveF32Bits: - value = inst.src_count == 0 ? ScalarProvenance::Unknown - : inst.src[0].kind == OperandKind::PcRelativeU32 - ? InternValue({ScalarValueOp::PcRelativeLow, inst.pc, inst.src[0].imm}) - : OperandValue(inst.src[0], before); + if (inst.src_count != 0) { + if (inst.src[0].kind == OperandKind::PcRelativeU32) { + value = + InternValue({ScalarValueOp::PcRelativeLow, inst.pc, inst.src[0].imm}); + } else { + value = OperandValue(inst.src[0], before); + } + } if (inst.op == Opcode::MoveU32 && inst.src_count != 0 && inst.src[0].kind == OperandKind::ImmediateU32 && inst.src[0].imm == 0 && dst != 0) { @@ -578,10 +584,10 @@ private: uint32_t src = 0; if (inst.src_count != 0 && dst + 1 < ScalarRegisters) { if (ScalarRegister(inst.src[0], src) && src + 1 < ScalarRegisters) { - value = before.regs[src]; + value = before.regs[src]; state.regs[dst + 1] = before.regs[src + 1]; } else { - value = OperandValue(inst.src[0], before); + value = OperandValue(inst.src[0], before); state.regs[dst + 1] = Constant( inst.src[0].kind == OperandKind::ImmediateU32 && inst.src[0].sext_64 ? UINT32_MAX @@ -687,7 +693,7 @@ private: if (inst.memory.kind == ResourceKind::Buffer || (inst.memory.kind == ResourceKind::ScalarBuffer && inst.op == Opcode::SBufferLoadDword)) { - const auto base = inst.memory.resource * 4u; + const auto base = inst.memory.resource * 4u; inst.memory.resource_source = AddDescriptor(state, base, 4); return; } diff --git a/src/graphics/shader/recompiler/ShaderRecompiler.cpp b/src/graphics/shader/recompiler/ShaderRecompiler.cpp index 5d0bd73c4..81aa968b9 100644 --- a/src/graphics/shader/recompiler/ShaderRecompiler.cpp +++ b/src/graphics/shader/recompiler/ShaderRecompiler.cpp @@ -180,9 +180,11 @@ bool IsDecodedSgpr(const Decoder::Operand& op) { } uint32_t DecodedSgprReg(const Decoder::Operand& op) { - return op.kind == Decoder::OperandKind::VccLo - ? 106u - : (op.kind == Decoder::OperandKind::VccHi ? 107u : op.reg); + switch (op.kind) { + case Decoder::OperandKind::VccLo: return 106u; + case Decoder::OperandKind::VccHi: return 107u; + default: return op.reg; + } } bool IsDecodedVgpr(const Decoder::Operand& op) { @@ -340,14 +342,13 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded const bool vertex_index_accumulator = IsDecodedVgpr(inst.dst) && (inst.dst.reg == 0 || (user_data_base == 8 && inst.dst.reg == 5)); - uint32_t sad_zero = 0; + uint32_t sad_zero = 0; const bool vertex_offset_add = vertex_index_accumulator && IsDecodedSgpr(inst.src0) && ((inst.opcode == Decoder::Opcode::VAddI32 && IsDecodedVgpr(inst.src1) && inst.src1.reg == inst.dst.reg) || - (user_data_base == 8 && inst.dst.reg == 5 && - inst.opcode == Decoder::Opcode::VSadU32 && IsDecodedVgpr(inst.src2) && - inst.src2.reg == inst.dst.reg && + (user_data_base == 8 && inst.dst.reg == 5 && inst.opcode == Decoder::Opcode::VSadU32 && + IsDecodedVgpr(inst.src2) && inst.src2.reg == inst.dst.reg && TryDecodedOperandConstant(sgprs, inst.src1, sad_zero) && sad_zero == 0)); if (data.loads.empty() && vertex_offset_add) { const auto reg = DecodedSgprReg(inst.src0); @@ -636,7 +637,7 @@ uint32_t RewriteEmbeddedVertexFetches(IR::Program& ir, const ShaderVertexInputIn } // namespace bool TryRecompile(std::span code, const CompileOptions& options, - CompileResult& result, std::string* error) { + CompileResult& result, std::string* error) { if (code.empty()) { if (error != nullptr) { *error = "invalid shader recompiler input"; @@ -804,10 +805,11 @@ bool TryRecompile(std::span code, const CompileOptions& options, runtime.user_data = std::span(user_data, options.user_data_count); runtime.shader_base = options.shader_base != 0 ? options.shader_base : reinterpret_cast(code.data()); - runtime.read_memory = options.read_memory != nullptr ? options.read_memory - : options.user_data == nullptr ? ReadZeroMemory - : nullptr; - runtime.userdata = options.read_memory_data; + runtime.read_memory = options.read_memory; + if (runtime.read_memory == nullptr && options.user_data == nullptr) { + runtime.read_memory = ReadZeroMemory; + } + runtime.userdata = options.read_memory_data; runtime.flat_memory_base = options.flat_memory_base; if (!IR::MaterializeResources(ir, runtime, resources, error)) { return false; diff --git a/src/graphics/shader/recompiler/SrtPatcher.cpp b/src/graphics/shader/recompiler/SrtPatcher.cpp index 02ec7b971..b28954de8 100644 --- a/src/graphics/shader/recompiler/SrtPatcher.cpp +++ b/src/graphics/shader/recompiler/SrtPatcher.cpp @@ -12,9 +12,13 @@ bool PatchSrtReads(Program& program, std::string* error) { if (!program.srt_plan_complete || program.srt_patching_complete || program.resource_tracking_complete) { if (error != nullptr) { - *error = !program.srt_plan_complete ? "SRT plan is not ready" - : program.srt_patching_complete ? "SRT reads already patched" - : "resources already tracked"; + if (!program.srt_plan_complete) { + *error = "SRT plan is not ready"; + } else if (program.srt_patching_complete) { + *error = "SRT reads already patched"; + } else { + *error = "resources already tracked"; + } } return false; } diff --git a/src/graphics/shader/recompiler/VectorAluOps.cpp b/src/graphics/shader/recompiler/VectorAluOps.cpp index 225df8821..f58fbff03 100644 --- a/src/graphics/shader/recompiler/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/VectorAluOps.cpp @@ -553,6 +553,17 @@ bool DecodeVop1Sdwa(uint32_t pc, std::span code, uint32_t word_i return ReadLiteralOperands(code, word_index, inst, error); } +void ApplyDppModifier(Operand& operand, uint32_t modifier) { + operand.negate = ((modifier >> 20u) & 0x1u) != 0u; + operand.absolute = ((modifier >> 21u) & 0x1u) != 0u; + operand.dpp = true; + operand.dpp_ctrl = (modifier >> 8u) & 0x1ffu; + operand.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u; + operand.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u; + operand.dpp_bank_mask = (modifier >> 24u) & 0xfu; + operand.dpp_row_mask = (modifier >> 28u) & 0xfu; +} + bool DecodeVop1Dpp(uint32_t pc, std::span code, uint32_t word_index, uint32_t opcode, uint32_t vdst, Instruction& inst, std::string* error) { if (word_index + 1u >= code.size()) { @@ -572,15 +583,8 @@ bool DecodeVop1Dpp(uint32_t pc, std::span code, uint32_t word_in !DecodeScalarSource(src0 + 256u, pc, inst.src0, error)) { return false; } - inst.src0.negate = ((modifier >> 20u) & 0x1u) != 0u; - inst.src0.absolute = ((modifier >> 21u) & 0x1u) != 0u; - inst.src0.dpp = true; - inst.src0.dpp_ctrl = (modifier >> 8u) & 0x1ffu; - inst.src0.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u; - inst.src0.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u; - inst.src0.dpp_bank_mask = (modifier >> 24u) & 0xfu; - inst.src0.dpp_row_mask = (modifier >> 28u) & 0xfu; - inst.src_count = 1; + ApplyDppModifier(inst.src0, modifier); + inst.src_count = 1; if (!IsVop1FloatSourceOpcode(inst.opcode) && (inst.src0.negate || inst.src0.absolute)) { SetUnsupported(inst, Family::VOP1, opcode, @@ -988,16 +992,9 @@ bool DecodeVop2Dpp(uint32_t pc, std::span code, uint32_t word_in return false; } ApplyDefaultVop2F16Destination(inst); - inst.src0.negate = ((modifier >> 20u) & 0x1u) != 0u; - inst.src0.absolute = ((modifier >> 21u) & 0x1u) != 0u; - inst.src0.dpp = true; - inst.src0.dpp_ctrl = (modifier >> 8u) & 0x1ffu; - inst.src0.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u; - inst.src0.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u; - inst.src0.dpp_bank_mask = (modifier >> 24u) & 0xfu; - inst.src0.dpp_row_mask = (modifier >> 28u) & 0xfu; - inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; - inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; + ApplyDppModifier(inst.src0, modifier); + inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; + inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; if (!IsVop2FloatSourceOpcode(inst.opcode) && (inst.src0.negate || inst.src0.absolute || inst.src1.negate || inst.src1.absolute)) { @@ -1142,18 +1139,11 @@ bool DecodeVopcDpp(uint32_t pc, std::span code, uint32_t word_in !DecodeVectorGpr(vsrc1, inst.src1, error)) { return false; } - inst.dst.kind = IsVopcCompareExec(inst.opcode) ? OperandKind::ExecLo : OperandKind::VccLo; - inst.src0.negate = ((modifier >> 20u) & 0x1u) != 0u; - inst.src0.absolute = ((modifier >> 21u) & 0x1u) != 0u; - inst.src0.dpp = true; - inst.src0.dpp_ctrl = (modifier >> 8u) & 0x1ffu; - inst.src0.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u; - inst.src0.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u; - inst.src0.dpp_bank_mask = (modifier >> 24u) & 0xfu; - inst.src0.dpp_row_mask = (modifier >> 28u) & 0xfu; - inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; - inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; - inst.src_count = 2; + inst.dst.kind = IsVopcCompareExec(inst.opcode) ? OperandKind::ExecLo : OperandKind::VccLo; + ApplyDppModifier(inst.src0, modifier); + inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; + inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; + inst.src_count = 2; return ReadLiteralOperands(code, word_index, inst, error); } @@ -1249,20 +1239,8 @@ void ApplyVop3pMixAbsModifiers(Instruction& inst) { } } -void ApplyNativeVop3MadMixModifiers(Instruction& inst, uint32_t op_sel, uint32_t abs, - uint32_t neg) { - Operand* sources[] = {&inst.src0, &inst.src1, &inst.src2}; - for (uint32_t i = 0; i < 3u; i++) { - sources[i]->op_sel = ((op_sel >> i) & 1u) != 0; - sources[i]->op_sel_hi = true; - sources[i]->negate = ((neg >> i) & 1u) != 0; - sources[i]->absolute = ((abs >> i) & 1u) != 0; - } - inst.dst.sdwa_sel = ((op_sel & 0x8u) != 0) ? 5u : 4u; -} - -void ApplyNativeVop3F16TernaryModifiers(Instruction& inst, uint32_t op_sel, uint32_t abs, - uint32_t neg) { +void ApplyNativeVop3TernaryModifiers(Instruction& inst, uint32_t op_sel, uint32_t abs, + uint32_t neg) { Operand* sources[] = {&inst.src0, &inst.src1, &inst.src2}; for (uint32_t i = 0; i < 3u; i++) { sources[i]->op_sel = ((op_sel >> i) & 1u) != 0; @@ -1601,11 +1579,13 @@ bool DecodeVop3(uint32_t pc, std::span code, uint32_t word_index HasUnsupportedNativeVop3Modifiers(inst.opcode, permlane, mad_mix, vop3b_uses_sdst, scalar_modifier_limits, abs, op_sel, clamp, omod, neg); if (modifiers) { - SetUnsupported(inst, Family::VOP3, opcode, - permlane && (op_sel & ~0x3u) != 0 - ? "VOP3 perm-lane op_sel bits are not implemented" - : mad_mix ? "VOP3 mad-mix clamp/omod is not implemented" - : "VOP3 source modifiers are not implemented"); + const char* reason = "VOP3 source modifiers are not implemented"; + if (permlane && (op_sel & ~0x3u) != 0) { + reason = "VOP3 perm-lane op_sel bits are not implemented"; + } else if (mad_mix) { + reason = "VOP3 mad-mix clamp/omod is not implemented"; + } + SetUnsupported(inst, Family::VOP3, opcode, reason); return true; } if (inst.opcode == Opcode::Unsupported) { @@ -1703,9 +1683,9 @@ bool DecodeVop3(uint32_t pc, std::span code, uint32_t word_index return false; } if (mad_mix) { - ApplyNativeVop3MadMixModifiers(inst, op_sel, abs, neg); + ApplyNativeVop3TernaryModifiers(inst, op_sel, abs, neg); } else if (f16_ternary) { - ApplyNativeVop3F16TernaryModifiers(inst, op_sel, abs, neg); + ApplyNativeVop3TernaryModifiers(inst, op_sel, abs, neg); } else if (b16_binary) { ApplyNativeVop3B16BinaryModifiers(inst, op_sel); } else if (pack_b32_f16) { diff --git a/src/graphics/shader/recompiler/shaderIR/ShaderIRMemory.cpp b/src/graphics/shader/recompiler/shaderIR/ShaderIRMemory.cpp index c02dadfdc..bae97a498 100644 --- a/src/graphics/shader/recompiler/shaderIR/ShaderIRMemory.cpp +++ b/src/graphics/shader/recompiler/shaderIR/ShaderIRMemory.cpp @@ -10,6 +10,71 @@ namespace Libs::Graphics::ShaderRecompiler::IR { namespace { +Opcode BufferLoadOpcode(const Decoder::Instruction& decoded) { + switch (decoded.data_bits) { + case 8u: return decoded.data_signed ? Opcode::BufferLoadSbyte : Opcode::BufferLoadUbyte; + case 16u: return decoded.data_signed ? Opcode::BufferLoadSshort : Opcode::BufferLoadUshort; + default: return Opcode::BufferLoadDword; + } +} + +Opcode BufferStoreOpcode(uint32_t data_bits) { + switch (data_bits) { + case 8u: return Opcode::BufferStoreByte; + case 16u: return Opcode::BufferStoreShort; + default: return Opcode::BufferStoreDword; + } +} + +Opcode DsReadOpcode(const Decoder::Instruction& decoded) { + switch (decoded.data_bits) { + case 8u: return decoded.data_signed ? Opcode::DsReadSbyte : Opcode::DsReadUbyte; + case 16u: return decoded.data_signed ? Opcode::DsReadSshort : Opcode::DsReadUshort; + default: return Opcode::DsReadB32; + } +} + +Opcode FlatLoadOpcode(const Decoder::Instruction& decoded) { + switch (decoded.data_bits) { + case 8u: return decoded.data_signed ? Opcode::FlatLoadSbyte : Opcode::FlatLoadUbyte; + case 16u: return decoded.data_signed ? Opcode::FlatLoadSshort : Opcode::FlatLoadUshort; + default: return Opcode::FlatLoadDword; + } +} + +Opcode FlatStoreOpcode(uint32_t data_bits) { + switch (data_bits) { + case 8u: return Opcode::FlatStoreByte; + case 16u: return Opcode::FlatStoreShort; + default: return Opcode::FlatStoreDword; + } +} + +Opcode DsWriteOpcode(uint32_t data_bits) { + switch (data_bits) { + case 8u: return Opcode::DsWriteByte; + case 16u: return Opcode::DsWriteShort; + default: return Opcode::DsWriteB32; + } +} + +Opcode LoweredImageOpcode(Decoder::Opcode opcode) { + switch (opcode) { + case Decoder::Opcode::ImageGetResinfo: return Opcode::ImageGetResinfo; + case Decoder::Opcode::ImageGetLod: return Opcode::ImageGetLod; + case Decoder::Opcode::ImageLoad: + case Decoder::Opcode::ImageLoadMip: return Opcode::ImageLoad; + case Decoder::Opcode::ImageGather4Lz: + case Decoder::Opcode::ImageGather4C: + case Decoder::Opcode::ImageGather4CLz: + case Decoder::Opcode::ImageGather4LzO: + case Decoder::Opcode::ImageGather4CO: + case Decoder::Opcode::ImageGather4CLzO: + case Decoder::Opcode::ImageGather4H: return Opcode::ImageGather4; + default: return Opcode::ImageSample; + } +} + bool LowerScalarBufferLoadDword(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op, std::string* error) { for (uint32_t i = 0; i < decoded.data_dwords; i++) { @@ -54,12 +119,7 @@ bool LowerBufferAddressSources(const Decoder::Instruction& decoded, Instruction& } bool LowerBufferLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { - const auto ir_op = - decoded.data_bits == 8u - ? (decoded.data_signed ? Opcode::BufferLoadSbyte : Opcode::BufferLoadUbyte) - : decoded.data_bits == 16u - ? (decoded.data_signed ? Opcode::BufferLoadSshort : Opcode::BufferLoadUshort) - : Opcode::BufferLoadDword; + const auto ir_op = BufferLoadOpcode(decoded); const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; const auto typed_format_components = TypedBufferFormatComponentCount(decoded); for (uint32_t i = 0; i < count; i++) { @@ -85,9 +145,7 @@ bool LowerBufferLoad(const Decoder::Instruction& decoded, BasicBlock& block, std } bool LowerBufferStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { - const auto ir_op = decoded.data_bits == 8u ? Opcode::BufferStoreByte - : decoded.data_bits == 16u ? Opcode::BufferStoreShort - : Opcode::BufferStoreDword; + const auto ir_op = BufferStoreOpcode(decoded.data_bits); auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; if (decoded.data_bits == 32u) { const auto typed_format_components = TypedBufferFormatComponentCount(decoded); @@ -131,11 +189,7 @@ ResourceKind DsMemoryKind(const Decoder::Instruction& decoded) { } bool LowerDsRead(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { - const auto ir_op = decoded.data_bits == 8u - ? (decoded.data_signed ? Opcode::DsReadSbyte : Opcode::DsReadUbyte) - : decoded.data_bits == 16u - ? (decoded.data_signed ? Opcode::DsReadSshort : Opcode::DsReadUshort) - : Opcode::DsReadB32; + const auto ir_op = DsReadOpcode(decoded); const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; for (uint32_t i = 0; i < count; i++) { Instruction inst; @@ -164,8 +218,7 @@ bool LowerDsRead2(const Decoder::Instruction& decoded, BasicBlock& block, uint32 inst.src_count = 1; inst.memory = ByteOffsetMemoryInfo(decoded, DsMemoryKind(decoded), offsets[read] + dword * 4u); - if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, index), inst.dst, - error) || + if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, index), inst.dst, error) || !LowerSourceOperand(decoded.src0, inst.src[0], error)) { return false; } @@ -309,11 +362,7 @@ bool LowerImageAtomicU32(const Decoder::Instruction& decoded, BasicBlock& block, bool LowerFlatLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { const auto kind = FlatSegmentResourceKind(decoded.memory_segment); - const auto ir_op = decoded.data_bits == 8u - ? (decoded.data_signed ? Opcode::FlatLoadSbyte : Opcode::FlatLoadUbyte) - : decoded.data_bits == 16u - ? (decoded.data_signed ? Opcode::FlatLoadSshort : Opcode::FlatLoadUshort) - : Opcode::FlatLoadDword; + const auto ir_op = FlatLoadOpcode(decoded); const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; if (decoded.data_bits == 32u && count > 1u) { Instruction inst; @@ -356,9 +405,7 @@ bool LowerFlatLoad(const Decoder::Instruction& decoded, BasicBlock& block, std:: bool LowerFlatStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { const auto kind = FlatSegmentResourceKind(decoded.memory_segment); - const auto ir_op = decoded.data_bits == 8u ? Opcode::FlatStoreByte - : decoded.data_bits == 16u ? Opcode::FlatStoreShort - : Opcode::FlatStoreDword; + const auto ir_op = FlatStoreOpcode(decoded.data_bits); const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; for (uint32_t dword = 0; dword < count; dword++) { Instruction inst; @@ -382,9 +429,7 @@ bool LowerFlatStore(const Decoder::Instruction& decoded, BasicBlock& block, std: } bool LowerDsWrite(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { - const auto ir_op = decoded.data_bits == 8u ? Opcode::DsWriteByte - : decoded.data_bits == 16u ? Opcode::DsWriteShort - : Opcode::DsWriteB32; + const auto ir_op = DsWriteOpcode(decoded.data_bits); const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; for (uint32_t i = 0; i < count; i++) { Instruction inst; @@ -445,20 +490,7 @@ bool LowerImageOperation(const Decoder::Instruction& decoded, BasicBlock& block, return true; } - inst.op = decoded.opcode == Decoder::Opcode::ImageGetResinfo ? Opcode::ImageGetResinfo - : decoded.opcode == Decoder::Opcode::ImageGetLod ? Opcode::ImageGetLod - : decoded.opcode == Decoder::Opcode::ImageLoad || - decoded.opcode == Decoder::Opcode::ImageLoadMip - ? Opcode::ImageLoad - : decoded.opcode == Decoder::Opcode::ImageGather4Lz || - decoded.opcode == Decoder::Opcode::ImageGather4C || - decoded.opcode == Decoder::Opcode::ImageGather4CLz || - decoded.opcode == Decoder::Opcode::ImageGather4LzO || - decoded.opcode == Decoder::Opcode::ImageGather4CO || - decoded.opcode == Decoder::Opcode::ImageGather4CLzO || - decoded.opcode == Decoder::Opcode::ImageGather4H - ? Opcode::ImageGather4 - : Opcode::ImageSample; + inst.op = LoweredImageOpcode(decoded.opcode); inst.src_count = 1; inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::Image); if (!LowerRegisterOperand(decoded.dst, inst.dst, error) || diff --git a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterAluOps.cpp b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterAluOps.cpp index d20021c26..c9e508136 100644 --- a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterAluOps.cpp +++ b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterAluOps.cpp @@ -11,10 +11,13 @@ void EmitPerInvocationMask(EmitterState& state, const IR::Operand& dst, uint32_t } uint32_t EmitLogicalBinary(EmitterState& state, uint32_t opcode, uint32_t lhs, uint32_t rhs) { - const auto logical_opcode = opcode == OpBitwiseAnd ? OpLogicalAnd - : opcode == OpBitwiseOr ? OpLogicalOr - : OpLogicalNotEqual; - const auto value = state.builder.AllocateId(); + uint32_t logical_opcode = OpLogicalNotEqual; + switch (opcode) { + case OpBitwiseAnd: logical_opcode = OpLogicalAnd; break; + case OpBitwiseOr: logical_opcode = OpLogicalOr; break; + default: break; + } + const auto value = state.builder.AllocateId(); state.builder.AddFunction({logical_opcode, state.bool_type, value, lhs, rhs}); return value; } @@ -469,10 +472,11 @@ uint32_t EmitSignExtendLow16U32(EmitterState& state, uint32_t value) { uint32_t EmitU16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane, bool sign_extend) { - const auto raw = EmitValueLoad(state, operand); - const auto lane = high_lane ? (operand.op_sel_hi ? 1u : 0u) : (operand.op_sel ? 1u : 0u); - auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw; - bits = EmitAndConstant(state, bits, 0xffffu); + const auto raw = EmitValueLoad(state, operand); + const auto selected_lane = high_lane ? operand.op_sel_hi : operand.op_sel; + const auto lane = selected_lane ? 1u : 0u; + auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw; + bits = EmitAndConstant(state, bits, 0xffffu); if (high_lane ? operand.negate_hi : operand.negate) { bits = EmitAndConstant(state, EmitNegateU32(state, bits), 0xffffu); } @@ -502,8 +506,12 @@ void EmitMinMaxU16(EmitterState& state, const IR::Instruction& inst, bool signed const auto rhs = EmitU16LaneBits(state, inst.src[1], false, signed_value); const auto cond = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - const auto op = signed_value ? (max_value ? OpSGreaterThan : OpSLessThan) - : (max_value ? OpUGreaterThan : OpULessThan); + uint32_t op = 0; + if (signed_value) { + op = max_value ? OpSGreaterThan : OpSLessThan; + } else { + op = max_value ? OpUGreaterThan : OpULessThan; + } state.builder.AddFunction({op, state.bool_type, cond, lhs, rhs}); state.builder.AddFunction({OpSelect, state.uint_type, ret, cond, lhs, rhs}); EmitStoreU32(state, inst.dst, EmitAndConstant(state, ret, 0xffffu)); @@ -2039,10 +2047,11 @@ void EmitDot2AccF32F16(EmitterState& state, const IR::Instruction& inst) { } uint32_t EmitPackedF16Lane(EmitterState& state, const IR::Operand& operand, bool high_lane) { - const auto raw = EmitValueLoad(state, operand); - const auto unpacked = state.builder.AllocateId(); - auto value = state.builder.AllocateId(); - const auto lane = high_lane ? (operand.op_sel_hi ? 1u : 0u) : (operand.op_sel ? 1u : 0u); + const auto raw = EmitValueLoad(state, operand); + const auto unpacked = state.builder.AllocateId(); + auto value = state.builder.AllocateId(); + const auto selected_lane = high_lane ? operand.op_sel_hi : operand.op_sel; + const auto lane = selected_lane ? 1u : 0u; state.builder.AddFunction( {OpExtInst, state.vec2_float_type, unpacked, state.glsl_std450, GlslUnpackHalf2x16, raw}); state.builder.AddFunction({OpCompositeExtract, state.float_type, value, unpacked, lane}); @@ -2069,10 +2078,11 @@ void EmitCompareF16(EmitterState& state, const IR::Instruction& inst, uint32_t o } uint32_t EmitPackedF16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane) { - const auto raw = EmitValueLoad(state, operand); - const auto lane = high_lane ? (operand.op_sel_hi ? 1u : 0u) : (operand.op_sel ? 1u : 0u); - auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw; - bits = EmitAndConstant(state, bits, 0xffffu); + const auto raw = EmitValueLoad(state, operand); + const auto selected_lane = high_lane ? operand.op_sel_hi : operand.op_sel; + const auto lane = selected_lane ? 1u : 0u; + auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw; + bits = EmitAndConstant(state, bits, 0xffffu); if (operand.absolute) { bits = EmitAndConstant(state, bits, 0x7fffu); } @@ -2403,8 +2413,12 @@ uint32_t EmitPackedInteger16Select(EmitterState& state, uint32_t lhs, uint32_t r bool signed_compare, bool max_value) { const auto cond = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - const auto op = signed_compare ? (max_value ? OpSGreaterThanEqual : OpSLessThan) - : (max_value ? OpUGreaterThanEqual : OpULessThan); + uint32_t op = 0; + if (signed_compare) { + op = max_value ? OpSGreaterThanEqual : OpSLessThan; + } else { + op = max_value ? OpUGreaterThanEqual : OpULessThan; + } state.builder.AddFunction({op, state.bool_type, cond, lhs, rhs}); state.builder.AddFunction({OpSelect, state.uint_type, ret, cond, lhs, rhs}); return ret; @@ -2419,9 +2433,12 @@ uint32_t EmitPackedInteger16Lane(EmitterState& state, const IR::Instruction& ins const auto arithmetic = opcode == IR::Opcode::PackedAshrrevI16; const auto value = EmitU16LaneBits(state, inst.src[1], high_lane, arithmetic); const auto ret = state.builder.AllocateId(); - const auto shift_op = opcode == IR::Opcode::PackedLshlrevB16 ? OpShiftLeftLogical - : arithmetic ? OpShiftRightArithmetic - : OpShiftRightLogical; + uint32_t shift_op = OpShiftRightLogical; + switch (opcode) { + case IR::Opcode::PackedLshlrevB16: shift_op = OpShiftLeftLogical; break; + case IR::Opcode::PackedAshrrevI16: shift_op = OpShiftRightArithmetic; break; + default: break; + } state.builder.AddFunction({shift_op, state.uint_type, ret, value, count}); return ret; } diff --git a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterImageOps.cpp b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterImageOps.cpp index 9e0aa408c..b7bc6f42d 100644 --- a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterImageOps.cpp +++ b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterImageOps.cpp @@ -23,6 +23,23 @@ uint32_t ConstantImageGatherHorizontalOffsets(EmitterState& state) { return value; } +IR::DescriptorBindingKind StorageImageBindingKind(ImageViewKind view, bool uint_image) { + switch (view) { + case ImageViewKind::Dim2D: + return uint_image ? IR::DescriptorBindingKind::StorageUint2D + : IR::DescriptorBindingKind::Storage2D; + case ImageViewKind::Dim2DArray: + return uint_image ? IR::DescriptorBindingKind::StorageUint2DArray + : IR::DescriptorBindingKind::Storage2DArray; + case ImageViewKind::Dim3D: + return uint_image ? IR::DescriptorBindingKind::StorageUint3D + : IR::DescriptorBindingKind::Storage3D; + default: + return uint_image ? IR::DescriptorBindingKind::StorageUint2D + : IR::DescriptorBindingKind::Storage2D; + } +} + uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resource, uint32_t array_index, bool uint_image, ImageViewKind view) { @@ -30,9 +47,8 @@ uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resourc uint_image ? state.ptr_uniform_storage_image_uint : state.ptr_uniform_storage_image; uint32_t variable = uint_image ? state.storage_image_uint_variable : state.storage_image_variable; - uint32_t image_type = uint_image ? state.storage_image_uint_type : state.storage_image_type; - IR::DescriptorBindingKind kind = uint_image ? IR::DescriptorBindingKind::StorageUint2D - : IR::DescriptorBindingKind::Storage2D; + uint32_t image_type = uint_image ? state.storage_image_uint_type : state.storage_image_type; + const auto kind = StorageImageBindingKind(view, uint_image); switch (view) { case ImageViewKind::Dim2D: break; case ImageViewKind::Dim2DArray: @@ -42,8 +58,6 @@ uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resourc : state.storage_image_2d_array_variable; image_type = uint_image ? state.storage_image_uint_2d_array_type : state.storage_image_2d_array_type; - kind = uint_image ? IR::DescriptorBindingKind::StorageUint2DArray - : IR::DescriptorBindingKind::Storage2DArray; break; case ImageViewKind::Dim3D: pointer_type = uint_image ? state.ptr_uniform_storage_image_uint_3d @@ -52,8 +66,6 @@ uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resourc uint_image ? state.storage_image_uint_3d_variable : state.storage_image_3d_variable; image_type = uint_image ? state.storage_image_uint_3d_type : state.storage_image_3d_type; - kind = uint_image ? IR::DescriptorBindingKind::StorageUint3D - : IR::DescriptorBindingKind::Storage3D; break; } const auto pointer = @@ -170,16 +182,8 @@ void EmitImageLoad(EmitterState& state, const IR::Instruction& inst) { void EmitImageStore(EmitterState& state, const IR::Instruction& inst) { const auto uint_image = inst.memory.kind == IR::ResourceKind::StorageImageUint; const auto view = StorageImageViewKind(state, inst.memory, uint_image, inst.pc); - const auto binding = ResourceForDescriptor( - state, - uint_image - ? (view == ImageViewKind::Dim2DArray ? IR::DescriptorBindingKind::StorageUint2DArray - : view == ImageViewKind::Dim3D ? IR::DescriptorBindingKind::StorageUint3D - : IR::DescriptorBindingKind::StorageUint2D) - : (view == ImageViewKind::Dim2DArray ? IR::DescriptorBindingKind::Storage2DArray - : view == ImageViewKind::Dim3D ? IR::DescriptorBindingKind::Storage3D - : IR::DescriptorBindingKind::Storage2D), - inst.memory.resource); + const auto binding = ResourceForDescriptor(state, StorageImageBindingKind(view, uint_image), + inst.memory.resource); const auto image = LoadStorageImageDescriptorAtIndex(state, inst.memory.resource, binding.array_index, uint_image, view); @@ -269,14 +273,17 @@ void EmitImageSample(EmitterState& state, const IR::Instruction& inst) { const auto view = SampledImageViewKind(state, inst.memory, inst.pc); const auto sampled_image = MakeSampledImage(state, inst.memory, inst.pc, view); - const auto layout = MakeImageSampleLayout(inst, view); - const auto base_coord = EmitImageCoordF32(state, inst, layout, view); - const auto sample = state.builder.AllocateId(); - const auto dref = HasImageSampleFlag(inst, Decoder::ImageSampleFlagCompare); - const bool integer = inst.memory.kind == IR::ResourceKind::ImageUint; - const auto result_type = dref ? state.float_type - : integer ? state.vec4_uint_type - : state.vec4_float_type; + const auto layout = MakeImageSampleLayout(inst, view); + const auto base_coord = EmitImageCoordF32(state, inst, layout, view); + const auto sample = state.builder.AllocateId(); + const auto dref = HasImageSampleFlag(inst, Decoder::ImageSampleFlagCompare); + const bool integer = inst.memory.kind == IR::ResourceKind::ImageUint; + uint32_t result_type = state.vec4_float_type; + if (dref) { + result_type = state.float_type; + } else if (integer) { + result_type = state.vec4_uint_type; + } const auto explicit_lod = ImageSampleNeedsExplicitLod(state, inst); const auto opcode = ImageSampleOpcode(state, inst); const auto coord = diff --git a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp index e06172ba8..a299093d4 100644 --- a/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp +++ b/src/graphics/shader/recompiler/spirvEmitter/spirvEmitterValues.cpp @@ -38,14 +38,14 @@ uint32_t EmitSdwaExtractU32(EmitterState& state, const IR::Operand& operand, uin const auto bits = state.builder.AllocateId(); state.builder.AddFunction({OpBitcast, state.int_type, signed_value, value}); state.builder.AddFunction({OpBitFieldSExtract, state.int_type, extracted, signed_value, - ConstantU32(state, offset), ConstantU32(state, width)}); + ConstantU32(state, offset), ConstantU32(state, width)}); state.builder.AddFunction({OpBitcast, state.uint_type, bits, extracted}); return bits; } const auto extracted = state.builder.AllocateId(); state.builder.AddFunction({OpBitFieldUExtract, state.uint_type, extracted, value, - ConstantU32(state, offset), ConstantU32(state, width)}); + ConstantU32(state, offset), ConstantU32(state, width)}); return extracted; } @@ -65,8 +65,7 @@ DppTargetLane EmitDppQuadPermTargetLane(EmitterState& state, uint32_t subid, uin const auto target = state.builder.AllocateId(); state.builder.AddFunction( {OpBitwiseAnd, state.uint_type, quad_base, subid, ConstantU32(state, 0xfffffffcu)}); - state.builder.AddFunction( - {OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 3)}); + state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 3)}); state.builder.AddFunction( {OpShiftLeftLogical, state.uint_type, shift, lane, ConstantU32(state, 1)}); state.builder.AddFunction( @@ -86,8 +85,7 @@ DppTargetLane EmitDppRowShiftTargetLane(EmitterState& state, uint32_t subid, uin const auto valid = state.builder.AllocateId(); state.builder.AddFunction( {OpBitwiseAnd, state.uint_type, row, subid, ConstantU32(state, 0xfffffff0u)}); - state.builder.AddFunction( - {OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)}); + state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)}); if (left) { state.builder.AddFunction( {OpIAdd, state.uint_type, lane_shifted, lane, ConstantU32(state, amount)}); @@ -114,8 +112,7 @@ DppTargetLane EmitDppRowRotateRightTargetLane(EmitterState& state, uint32_t subi const auto target = state.builder.AllocateId(); state.builder.AddFunction( {OpBitwiseAnd, state.uint_type, row, subid, ConstantU32(state, 0xfffffff0u)}); - state.builder.AddFunction( - {OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)}); + state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)}); state.builder.AddFunction( {OpUGreaterThanEqual, state.bool_type, in_high, lane, ConstantU32(state, amount)}); state.builder.AddFunction({OpISub, state.uint_type, minus, lane, ConstantU32(state, amount)}); @@ -174,7 +171,7 @@ uint32_t EmitDppValueU32(EmitterState& state, const IR::Operand& operand, uint32 const auto target = EmitDppTargetLane(state, operand.dpp_ctrl); const auto shuffled = state.builder.AllocateId(); state.builder.AddFunction({OpGroupNonUniformShuffle, state.uint_type, shuffled, - ConstantU32(state, ScopeSubgroup), value, target.lane}); + ConstantU32(state, ScopeSubgroup), value, target.lane}); if (operand.dpp_fetch_inactive) { return shuffled; } @@ -235,8 +232,7 @@ uint32_t EmitLaneMaskPartU32(EmitterState& state, uint32_t part) { const auto subid = EmitSubgroupLocalInvocationId(state); const auto lane = state.builder.AllocateId(); const auto bit = state.builder.AllocateId(); - state.builder.AddFunction( - {OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)}); + state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)}); state.builder.AddFunction( {OpShiftLeftLogical, state.uint_type, bit, ConstantU32(state, 1), lane}); if (part == 0) { @@ -265,8 +261,7 @@ uint32_t EmitThreadMaskBelowPartU32(EmitterState& state, uint32_t part) { const auto lane = state.builder.AllocateId(); const auto bit = state.builder.AllocateId(); const auto below = state.builder.AllocateId(); - state.builder.AddFunction( - {OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)}); + state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)}); state.builder.AddFunction( {OpShiftLeftLogical, state.uint_type, bit, ConstantU32(state, 1), lane}); state.builder.AddFunction({OpISub, state.uint_type, below, bit, ConstantU32(state, 1)}); @@ -462,7 +457,7 @@ uint32_t EmitVertexParameterComponentU32(EmitterState& state, const InputBinding const auto pointer_type = VertexParameterScalarPointerType(state, kind); const auto pointer = state.builder.AllocateId(); state.builder.AddFunction({OpAccessChain, pointer_type, pointer, input.variable_id, - ConstantU32(state, component)}); + ConstantU32(state, component)}); state.builder.AddFunction({OpLoad, scalar_type, raw, pointer}); } @@ -527,10 +522,13 @@ uint32_t EmitFloatLoad(EmitterState& state, const IR::Operand& operand) { uint32_t ApplyResultModifiersF32(EmitterState& state, uint32_t value, const IR::Operand& dst) { uint32_t result = value; if (dst.omod != 0) { - const uint32_t bits = dst.omod == 1u ? 0x40000000u - : dst.omod == 2u ? 0x40800000u - : 0x3f000000u; - const auto scaled = state.builder.AllocateId(); + uint32_t bits = 0x3f000000u; + switch (dst.omod) { + case 1u: bits = 0x40000000u; break; + case 2u: bits = 0x40800000u; break; + default: break; + } + const auto scaled = state.builder.AllocateId(); state.builder.AddFunction( {OpFMul, state.float_type, scaled, result, ConstantF32(state, bits)}); result = scaled; @@ -540,7 +538,7 @@ uint32_t ApplyResultModifiersF32(EmitterState& state, uint32_t value, const IR:: } const auto ret = state.builder.AllocateId(); state.builder.AddFunction({OpExtInst, state.float_type, ret, state.glsl_std450, GlslFClamp, - result, ConstantF32(state, 0), ConstantF32(state, 0x3f800000u)}); + result, ConstantF32(state, 0), ConstantF32(state, 0x3f800000u)}); return ret; } @@ -565,7 +563,7 @@ uint32_t EmitMixF32Load(EmitterState& state, const IR::Operand& operand) { const auto unpacked = state.builder.AllocateId(); auto f32 = state.builder.AllocateId(); state.builder.AddFunction({OpExtInst, state.vec2_float_type, unpacked, state.glsl_std450, - GlslUnpackHalf2x16, bits}); + GlslUnpackHalf2x16, bits}); state.builder.AddFunction( {OpCompositeExtract, state.float_type, f32, unpacked, operand.op_sel ? 1u : 0u}); if (operand.absolute) { @@ -651,7 +649,7 @@ uint32_t EmitLaneIndexActiveBool(EmitterState& state, uint32_t lane) { if (state.per_invocation_masks) { const auto ballot = state.builder.AllocateId(); state.builder.AddFunction({OpGroupNonUniformBallot, state.vec4_uint_type, ballot, - ConstantU32(state, ScopeSubgroup), EmitExecActiveBool(state)}); + ConstantU32(state, ScopeSubgroup), EmitExecActiveBool(state)}); return EmitBallotLaneActiveBool(state, ballot, lane); } const auto lane_low = state.builder.AllocateId(); @@ -682,7 +680,7 @@ uint32_t EmitLaneIndexActiveBool(EmitterState& state, uint32_t lane) { uint32_t EmitSubgroupLaneActiveBool(EmitterState& state, uint32_t lane) { const auto active_ballot = state.builder.AllocateId(); state.builder.AddFunction({OpGroupNonUniformBallot, state.vec4_uint_type, active_ballot, - ConstantU32(state, ScopeSubgroup), EmitTrueBool(state)}); + ConstantU32(state, ScopeSubgroup), EmitTrueBool(state)}); return EmitBallotLaneActiveBool(state, active_ballot, lane); } uint32_t EmitBallotLaneActiveBool(EmitterState& state, uint32_t active_ballot, uint32_t lane) {