diff options
Diffstat (limited to 'src')
33 files changed, 253 insertions, 166 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6b6efbc00..b7d52babc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -146,10 +146,8 @@ add_library(core STATIC hle/service/filesystem/fsp_srv.h hle/service/friend/friend.cpp hle/service/friend/friend.h - hle/service/friend/friend_a.cpp - hle/service/friend/friend_a.h - hle/service/friend/friend_u.cpp - hle/service/friend/friend_u.h + hle/service/friend/interface.cpp + hle/service/friend/interface.h hle/service/hid/hid.cpp hle/service/hid/hid.h hle/service/lm/lm.cpp diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index d23adb28a..57b8634b9 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -102,8 +102,8 @@ public: u64 tpidr_el0 = 0; }; -std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() { - const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data(); +std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { + auto** const page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data(); Dynarmic::A64::UserConfig config; diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 350f61fd2..14c072601 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -50,7 +50,7 @@ public: void PageTableChanged() override; private: - std::unique_ptr<Dynarmic::A64::Jit> MakeJit(); + std::unique_ptr<Dynarmic::A64::Jit> MakeJit() const; friend class ARM_Dynarmic_Callbacks; std::unique_ptr<ARM_Dynarmic_Callbacks> cb; diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp index 8d2bd9f6b..521e21078 100644 --- a/src/core/file_sys/partition_filesystem.cpp +++ b/src/core/file_sys/partition_filesystem.cpp @@ -65,8 +65,8 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) { std::string name( reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset])); - pfs_files.emplace_back( - std::make_shared<OffsetVfsFile>(file, entry.size, content_offset + entry.offset, name)); + pfs_files.emplace_back(std::make_shared<OffsetVfsFile>( + file, entry.size, content_offset + entry.offset, std::move(name))); } status = Loader::ResultStatus::Success; @@ -109,7 +109,7 @@ bool PartitionFilesystem::ReplaceFileWithSubdirectory(VirtualFile file, VirtualD return false; const std::ptrdiff_t offset = std::distance(pfs_files.begin(), iter); - pfs_files[offset] = pfs_files.back(); + pfs_files[offset] = std::move(pfs_files.back()); pfs_files.pop_back(); pfs_dirs.emplace_back(std::move(dir)); diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 8b5b06f31..7fb0da408 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -25,9 +25,9 @@ protected: ptrdiff_t index = 0; public: - RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} + explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} - RequestHelperBase(Kernel::HLERequestContext& context) + explicit RequestHelperBase(Kernel::HLERequestContext& context) : context(&context), cmdbuf(context.CommandBuffer()) {} void Skip(unsigned size_in_words, bool set_to_null) { @@ -56,13 +56,6 @@ public: class ResponseBuilder : public RequestHelperBase { public: - ResponseBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {} - - u32 normal_params_size{}; - u32 num_handles_to_copy{}; - u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent - std::ptrdiff_t datapayload_index{}; - /// Flags used for customizing the behavior of ResponseBuilder enum class Flags : u32 { None = 0, @@ -71,9 +64,11 @@ public: AlwaysMoveHandles = 1, }; - ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size, - u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, - Flags flags = Flags::None) + explicit ResponseBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {} + + explicit ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size, + u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, + Flags flags = Flags::None) : RequestHelperBase(context), normal_params_size(normal_params_size), num_handles_to_copy(num_handles_to_copy), num_objects_to_move(num_objects_to_move) { @@ -206,6 +201,12 @@ public: template <typename... O> void PushCopyObjects(Kernel::SharedPtr<O>... pointers); + +private: + u32 normal_params_size{}; + u32 num_handles_to_copy{}; + u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent + std::ptrdiff_t datapayload_index{}; }; /// Push /// @@ -273,9 +274,9 @@ inline void ResponseBuilder::PushMoveObjects(Kernel::SharedPtr<O>... pointers) { class RequestParser : public RequestHelperBase { public: - RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} + explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} - RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { + explicit RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { ASSERT_MSG(context.GetDataPayloadOffset(), "context is incomplete"); Skip(context.GetDataPayloadOffset(), false); // Skip the u64 command id, it's already stored in the context @@ -285,8 +286,9 @@ public: ResponseBuilder MakeBuilder(u32 normal_params_size, u32 num_handles_to_copy, u32 num_handles_to_move, - ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) { - return {*context, normal_params_size, num_handles_to_copy, num_handles_to_move, flags}; + ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) const { + return ResponseBuilder{*context, normal_params_size, num_handles_to_copy, + num_handles_to_move, flags}; } template <typename T> @@ -298,6 +300,14 @@ public: template <typename First, typename... Other> void Pop(First& first_value, Other&... other_values); + template <typename T> + T PopEnum() { + static_assert(std::is_enum_v<T>, "T must be an enum type within a PopEnum call."); + static_assert(!std::is_convertible_v<T, int>, + "enum type in PopEnum must be a strongly typed enum."); + return static_cast<T>(Pop<std::underlying_type_t<T>>()); + } + /** * @brief Reads the next normal parameters as a struct, by copying it * @note: The output class must be correctly packed/padded to fit hardware layout. diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 01b805df8..84727f748 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -91,7 +91,7 @@ protected: */ class HLERequestContext { public: - HLERequestContext(SharedPtr<Kernel::ServerSession> session); + explicit HLERequestContext(SharedPtr<ServerSession> session); ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 3f1de3258..feb7b88d2 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -19,7 +19,7 @@ namespace Kernel { /// Returns the number of threads that are waiting for a mutex, and the highest priority one among /// those. static std::pair<SharedPtr<Thread>, u32> GetHighestPriorityMutexWaitingThread( - SharedPtr<Thread> current_thread, VAddr mutex_addr) { + const SharedPtr<Thread>& current_thread, VAddr mutex_addr) { SharedPtr<Thread> highest_priority_thread; u32 num_waiters = 0; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 7b41c9cfd..da7cacb57 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -165,11 +165,14 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 using ObjectPtr = SharedPtr<WaitObject>; std::vector<ObjectPtr> objects(handle_count); - for (int i = 0; i < handle_count; ++i) { - Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); - auto object = g_handle_table.Get<WaitObject>(handle); - if (object == nullptr) + for (u64 i = 0; i < handle_count; ++i) { + const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); + const auto object = g_handle_table.Get<WaitObject>(handle); + + if (object == nullptr) { return ERR_INVALID_HANDLE; + } + objects[i] = object; } diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 3e1c2c0a0..0b158e015 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -35,7 +35,7 @@ static constexpr u128 DEFAULT_USER_ID{1ull, 0ull}; class IProfile final : public ServiceFramework<IProfile> { public: - IProfile(u128 user_id) : ServiceFramework("IProfile"), user_id(user_id) { + explicit IProfile(u128 user_id) : ServiceFramework("IProfile"), user_id(user_id) { static const FunctionInfo functions[] = { {0, nullptr, "Get"}, {1, &IProfile::GetBase, "GetBase"}, diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h index 85258a666..fa68c7d93 100644 --- a/src/core/hle/service/apm/interface.h +++ b/src/core/hle/service/apm/interface.h @@ -19,7 +19,4 @@ private: std::shared_ptr<Module> apm; }; -/// Registers all AM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); - } // namespace Service::APM diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index c98a46e05..fb4d89068 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -5,8 +5,7 @@ #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/friend/friend.h" -#include "core/hle/service/friend/friend_a.h" -#include "core/hle/service/friend/friend_u.h" +#include "core/hle/service/friend/interface.h" namespace Service::Friend { @@ -21,8 +20,11 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) void InstallInterfaces(SM::ServiceManager& service_manager) { auto module = std::make_shared<Module>(); - std::make_shared<Friend_A>(module)->InstallAsService(service_manager); - std::make_shared<Friend_U>(module)->InstallAsService(service_manager); + std::make_shared<Friend>(module, "friend:a")->InstallAsService(service_manager); + std::make_shared<Friend>(module, "friend:m")->InstallAsService(service_manager); + std::make_shared<Friend>(module, "friend:s")->InstallAsService(service_manager); + std::make_shared<Friend>(module, "friend:u")->InstallAsService(service_manager); + std::make_shared<Friend>(module, "friend:v")->InstallAsService(service_manager); } } // namespace Service::Friend diff --git a/src/core/hle/service/friend/friend_u.cpp b/src/core/hle/service/friend/friend_u.cpp deleted file mode 100644 index 90b30883f..000000000 --- a/src/core/hle/service/friend/friend_u.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/friend/friend_u.h" - -namespace Service::Friend { - -Friend_U::Friend_U(std::shared_ptr<Module> module) - : Module::Interface(std::move(module), "friend:u") { - static const FunctionInfo functions[] = { - {0, &Friend_U::CreateFriendService, "CreateFriendService"}, - {1, nullptr, "CreateNotificationService"}, - }; - RegisterHandlers(functions); -} - -} // namespace Service::Friend diff --git a/src/core/hle/service/friend/friend_u.h b/src/core/hle/service/friend/friend_u.h deleted file mode 100644 index 0d953d807..000000000 --- a/src/core/hle/service/friend/friend_u.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/friend/friend.h" - -namespace Service::Friend { - -class Friend_U final : public Module::Interface { -public: - explicit Friend_U(std::shared_ptr<Module> module); -}; - -} // namespace Service::Friend diff --git a/src/core/hle/service/friend/friend_a.cpp b/src/core/hle/service/friend/interface.cpp index a2cc81926..27c6a09e2 100644 --- a/src/core/hle/service/friend/friend_a.cpp +++ b/src/core/hle/service/friend/interface.cpp @@ -2,15 +2,16 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/friend/friend_a.h" +#include "core/hle/service/friend/interface.h" namespace Service::Friend { -Friend_A::Friend_A(std::shared_ptr<Module> module) - : Module::Interface(std::move(module), "friend:a") { +Friend::Friend(std::shared_ptr<Module> module, const char* name) + : Interface(std::move(module), name) { static const FunctionInfo functions[] = { - {0, &Friend_A::CreateFriendService, "CreateFriendService"}, + {0, &Friend::CreateFriendService, "CreateFriendService"}, {1, nullptr, "CreateNotificationService"}, + {2, nullptr, "CreateDaemonSuspendSessionService"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/friend/friend_a.h b/src/core/hle/service/friend/interface.h index 81257583b..89dae8471 100644 --- a/src/core/hle/service/friend/friend_a.h +++ b/src/core/hle/service/friend/interface.h @@ -8,9 +8,9 @@ namespace Service::Friend { -class Friend_A final : public Module::Interface { +class Friend final : public Module::Interface { public: - explicit Friend_A(std::shared_ptr<Module> module); + explicit Friend(std::shared_ptr<Module> module, const char* name); }; } // namespace Service::Friend diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index fee841d46..180f22703 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -146,7 +146,7 @@ protected: * @param max_sessions Maximum number of sessions that can be * connected to this service at the same time. */ - ServiceFramework(const char* service_name, u32 max_sessions = DefaultMaxSessions) + explicit ServiceFramework(const char* service_name, u32 max_sessions = DefaultMaxSessions) : ServiceFrameworkBase(service_name, max_sessions, Invoker) {} /// Registers handlers in the service. diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index fa85277fe..41efca31c 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -10,13 +10,22 @@ namespace Service::Set { void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); + rb.PushEnum(color_set); - LOG_WARNING(Service_SET, "(STUBBED) called"); + LOG_DEBUG(Service_SET, "called"); +} + +void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + color_set = rp.PopEnum<ColorSet>(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_DEBUG(Service_SET, "called"); } SET_SYS::SET_SYS() : ServiceFramework("set:sys") { @@ -44,7 +53,7 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") { {21, nullptr, "GetEulaVersions"}, {22, nullptr, "SetEulaVersions"}, {23, &SET_SYS::GetColorSetId, "GetColorSetId"}, - {24, nullptr, "SetColorSetId"}, + {24, &SET_SYS::SetColorSetId, "SetColorSetId"}, {25, nullptr, "GetConsoleInformationUploadFlag"}, {26, nullptr, "SetConsoleInformationUploadFlag"}, {27, nullptr, "GetAutomaticApplicationDownloadFlag"}, @@ -172,4 +181,6 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") { RegisterHandlers(functions); } +SET_SYS::~SET_SYS() = default; + } // namespace Service::Set diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index b77a97cde..f602f3c77 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h @@ -11,10 +11,19 @@ namespace Service::Set { class SET_SYS final : public ServiceFramework<SET_SYS> { public: explicit SET_SYS(); - ~SET_SYS() = default; + ~SET_SYS() override; private: + /// Indicates the current theme set by the system settings + enum class ColorSet : u32 { + BasicWhite = 0, + BasicBlack = 1, + }; + void GetColorSetId(Kernel::HLERequestContext& ctx); + void SetColorSetId(Kernel::HLERequestContext& ctx); + + ColorSet color_set = ColorSet::BasicWhite; }; } // namespace Service::Set diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 18bd62a08..b0277a875 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -6,7 +6,6 @@ #include "common/common_funcs.h" #include "common/file_util.h" #include "common/logging/log.h" -#include "common/string_util.h" #include "core/file_sys/content_archive.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/process.h" @@ -18,34 +17,6 @@ namespace Loader { -static std::string FindRomFS(const std::string& directory) { - std::string filepath_romfs; - const auto callback = [&filepath_romfs](u64*, const std::string& directory, - const std::string& virtual_name) -> bool { - const std::string physical_name = directory + virtual_name; - if (FileUtil::IsDirectory(physical_name)) { - // Skip directories - return true; - } - - // Verify extension - const std::string extension = physical_name.substr(physical_name.find_last_of(".") + 1); - if (Common::ToLower(extension) != "romfs") { - return true; - } - - // Found it - we are done - filepath_romfs = std::move(physical_name); - return false; - }; - - // Search the specified directory recursively, looking for the first .romfs file, which will - // be used for the RomFS - FileUtil::ForeachDirectoryEntry(nullptr, directory, callback); - - return filepath_romfs; -} - AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file) : AppLoader(std::move(file)) {} diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 4bfd5f536..352938dcb 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -190,7 +190,7 @@ private: u32 entryPoint; public: - ElfReader(void* ptr); + explicit ElfReader(void* ptr); u32 Read32(int off) const { return base32[off >> 2]; diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 6f517ca8c..fbf11e5d0 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -79,7 +79,7 @@ enum class ResultStatus { /// Interface for loading an application class AppLoader : NonCopyable { public: - AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {} + explicit AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {} virtual ~AppLoader() {} /** diff --git a/src/core/tracer/recorder.h b/src/core/tracer/recorder.h index 629c2f6d2..e1cefd5fe 100644 --- a/src/core/tracer/recorder.h +++ b/src/core/tracer/recorder.h @@ -32,7 +32,7 @@ public: * Recorder constructor * @param initial_state Initial recorder state */ - Recorder(const InitialState& initial_state); + explicit Recorder(const InitialState& initial_state); /// Finish recording of this Citrace and save it using the given filename. void Finish(const std::string& filename); diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index d7328ff39..0e205ed72 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -75,14 +75,6 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { ProcessMacroUpload(value); break; } - case MAXWELL3D_REG_INDEX(code_address.code_address_high): - case MAXWELL3D_REG_INDEX(code_address.code_address_low): { - // Note: For some reason games (like Puyo Puyo Tetris) seem to write 0 to the CODE_ADDRESS - // register, we do not currently know if that's intended or a bug, so we assert it lest - // stuff breaks in other places (like the shader address calculation). - ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value."); - break; - } case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]): case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]): diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index a003bc9e3..60c49d672 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -35,9 +35,11 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { case RenderTargetFormat::RGBA32_FLOAT: return 16; case RenderTargetFormat::RGBA16_FLOAT: + case RenderTargetFormat::RG32_FLOAT: return 8; case RenderTargetFormat::RGBA8_UNORM: case RenderTargetFormat::RGB10_A2_UNORM: + case RenderTargetFormat::BGRA8_UNORM: return 4; default: UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format)); diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index a32148ecd..e9d87efb4 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -18,10 +18,13 @@ enum class RenderTargetFormat : u32 { RGBA32_FLOAT = 0xC0, RGBA32_UINT = 0xC2, RGBA16_FLOAT = 0xCA, + RG32_FLOAT = 0xCB, + BGRA8_UNORM = 0xCF, RGB10_A2_UNORM = 0xD1, RGBA8_UNORM = 0xD5, RGBA8_SRGB = 0xD6, R11G11B10_FLOAT = 0xE0, + R8_UNORM = 0xF3, }; enum class DepthFormat : u32 { @@ -31,6 +34,7 @@ enum class DepthFormat : u32 { Z24_X8_UNORM = 0x15, Z24_S8_UNORM = 0x16, Z24_C8_UNORM = 0x18, + Z32_S8_X24_FLOAT = 0x19, }; /// Returns the number of bytes per pixel of each rendertarget format. diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 56d9c575b..a1c47bae9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -5,6 +5,7 @@ #include <algorithm> #include <memory> #include <string> +#include <string_view> #include <tuple> #include <utility> #include <glad/glad.h> @@ -37,11 +38,6 @@ MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); RasterizerOpenGL::RasterizerOpenGL() { - has_ARB_buffer_storage = false; - has_ARB_direct_state_access = false; - has_ARB_separate_shader_objects = false; - has_ARB_vertex_attrib_binding = false; - // Create sampler objects for (size_t i = 0; i < texture_samplers.size(); ++i) { texture_samplers[i].Create(); @@ -59,7 +55,8 @@ RasterizerOpenGL::RasterizerOpenGL() { GLint ext_num; glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num); for (GLint i = 0; i < ext_num; i++) { - std::string extension{reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))}; + const std::string_view extension{ + reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))}; if (extension == "GL_ARB_buffer_storage") { has_ARB_buffer_storage = true; @@ -110,8 +107,6 @@ RasterizerOpenGL::RasterizerOpenGL() { glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.handle); } - accelerate_draw = AccelDraw::Disabled; - glEnable(GL_BLEND); LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!"); @@ -601,7 +596,6 @@ void RasterizerOpenGL::SamplerInfo::Create() { sampler.Create(); mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear; wrap_u = wrap_v = Tegra::Texture::WrapMode::Wrap; - border_color_r = border_color_g = border_color_b = border_color_a = 0; // default is GL_LINEAR_MIPMAP_LINEAR glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -630,8 +624,12 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr } if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border) { - // TODO(Subv): Implement border color - ASSERT(false); + const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g, + config.border_color_b, config.border_color_a}}; + if (border_color != new_border_color) { + border_color = new_border_color; + glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data()); + } } } @@ -691,10 +689,12 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr glBindBuffer(GL_UNIFORM_BUFFER, 0); // Now configure the bindpoint of the buffer inside the shader - std::string buffer_name = used_buffer.GetName(); - GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, buffer_name.c_str()); - if (index != -1) + const std::string buffer_name = used_buffer.GetName(); + const GLuint index = + glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, buffer_name.c_str()); + if (index != GL_INVALID_INDEX) { glUniformBlockBinding(program, index, buffer_draw_state.bindpoint); + } } state.Apply(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index c406142e4..e150be58f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -77,10 +77,7 @@ private: Tegra::Texture::TextureFilter min_filter; Tegra::Texture::WrapMode wrap_u; Tegra::Texture::WrapMode wrap_v; - u32 border_color_r; - u32 border_color_g; - u32 border_color_b; - u32 border_color_a; + GLvec4 border_color; }; /// Configures the color and depth framebuffer states and returns the dirty <Color, Depth> @@ -138,10 +135,10 @@ private: /// Syncs the blend state to match the guest state void SyncBlendState(); - bool has_ARB_buffer_storage; - bool has_ARB_direct_state_access; - bool has_ARB_separate_shader_objects; - bool has_ARB_vertex_attrib_binding; + bool has_ARB_buffer_storage = false; + bool has_ARB_direct_state_access = false; + bool has_ARB_separate_shader_objects = false; + bool has_ARB_vertex_attrib_binding = false; OpenGLState state; @@ -170,5 +167,5 @@ private: void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset); enum class AccelDraw { Disabled, Arrays, Indexed }; - AccelDraw accelerate_draw; + AccelDraw accelerate_draw = AccelDraw::Disabled; }; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 28f0bc379..91ce0357b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -38,7 +38,8 @@ struct FormatTuple { params.addr = config.tic.Address(); params.is_tiled = config.tic.IsTiled(); params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0, - params.pixel_format = PixelFormatFromTextureFormat(config.tic.format); + params.pixel_format = + PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value()); params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); params.type = GetFormatType(params.pixel_format); params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); @@ -106,6 +107,12 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form true}, // BC7U {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8 + {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8 + {GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F + {GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F + {GL_R32F, GL_RED, GL_FLOAT, ComponentType::Float, false}, // R32F + {GL_R16F, GL_RED, GL_HALF_FLOAT, ComponentType::Float, false}, // R16F + {GL_R16, GL_RED, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // R16UNORM // DepthStencil formats {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, @@ -115,6 +122,8 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // Z16 + {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, + ComponentType::Float, false}, // Z32FS8 }}; static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { @@ -197,9 +206,12 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>, MortonCopy<true, PixelFormat::BC7U>, MortonCopy<true, PixelFormat::ASTC_2D_4X4>, - MortonCopy<true, PixelFormat::G8R8>, MortonCopy<true, PixelFormat::Z24S8>, + MortonCopy<true, PixelFormat::G8R8>, MortonCopy<true, PixelFormat::BGRA8>, + MortonCopy<true, PixelFormat::RGBA32F>, MortonCopy<true, PixelFormat::RG32F>, + MortonCopy<true, PixelFormat::R32F>, MortonCopy<true, PixelFormat::R16F>, + MortonCopy<true, PixelFormat::R16UNORM>, MortonCopy<true, PixelFormat::Z24S8>, MortonCopy<true, PixelFormat::S8Z24>, MortonCopy<true, PixelFormat::Z32F>, - MortonCopy<true, PixelFormat::Z16>, + MortonCopy<true, PixelFormat::Z16>, MortonCopy<true, PixelFormat::Z32FS8>, }; static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), @@ -213,7 +225,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), MortonCopy<false, PixelFormat::RGBA16F>, MortonCopy<false, PixelFormat::R11FG11FB10F>, MortonCopy<false, PixelFormat::RGBA32UI>, - // TODO(Subv): Swizzling the DXT1/DXT23/DXT45/DXN1/BC7U formats is not yet supported + // TODO(Subv): Swizzling DXT1/DXT23/DXT45/DXN1/BC7U/ASTC_2D_4X4 formats is not supported nullptr, nullptr, nullptr, @@ -221,10 +233,17 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), nullptr, nullptr, MortonCopy<false, PixelFormat::G8R8>, + MortonCopy<false, PixelFormat::BGRA8>, + MortonCopy<false, PixelFormat::RGBA32F>, + MortonCopy<false, PixelFormat::RG32F>, + MortonCopy<false, PixelFormat::R32F>, + MortonCopy<false, PixelFormat::R16F>, + MortonCopy<false, PixelFormat::R16UNORM>, MortonCopy<false, PixelFormat::Z24S8>, MortonCopy<false, PixelFormat::S8Z24>, MortonCopy<false, PixelFormat::Z32F>, MortonCopy<false, PixelFormat::Z16>, + MortonCopy<false, PixelFormat::Z32FS8>, }; // Allocate an uninitialized texture of appropriate size and format for the surface diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index b084c4db4..fc864c56f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -37,14 +37,21 @@ struct SurfaceParams { BC7U = 12, ASTC_2D_4X4 = 13, G8R8 = 14, + BGRA8 = 15, + RGBA32F = 16, + RG32F = 17, + R32F = 18, + R16F = 19, + R16UNORM = 20, MaxColorFormat, // DepthStencil formats - Z24S8 = 15, - S8Z24 = 16, - Z32F = 17, - Z16 = 18, + Z24S8 = 21, + S8Z24 = 22, + Z32F = 23, + Z16 = 24, + Z32FS8 = 25, MaxDepthStencilFormat, @@ -97,10 +104,17 @@ struct SurfaceParams { 4, // BC7U 4, // ASTC_2D_4X4 1, // G8R8 + 1, // BGRA8 + 1, // RGBA32F + 1, // RG32F + 1, // R32F + 1, // R16F + 1, // R16UNORM 1, // Z24S8 1, // S8Z24 1, // Z32F 1, // Z16 + 1, // Z32FS8 }}; ASSERT(static_cast<size_t>(format) < compression_factor_table.size()); @@ -127,10 +141,17 @@ struct SurfaceParams { 128, // BC7U 32, // ASTC_2D_4X4 16, // G8R8 + 32, // BGRA8 + 128, // RGBA32F + 64, // RG32F + 32, // R32F + 16, // R16F + 16, // R16UNORM 32, // Z24S8 32, // S8Z24 32, // Z32F 16, // Z16 + 64, // Z32FS8 }}; ASSERT(static_cast<size_t>(format) < bpp_table.size()); @@ -151,6 +172,8 @@ struct SurfaceParams { return PixelFormat::Z32F; case Tegra::DepthFormat::Z16_UNORM: return PixelFormat::Z16; + case Tegra::DepthFormat::Z32_S8_X24_FLOAT: + return PixelFormat::Z32FS8; default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); @@ -162,21 +185,30 @@ struct SurfaceParams { case Tegra::RenderTargetFormat::RGBA8_UNORM: case Tegra::RenderTargetFormat::RGBA8_SRGB: return PixelFormat::ABGR8; + case Tegra::RenderTargetFormat::BGRA8_UNORM: + return PixelFormat::BGRA8; case Tegra::RenderTargetFormat::RGB10_A2_UNORM: return PixelFormat::A2B10G10R10; case Tegra::RenderTargetFormat::RGBA16_FLOAT: return PixelFormat::RGBA16F; + case Tegra::RenderTargetFormat::RGBA32_FLOAT: + return PixelFormat::RGBA32F; + case Tegra::RenderTargetFormat::RG32_FLOAT: + return PixelFormat::RG32F; case Tegra::RenderTargetFormat::R11G11B10_FLOAT: return PixelFormat::R11FG11FB10F; case Tegra::RenderTargetFormat::RGBA32_UINT: return PixelFormat::RGBA32UI; + case Tegra::RenderTargetFormat::R8_UNORM: + return PixelFormat::R8; default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); } } - static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format) { + static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format, + Tegra::Texture::ComponentType component_type) { // TODO(Subv): Properly implement this switch (format) { case Tegra::Texture::TextureFormat::A8R8G8B8: @@ -196,7 +228,33 @@ struct SurfaceParams { case Tegra::Texture::TextureFormat::BF10GF11RF11: return PixelFormat::R11FG11FB10F; case Tegra::Texture::TextureFormat::R32_G32_B32_A32: - return PixelFormat::RGBA32UI; + switch (component_type) { + case Tegra::Texture::ComponentType::FLOAT: + return PixelFormat::RGBA32F; + case Tegra::Texture::ComponentType::UINT: + return PixelFormat::RGBA32UI; + } + LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", + static_cast<u32>(component_type)); + UNREACHABLE(); + case Tegra::Texture::TextureFormat::R32_G32: + return PixelFormat::RG32F; + case Tegra::Texture::TextureFormat::R16: + switch (component_type) { + case Tegra::Texture::ComponentType::FLOAT: + return PixelFormat::R16F; + case Tegra::Texture::ComponentType::UNORM: + return PixelFormat::R16UNORM; + } + LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}", + static_cast<u32>(component_type)); + UNREACHABLE(); + case Tegra::Texture::TextureFormat::R32: + return PixelFormat::R32F; + case Tegra::Texture::TextureFormat::ZF32: + return PixelFormat::Z32F; + case Tegra::Texture::TextureFormat::Z24S8: + return PixelFormat::Z24S8; case Tegra::Texture::TextureFormat::DXT1: return PixelFormat::DXT1; case Tegra::Texture::TextureFormat::DXT23: @@ -210,7 +268,8 @@ struct SurfaceParams { case Tegra::Texture::TextureFormat::ASTC_2D_4X4: return PixelFormat::ASTC_2D_4X4; default: - LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); + LOG_CRITICAL(HW_GPU, "Unimplemented format={}, component_type={}", + static_cast<u32>(format), static_cast<u32>(component_type)); UNREACHABLE(); } } @@ -248,7 +307,25 @@ struct SurfaceParams { return Tegra::Texture::TextureFormat::BC7U; case PixelFormat::ASTC_2D_4X4: return Tegra::Texture::TextureFormat::ASTC_2D_4X4; + case PixelFormat::BGRA8: + // TODO(bunnei): This is fine for unswizzling (since we just need the right component + // sizes), but could be a bug if we used this function in different ways. + return Tegra::Texture::TextureFormat::A8R8G8B8; + case PixelFormat::RGBA32F: + return Tegra::Texture::TextureFormat::R32_G32_B32_A32; + case PixelFormat::RG32F: + return Tegra::Texture::TextureFormat::R32_G32; + case PixelFormat::R32F: + return Tegra::Texture::TextureFormat::R32; + case PixelFormat::R16F: + case PixelFormat::R16UNORM: + return Tegra::Texture::TextureFormat::R16; + case PixelFormat::Z32F: + return Tegra::Texture::TextureFormat::ZF32; + case PixelFormat::Z24S8: + return Tegra::Texture::TextureFormat::Z24S8; default: + LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); } } @@ -263,7 +340,10 @@ struct SurfaceParams { return Tegra::DepthFormat::Z32_FLOAT; case PixelFormat::Z16: return Tegra::DepthFormat::Z16_UNORM; + case PixelFormat::Z32FS8: + return Tegra::DepthFormat::Z32_S8_X24_FLOAT; default: + LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); } } @@ -273,6 +353,8 @@ struct SurfaceParams { switch (type) { case Tegra::Texture::ComponentType::UNORM: return ComponentType::UNorm; + case Tegra::Texture::ComponentType::FLOAT: + return ComponentType::Float; default: LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type)); UNREACHABLE(); @@ -284,10 +366,14 @@ struct SurfaceParams { switch (format) { case Tegra::RenderTargetFormat::RGBA8_UNORM: case Tegra::RenderTargetFormat::RGBA8_SRGB: + case Tegra::RenderTargetFormat::BGRA8_UNORM: case Tegra::RenderTargetFormat::RGB10_A2_UNORM: + case Tegra::RenderTargetFormat::R8_UNORM: return ComponentType::UNorm; case Tegra::RenderTargetFormat::RGBA16_FLOAT: case Tegra::RenderTargetFormat::R11G11B10_FLOAT: + case Tegra::RenderTargetFormat::RGBA32_FLOAT: + case Tegra::RenderTargetFormat::RG32_FLOAT: return ComponentType::Float; case Tegra::RenderTargetFormat::RGBA32_UINT: return ComponentType::UInt; @@ -314,6 +400,7 @@ struct SurfaceParams { case Tegra::DepthFormat::Z24_S8_UNORM: return ComponentType::UNorm; case Tegra::DepthFormat::Z32_FLOAT: + case Tegra::DepthFormat::Z32_S8_X24_FLOAT: return ComponentType::Float; default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index d4b1a6f33..acf067050 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -756,8 +756,8 @@ private: } } - std::string WriteTexsInstruction(const Instruction& instr, const std::string& coord, - const std::string& texture) { + void WriteTexsInstruction(const Instruction& instr, const std::string& coord, + const std::string& texture) { // Add an extra scope and declare the texture coords inside to prevent // overwriting them in case they are used as outputs of the texs instruction. shader.AddLine('{'); diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index e19c3b280..16b1bd606 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -56,6 +56,9 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { return {}; } + case Maxwell::VertexAttribute::Type::UnsignedInt: + return GL_UNSIGNED_INT; + case Maxwell::VertexAttribute::Type::Float: return GL_FLOAT; } @@ -112,6 +115,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { return GL_MIRRORED_REPEAT; case Tegra::Texture::WrapMode::ClampToEdge: return GL_CLAMP_TO_EDGE; + case Tegra::Texture::WrapMode::Border: + return GL_CLAMP_TO_BORDER; case Tegra::Texture::WrapMode::ClampOGL: // TODO(Subv): GL_CLAMP was removed as of OpenGL 3.1, to implement GL_CLAMP, we can use // GL_CLAMP_TO_BORDER to get the border color of the texture, and then sample the edge to diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index a3e67d105..50c5a56f6 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -61,10 +61,12 @@ u32 BytesPerPixel(TextureFormat format) { case TextureFormat::A8R8G8B8: case TextureFormat::A2B10G10R10: case TextureFormat::BF10GF11RF11: + case TextureFormat::R32: return 4; case TextureFormat::A1B5G5R5: case TextureFormat::B5G6R5: case TextureFormat::G8R8: + case TextureFormat::R16: return 2; case TextureFormat::R8: return 1; @@ -72,6 +74,8 @@ u32 BytesPerPixel(TextureFormat format) { return 8; case TextureFormat::R32_G32_B32_A32: return 16; + case TextureFormat::R32_G32: + return 8; default: UNIMPLEMENTED_MSG("Format not implemented"); break; @@ -86,6 +90,8 @@ static u32 DepthBytesPerPixel(DepthFormat format) { case DepthFormat::Z24_S8_UNORM: case DepthFormat::Z32_FLOAT: return 4; + case DepthFormat::Z32_S8_X24_FLOAT: + return 8; default: UNIMPLEMENTED_MSG("Format not implemented"); break; @@ -118,6 +124,9 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, case TextureFormat::G8R8: case TextureFormat::R16_G16_B16_A16: case TextureFormat::R32_G32_B32_A32: + case TextureFormat::R32_G32: + case TextureFormat::R32: + case TextureFormat::R16: case TextureFormat::BF10GF11RF11: case TextureFormat::ASTC_2D_4X4: CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, @@ -143,6 +152,7 @@ std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 wid case DepthFormat::S8_Z24_UNORM: case DepthFormat::Z24_S8_UNORM: case DepthFormat::Z32_FLOAT: + case DepthFormat::Z32_S8_X24_FLOAT: CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, unswizzled_data.data(), true, block_height); break; @@ -174,6 +184,9 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat case TextureFormat::G8R8: case TextureFormat::BF10GF11RF11: case TextureFormat::R32_G32_B32_A32: + case TextureFormat::R32_G32: + case TextureFormat::R32: + case TextureFormat::R16: // TODO(Subv): For the time being just forward the same data without any decoding. rgba_data = texture_data; break; diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index d1c755033..c6bd2f4b9 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h @@ -242,10 +242,10 @@ struct TSCEntry { BitField<6, 2, TextureMipmapFilter> mip_filter; }; INSERT_PADDING_BYTES(8); - u32 border_color_r; - u32 border_color_g; - u32 border_color_b; - u32 border_color_a; + float border_color_r; + float border_color_g; + float border_color_b; + float border_color_a; }; static_assert(sizeof(TSCEntry) == 0x20, "TSCEntry has wrong size"); |