[shader_recompiler/Maxwell] ISBERD add size reads

This commit is contained in:
SDK Chan 2025-08-04 20:48:22 +00:00 committed by crueter
parent b906abf9fc
commit 178b4df34d
6 changed files with 486 additions and 432 deletions

View file

@ -240,6 +240,7 @@ add_library(shader_recompiler STATIC
runtime_info.h runtime_info.h
shader_info.h shader_info.h
varying_state.h varying_state.h
frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h
) )
target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit SPIRV-Tools-opt SPIRV-Tools SPIRV-Tools-link) target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit SPIRV-Tools-opt SPIRV-Tools SPIRV-Tools-link)

View file

@ -268,4 +268,40 @@ void TranslatorVisitor::ResetOFlag() {
SetOFlag(ir.Imm1(false)); SetOFlag(ir.Imm1(false));
} }
IR::U32 TranslatorVisitor::apply_ISBERD_shift(IR::U32 result, isberd::Shift shift_value) {
if (shift_value != isberd::Shift::Default) {
return ir.ShiftLeftLogical(result, ir.Imm32(1));
}
return result;
}
IR::U32 TranslatorVisitor::apply_ISBERD_size_read(IR::U32 address, isberd::SZ sz) {
switch (sz) {
case isberd::SZ::U8:
return ir.LoadGlobalU8(ir.UConvert(64, address));
case isberd::SZ::U16:
return ir.LoadGlobalU16(ir.UConvert(64, address));
case isberd::SZ::U32:
case isberd::SZ::F32:
return ir.LoadGlobal32(ir.UConvert(64, address));
default:
UNREACHABLE();
}
}
IR::U32 TranslatorVisitor::compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value) {
IR::U32 address{};
if (src_reg_num == 0xFF) {
address = ir.Imm32(imm);
} else {
auto offset = ir.Imm32(imm);
address = ir.IAdd(X(src_reg), offset);
if (skew_value != 0) {
address = ir.IAdd(address, ir.LaneId());
}
}
return address;
};
} // namespace Shader::Maxwell } // namespace Shader::Maxwell

View file

@ -7,6 +7,7 @@
#include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/ir_emitter.h" #include "shader_recompiler/frontend/ir/ir_emitter.h"
#include "shader_recompiler/frontend/maxwell/instruction.h" #include "shader_recompiler/frontend/maxwell/instruction.h"
#include "shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h"
namespace Shader::Maxwell { namespace Shader::Maxwell {
@ -381,6 +382,11 @@ public:
void ResetSFlag(); void ResetSFlag();
void ResetCFlag(); void ResetCFlag();
void ResetOFlag(); void ResetOFlag();
// Helper functions for various translator visitors
IR::U32 apply_ISBERD_shift(IR::U32 result, isberd::Shift shift_value);
IR::U32 apply_ISBERD_size_read(IR::U32 address, isberd::SZ sz_value);
IR::U32 compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value);
}; };
} // namespace Shader::Maxwell } // namespace Shader::Maxwell

View file

