mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-04-08 18:31:29 -06:00
Merge branch 'master' into master
This commit is contained in:
commit
162d41f204
1
externals/CMakeLists.txt
vendored
1
externals/CMakeLists.txt
vendored
@ -60,6 +60,7 @@ if (ENABLE_TESTS)
|
||||
add_subdirectory(catch2)
|
||||
endif()
|
||||
target_link_libraries(catch2 INTERFACE Catch2::Catch2WithMain)
|
||||
include(Catch)
|
||||
endif()
|
||||
|
||||
# Crypto++
|
||||
|
||||
@ -504,8 +504,9 @@ object NativeLibrary {
|
||||
const val ErrorSystemFiles = 8
|
||||
const val ErrorSavestate = 9
|
||||
const val ErrorArticDisconnected = 10
|
||||
const val ShutdownRequested = 11
|
||||
const val ErrorUnknown = 12
|
||||
const val ErrorN3DSApplication = 11
|
||||
const val ShutdownRequested = 12
|
||||
const val ErrorUnknown = 13
|
||||
|
||||
fun newInstance(resultCode: Int): EmulationErrorDialogFragment {
|
||||
val args = Bundle()
|
||||
|
||||
@ -17,7 +17,7 @@ enum class IntSetting(
|
||||
CAMERA_INNER_FLIP(SettingKeys.camera_inner_flip(), Settings.SECTION_CAMERA, 0),
|
||||
CAMERA_OUTER_LEFT_FLIP(SettingKeys.camera_outer_left_flip(), Settings.SECTION_CAMERA, 0),
|
||||
CAMERA_OUTER_RIGHT_FLIP(SettingKeys.camera_outer_right_flip(), Settings.SECTION_CAMERA, 0),
|
||||
GRAPHICS_API(SettingKeys.graphics_api(), Settings.SECTION_RENDERER, 1),
|
||||
GRAPHICS_API(SettingKeys.graphics_api(), Settings.SECTION_RENDERER, 2),
|
||||
RESOLUTION_FACTOR(SettingKeys.resolution_factor(), Settings.SECTION_RENDERER, 1),
|
||||
STEREOSCOPIC_3D_MODE(SettingKeys.render_3d(), Settings.SECTION_RENDERER, 2),
|
||||
STEREOSCOPIC_3D_DEPTH(SettingKeys.factor_3d(), Settings.SECTION_RENDERER, 0),
|
||||
|
||||
@ -90,7 +90,7 @@ static const char* android_config_default_file_content = (BOOST_HANA_STRING(R"(
|
||||
|
||||
[Renderer]
|
||||
# Whether to render using OpenGL
|
||||
# 1: OpenGL ES (default), 2: Vulkan
|
||||
# 1: OpenGL ES, 2: Vulkan (default)
|
||||
)") DECLARE_KEY(graphics_api) BOOST_HANA_STRING(R"(
|
||||
|
||||
# Whether to compile shaders on multiple worker threads (Vulkan only)
|
||||
|
||||
@ -5,13 +5,13 @@
|
||||
android:id="@+id/coordinator_about"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:background="?attr/colorSurface">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_about"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_system_files"
|
||||
|
||||
@ -61,7 +61,14 @@ bool GetMicrophoneInterface(struct retro_microphone_interface* mic_interface) {
|
||||
}
|
||||
|
||||
Settings::GraphicsAPI GetPreferredRenderer() {
|
||||
// try and maintain the current driver
|
||||
// On Android, we really want to default to Vulkan if we can, so we'll ignore the frontend's
|
||||
// recommendation if possible...
|
||||
#if defined(ANDROID) && defined(ENABLE_VULKAN)
|
||||
return Settings::GraphicsAPI::Vulkan;
|
||||
#endif
|
||||
// ...Otherwise negotiate with the RetroArch frontend as usual
|
||||
|
||||
// Attempt to use the renderer recommended by the frontend if possible
|
||||
retro_hw_context_type context_type = RETRO_HW_CONTEXT_OPENGL;
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &context_type);
|
||||
switch (context_type) {
|
||||
@ -80,7 +87,7 @@ Settings::GraphicsAPI GetPreferredRenderer() {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// we can't maintain the current driver, need to switch
|
||||
// We can't get a recommendation from the frontend, so fall back to whatever's available
|
||||
#if defined(ENABLE_VULKAN)
|
||||
return Settings::GraphicsAPI::Vulkan;
|
||||
#elif defined(ENABLE_OPENGL)
|
||||
|
||||
@ -498,8 +498,11 @@ struct Values {
|
||||
Setting<bool> apply_region_free_patch{true, Keys::apply_region_free_patch};
|
||||
|
||||
// Renderer
|
||||
// clang-format off
|
||||
SwitchableSetting<GraphicsAPI, true> graphics_api{
|
||||
#if defined(ENABLE_OPENGL)
|
||||
#if defined(ANDROID) && defined(ENABLE_VULKAN) // Prefer Vulkan on Android, OpenGL on everything else
|
||||
GraphicsAPI::Vulkan,
|
||||
#elif defined(ENABLE_OPENGL)
|
||||
GraphicsAPI::OpenGL,
|
||||
#elif defined(ENABLE_VULKAN)
|
||||
GraphicsAPI::Vulkan,
|
||||
@ -510,6 +513,7 @@ struct Values {
|
||||
#error "At least one renderer must be enabled."
|
||||
#endif
|
||||
GraphicsAPI::Software, GraphicsAPI::Vulkan, Keys::graphics_api};
|
||||
// clang-format on
|
||||
SwitchableSetting<u32> physical_device{0, Keys::physical_device};
|
||||
Setting<bool> use_gles{false, Keys::use_gles};
|
||||
Setting<bool> renderer_debug{false, Keys::renderer_debug};
|
||||
|
||||
@ -36,6 +36,10 @@ if (ENABLE_LIBRETRO)
|
||||
endif()
|
||||
|
||||
add_test(NAME tests COMMAND tests)
|
||||
if(NOT ANDROID)
|
||||
catch_discover_tests(tests)
|
||||
endif()
|
||||
|
||||
|
||||
if (CITRA_USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers(tests PRIVATE precompiled_headers.h)
|
||||
|
||||
@ -481,6 +481,39 @@ SHADER_TEST_CASE("RSQ", "[video_core][shader]") {
|
||||
REQUIRE(shader.Run({0.0625f}).x == Catch::Approx(4.0f).margin(0.004f));
|
||||
}
|
||||
|
||||
SHADER_TEST_CASE("SETEMIT", "[video_core][shader]") {
|
||||
Pica::GeometryEmitter geometry_emitter;
|
||||
|
||||
for (u8 winding = 0; winding <= 1; ++winding) {
|
||||
for (u8 prim_emit = 0; prim_emit <= 1; ++prim_emit) {
|
||||
for (u8 vertex_id = 0; vertex_id <= 3; ++vertex_id) {
|
||||
auto shader_setup = CompileShaderSetup({
|
||||
{OpCode::Id::NOP}, // setemit
|
||||
{OpCode::Id::END},
|
||||
});
|
||||
|
||||
// nihstro does not support the SETEMIT instructions, so the instruction-binary must
|
||||
// be manually
|
||||
// inserted here:
|
||||
nihstro::Instruction SETEMIT = {};
|
||||
SETEMIT.opcode = nihstro::OpCode(nihstro::OpCode::Id::SETEMIT);
|
||||
SETEMIT.setemit.winding.Assign(winding);
|
||||
SETEMIT.setemit.prim_emit.Assign(prim_emit);
|
||||
SETEMIT.setemit.vertex_id.Assign(vertex_id);
|
||||
shader_setup->UpdateProgramCode(0, SETEMIT.hex);
|
||||
|
||||
auto shader = TestType(std::move(shader_setup));
|
||||
Pica::ShaderUnit shader_unit(&geometry_emitter);
|
||||
shader.Run(shader_unit, 1.0f);
|
||||
|
||||
REQUIRE(geometry_emitter.emit_state.winding == winding);
|
||||
REQUIRE(geometry_emitter.emit_state.prim_emit == prim_emit);
|
||||
REQUIRE(geometry_emitter.emit_state.vertex_id == vertex_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHADER_TEST_CASE("Uniform Read", "[video_core][shader]") {
|
||||
const auto sh_input = SourceRegister::MakeInput(0);
|
||||
const auto sh_c0 = SourceRegister::MakeFloat(0);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -29,15 +29,15 @@ void ShaderUnit::WriteOutput(const ShaderRegs& config, AttributeBuffer& buffer)
|
||||
}
|
||||
|
||||
void GeometryEmitter::Emit(std::span<Common::Vec4<f24>, 16> output_regs) {
|
||||
ASSERT(vertex_id < 3);
|
||||
ASSERT(emit_state.vertex_id < 3);
|
||||
|
||||
u32 output_index{};
|
||||
for (u32 reg : Common::BitSet<u32>(output_mask)) {
|
||||
buffer[vertex_id][output_index++] = output_regs[reg];
|
||||
buffer[emit_state.vertex_id][output_index++] = output_regs[reg];
|
||||
}
|
||||
|
||||
if (prim_emit) {
|
||||
if (winding) {
|
||||
if (emit_state.prim_emit) {
|
||||
if (emit_state.winding) {
|
||||
handlers->winding_setter();
|
||||
}
|
||||
for (std::size_t i = 0; i < buffer.size(); ++i) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -75,11 +75,18 @@ struct GeometryEmitter {
|
||||
void Emit(std::span<Common::Vec4<f24>, 16> output_regs);
|
||||
|
||||
public:
|
||||
std::array<AttributeBuffer, 3> buffer;
|
||||
u8 vertex_id;
|
||||
bool prim_emit;
|
||||
bool winding;
|
||||
union EmitState {
|
||||
struct {
|
||||
bool winding : 1;
|
||||
bool prim_emit : 1;
|
||||
u8 vertex_id : 2;
|
||||
};
|
||||
u8 raw;
|
||||
} emit_state;
|
||||
static_assert(sizeof(emit_state) == 1);
|
||||
|
||||
u32 output_mask;
|
||||
std::array<AttributeBuffer, 3> buffer;
|
||||
Handlers* handlers;
|
||||
|
||||
private:
|
||||
@ -87,9 +94,7 @@ private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const u32 file_version) {
|
||||
ar & buffer;
|
||||
ar & vertex_id;
|
||||
ar & prim_emit;
|
||||
ar & winding;
|
||||
ar & emit_state.raw;
|
||||
ar & output_mask;
|
||||
}
|
||||
};
|
||||
|
||||
@ -671,9 +671,9 @@ static void RunInterpreter(const ShaderSetup& setup, ShaderUnit& state,
|
||||
case OpCode::Id::SETEMIT: {
|
||||
auto* emitter = state.emitter_ptr;
|
||||
ASSERT_MSG(emitter, "Execute SETEMIT on VS");
|
||||
emitter->vertex_id = instr.setemit.vertex_id;
|
||||
emitter->prim_emit = instr.setemit.prim_emit != 0;
|
||||
emitter->winding = instr.setemit.winding != 0;
|
||||
emitter->emit_state.vertex_id = instr.setemit.vertex_id;
|
||||
emitter->emit_state.prim_emit = instr.setemit.prim_emit != 0;
|
||||
emitter->emit_state.winding = instr.setemit.winding != 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -865,12 +865,13 @@ void JitShader::Compile_SETE(Instruction instr) {
|
||||
|
||||
l(have_emitter);
|
||||
|
||||
MOV(XSCRATCH1.toW(), instr.setemit.vertex_id);
|
||||
STRB(XSCRATCH1.toW(), XSCRATCH0, u32(offsetof(GeometryEmitter, vertex_id)));
|
||||
MOV(XSCRATCH1.toW(), instr.setemit.prim_emit);
|
||||
STRB(XSCRATCH1.toW(), XSCRATCH0, u32(offsetof(GeometryEmitter, prim_emit)));
|
||||
MOV(XSCRATCH1.toW(), instr.setemit.winding);
|
||||
STRB(XSCRATCH1.toW(), XSCRATCH0, u32(offsetof(GeometryEmitter, winding)));
|
||||
const GeometryEmitter::EmitState new_state{
|
||||
.winding = instr.setemit.winding != 0,
|
||||
.prim_emit = instr.setemit.prim_emit != 0,
|
||||
.vertex_id = static_cast<uint8_t>(instr.setemit.vertex_id),
|
||||
};
|
||||
MOV(XSCRATCH1.toW(), new_state.raw);
|
||||
STRB(XSCRATCH1.toW(), XSCRATCH0, u32(offsetof(GeometryEmitter, emit_state)));
|
||||
|
||||
l(end);
|
||||
}
|
||||
|
||||
@ -905,9 +905,12 @@ void JitShader::Compile_SETE(Instruction instr) {
|
||||
jmp(end);
|
||||
|
||||
L(have_emitter);
|
||||
mov(byte[rax + offsetof(GeometryEmitter, vertex_id)], instr.setemit.vertex_id);
|
||||
mov(byte[rax + offsetof(GeometryEmitter, prim_emit)], instr.setemit.prim_emit);
|
||||
mov(byte[rax + offsetof(GeometryEmitter, winding)], instr.setemit.winding);
|
||||
const GeometryEmitter::EmitState new_state{
|
||||
.winding = instr.setemit.winding != 0,
|
||||
.prim_emit = instr.setemit.prim_emit != 0,
|
||||
.vertex_id = static_cast<uint8_t>(instr.setemit.vertex_id),
|
||||
};
|
||||
mov(byte[rax + offsetof(GeometryEmitter, emit_state)], new_state.raw);
|
||||
L(end);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user