@ -7,23 +7,9 @@
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
#include "shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h"
namespace Shader::Maxwell { namespace Shader::Maxwell {
namespace {
enum class Mode : u64 {
Default,
Patch,
Prim,
Attr,
};
enum class Shift : u64 {
Default,
U16,
B32,
};
} // Anonymous namespace
// Valid only for GS, TI, VS and trap // Valid only for GS, TI, VS and trap
void TranslatorVisitor::ISBERD(u64 insn) { void TranslatorVisitor::ISBERD(u64 insn) {
@ -35,70 +21,49 @@ void TranslatorVisitor::ISBERD(u64 insn) {
BitField<24, 8, u32> imm; BitField<24, 8, u32> imm;
BitField<31, 1, u64> skew; BitField<31, 1, u64> skew;
BitField<32, 1, u64> o; BitField<32, 1, u64> o;
BitField<33, 2, Mode> mode; BitField<33, 2, isberd::Mode> mode;
BitField<47, 2, Shift> shift; BitField<36, 4, isberd::SZ> sz;
BitField<47, 2, isberd::Shift> shift;
} const isberd{insn}; } const isberd{insn};
if (isberd.skew != 0) { auto address = compute_ISBERD_address(isberd.src_reg, isberd.src_reg_num, isberd.imm, isberd.skew);
IR::U32 current_lane_id{ir.LaneId()};
IR::U32 result{ir.IAdd(X(isberd.src_reg), current_lane_id)};
X(isberd.dest_reg, result);
}
if (isberd.o != 0) { if (isberd.o != 0) {
IR::U32 address{}; auto result = apply_ISBERD_size_read(address, isberd.sz.Value());
IR::F32 result{}; X(isberd.dest_reg, apply_ISBERD_shift(result, isberd.shift.Value()));
if (isberd.src_reg_num == 0xFF) {
address = ir.Imm32(isberd.imm); return;
result = ir.GetAttributeIndexed(address);
} else {
IR::U32 offset = ir.Imm32(isberd.imm);
address = ir.IAdd(X(isberd.src_reg), offset);
result = ir.GetAttributeIndexed(address);
}
X(isberd.dest_reg, ir.BitCast<IR::U32>(result));
}
if (isberd.mode != Mode::Default) {
IR::F32 result{};
IR::U32 index{};
if (isberd.src_reg_num == 0xFF) {
index = ir.Imm32(isberd.imm);
} else {
index = ir.IAdd(X(isberd.src_reg), ir.Imm32(isberd.imm));
} }
switch (static_cast<u64>(isberd.mode.Value())) { if (isberd.mode != isberd::Mode::Default) {
case static_cast<u64>(Mode::Patch): IR::F32 result_f32{};
result = ir.GetPatch(index.Patch()); switch (isberd.mode.Value()) {
case isberd::Mode::Patch:
result_f32 = ir.GetPatch(address.Patch());
break; break;
case static_cast<u64>(Mode::Prim): case isberd::Mode::Prim:
result = ir.GetAttribute(index.Attribute()); result_f32 = ir.GetAttribute(address.Attribute());
break; break;
case static_cast<u64>(Mode::Attr): case isberd::Mode::Attr:
result = ir.GetAttributeIndexed(index); result_f32 = ir.GetAttributeIndexed(address);
break; break;
default:
UNREACHABLE();
} }
X(isberd.dest_reg, ir.BitCast<IR::U32>(result));
} auto result_u32 = ir.BitCast<IR::U32>(result_f32);
if (isberd.shift != Shift::Default) { X(isberd.dest_reg, apply_ISBERD_shift(result_u32, isberd.shift.Value()));
IR::U32 result{}; return;
switch (static_cast<u64>(isberd.shift.Value())) {
case static_cast<u64>(Shift::U16):
result = ir.ShiftLeftLogical(result, static_cast<IR::U32>(ir.Imm16(1)));
break;
case static_cast<u64>(Shift::B32):
result = ir.ShiftLeftLogical(result, ir.Imm32(1));
break;
} }
if (isberd.skew != 0) {
auto result = ir.IAdd(X(isberd.src_reg), ir.LaneId());
X(isberd.dest_reg, result); X(isberd.dest_reg, result);
return;
} }
//LOG_DEBUG(Shader, "(STUBBED) called {}", insn);
if (isberd.src_reg_num == 0xFF) { // Fallback if nothing else applies
IR::U32 src_imm{ir.Imm32(static_cast<u32>(isberd.imm))};
IR::U32 result{ir.IAdd(X(isberd.src_reg), src_imm)};
X(isberd.dest_reg, result);
} else {
X(isberd.dest_reg, X(isberd.src_reg)); X(isberd.dest_reg, X(isberd.src_reg));
} }
}
} // namespace Shader::Maxwell } // namespace Shader::Maxwell

View file

@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "shader_recompiler/environment.h"
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/ir_emitter.h"
#include "shader_recompiler/frontend/maxwell/instruction.h"
namespace Shader::Maxwell {
namespace isberd {
enum class Mode : u64 {
Default,
Patch,
Prim,
Attr,
};
enum class Shift : u64 {
Default,
U16,
B32,
};
enum class SZ : u64 {
U8,
U16,
U32,
F32,
};
} // Anonymous namespace
} // namespace Shader::Maxwell

View file

@ -1,5 +1,5 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-FileCopyrightText: 2018 yuzu Emulator Project SPDX-License-Identifier:
# SPDX-License-Identifier: GPL-2.0-or-later # GPL-2.0-or-later
add_subdirectory(host_shaders) add_subdirectory(host_shaders)
@ -9,7 +9,8 @@ if(LIBVA_FOUND)
list(APPEND FFmpeg_LIBRARIES ${LIBVA_LIBRARIES}) list(APPEND FFmpeg_LIBRARIES ${LIBVA_LIBRARIES})
endif() endif()
add_library(video_core STATIC add_library(
video_core STATIC
buffer_cache/buffer_base.h buffer_cache/buffer_base.h
buffer_cache/buffer_cache_base.h buffer_cache/buffer_cache_base.h
buffer_cache/buffer_cache.cpp buffer_cache/buffer_cache.cpp
@ -312,8 +313,7 @@ add_library(video_core STATIC
vulkan_common/nsight_aftermath_tracker.h vulkan_common/nsight_aftermath_tracker.h
vulkan_common/vma.cpp vulkan_common/vma.cpp
vulkan_common/vma.h vulkan_common/vma.h
vulkan_common/vulkan.h vulkan_common/vulkan.h)
)
target_link_libraries(video_core PUBLIC common core) target_link_libraries(video_core PUBLIC common core)
target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder) target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder)
@ -333,38 +333,52 @@ target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHe
if(ENABLE_NSIGHT_AFTERMATH) if(ENABLE_NSIGHT_AFTERMATH)
if(NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) if(NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
message(FATAL_ERROR "Environment variable NSIGHT_AFTERMATH_SDK has to be provided") message(
FATAL_ERROR "Environment variable NSIGHT_AFTERMATH_SDK has to be provided"
)
endif() endif()
if(NOT WIN32) if(NOT WIN32)
message(FATAL_ERROR "Nsight Aftermath doesn't support non-Windows platforms") message(
FATAL_ERROR "Nsight Aftermath doesn't support non-Windows platforms")
endif() endif()
target_compile_definitions(video_core PRIVATE HAS_NSIGHT_AFTERMATH) target_compile_definitions(video_core PRIVATE HAS_NSIGHT_AFTERMATH)
target_include_directories(video_core PRIVATE "$ENV{NSIGHT_AFTERMATH_SDK}/include") target_include_directories(video_core
PRIVATE "$ENV{NSIGHT_AFTERMATH_SDK}/include")
endif() endif()
if(MSVC) if(MSVC)
target_compile_options(video_core PRIVATE target_compile_options(
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data video_core
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data PRIVATE /we4242 # 'identifier': conversion from 'type1' to 'type2', possible
# loss of data
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible
# loss of data
) )
else() else()
if(APPLE) if(APPLE)
# error: declaration shadows a typedef in 'interval_base_set<SubType, DomainT, Compare, Interval, Alloc>' # error: declaration shadows a typedef in 'interval_base_set<SubType,
# error: implicit conversion loses integer precision: 'int' to 'boost::icl::bound_type' (aka 'unsigned char') # DomainT, Compare, Interval, Alloc>' error: implicit conversion loses
target_compile_options(video_core PRIVATE -Wno-shadow -Wno-unused-local-typedef) # integer precision: 'int' to 'boost::icl::bound_type' (aka 'unsigned char')
target_compile_options(video_core PRIVATE -Wno-shadow
-Wno-unused-local-typedef)
else() else()
target_compile_options(video_core PRIVATE -Werror=conversion) target_compile_options(video_core PRIVATE -Werror=conversion)
endif() endif()
target_compile_options(video_core PRIVATE target_compile_options(video_core PRIVATE -Wno-sign-conversion)
-Wno-sign-conversion
)
# xbyak # xbyak
set_source_files_properties(macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-shadow") set_source_files_properties(
macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS
"-Wno-conversion;-Wno-shadow")
# VMA # VMA
set_source_files_properties(vulkan_common/vma.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-unused-variable;-Wno-unused-parameter;-Wno-missing-field-initializers") set_source_files_properties(
vulkan_common/vma.cpp
PROPERTIES
COMPILE_OPTIONS
"-Wno-conversion;-Wno-unused-variable;-Wno-unused-parameter;-Wno-missing-field-initializers"
)
# Get around GCC failing with intrinsics in Debug # Get around GCC failing with intrinsics in Debug
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_BUILD_TYPE MATCHES "Debug") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_BUILD_TYPE MATCHES "Debug")
@ -373,10 +387,8 @@ else()
endif() endif()
if(ARCHITECTURE_x86_64) if(ARCHITECTURE_x86_64)
target_sources(video_core PRIVATE target_sources(video_core PRIVATE macro/macro_jit_x64.cpp
macro/macro_jit_x64.cpp macro/macro_jit_x64.h)
macro/macro_jit_x64.h
)
target_link_libraries(video_core PUBLIC xbyak::xbyak) target_link_libraries(video_core PUBLIC xbyak::xbyak)
if(NOT MSVC) if(NOT MSVC)