diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 2603192fea..10755abc1e 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -144,6 +144,7 @@ static u32 latest_signal = 0; static bool memory_break = false; static Kernel::Thread* current_thread = nullptr; +static int thread_id = -1; // Binding to a port within the reserved ports range (0-1023) requires root permissions, // so default to a port outside of that range. @@ -562,11 +563,9 @@ static void HandleQuery() { /// Handle set thread command from gdb client. static void HandleSetThread() { if (memcmp(command_buffer, "Hc", 2) == 0 || memcmp(command_buffer, "Hg", 2) == 0) { - int thread_id = -1; + thread_id = -1; if (command_buffer[2] != '-') { - thread_id = static_cast(HexToInt( - command_buffer + 2, - command_length - 2 /*strlen(reinterpret_cast(command_buffer) + 2)*/)); + thread_id = static_cast(HexToInt(command_buffer + 2, command_length - 2)); } if (thread_id >= 1) { current_thread = FindThreadById(thread_id); @@ -585,9 +584,7 @@ static void HandleSetThread() { /// Handle thread alive command from gdb client. static void HandleThreadAlive() { - int thread_id = static_cast( - HexToInt(command_buffer + 1, - command_length - 1 /*strlen(reinterpret_cast(command_buffer) + 1)*/)); + int thread_id = static_cast(HexToInt(command_buffer + 1, command_length - 1)); if (thread_id == 0) { thread_id = 1; } @@ -1192,7 +1189,9 @@ void SetCpuStepFlag(bool is_step) { } void SendTrap(Kernel::Thread* thread, int trap) { - if (send_trap) { + //NGLOG_ERROR(Debug_GDBStub, "SendTrap {} {} {} {}", thread->GetThreadId(), thread_id, trap, + // send_trap); + if (send_trap && (thread == current_thread)) { send_trap = false; SendSignal(thread, trap); } diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 12954556d2..b8d6b8d4d0 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -561,7 +561,7 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF {32, nullptr, "BeginBlockingHomeButton"}, {33, nullptr, "EndBlockingHomeButton"}, {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, - {50, nullptr, "GetPseudoDeviceId"}, + {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, {60, nullptr, "SetMediaPlaybackStateForApplication"}, {65, nullptr, "IsGamePlayRecordingSupported"}, {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, @@ -684,6 +684,17 @@ void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) { NGLOG_WARNING(Service_AM, "(STUBBED) called"); } +void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + + // Returns a 128-bit UUID + rb.Push(0); + rb.Push(0); + + NGLOG_WARNING(Service_AM, "(STUBBED) called"); +} + void InstallInterfaces(SM::ServiceManager& service_manager, std::shared_ptr nvflinger) { std::make_shared(nvflinger)->InstallAsService(service_manager); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 301a6c7988..1da79fd015 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -138,6 +138,7 @@ private: void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx); void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx); void NotifyRunning(Kernel::HLERequestContext& ctx); + void GetPseudoDeviceId(Kernel::HLERequestContext& ctx); }; class IHomeMenuFunctions final : public ServiceFramework { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index eee92cfcde..62489c7fee 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -38,7 +38,7 @@ public: {8, nullptr, "SetPriority"}, {9, nullptr, "SetNetworkProfileId"}, {10, nullptr, "SetRejectable"}, - {11, nullptr, "SetConnectionConfirmationOption"}, + {11, &IRequest::SetConnectionConfirmationOption, "SetConnectionConfirmationOption"}, {12, nullptr, "SetPersistent"}, {13, nullptr, "SetInstant"}, {14, nullptr, "SetSustainable"}, @@ -67,23 +67,32 @@ private: rb.Push(RESULT_SUCCESS); rb.Push(0); } + void GetResult(Kernel::HLERequestContext& ctx) { NGLOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { NGLOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 2}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(event1, event2); } + void Cancel(Kernel::HLERequestContext& ctx) { NGLOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + void SetConnectionConfirmationOption(Kernel::HLERequestContext& ctx) { + NGLOG_WARNING(Service_NIFM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + Kernel::SharedPtr event1, event2; }; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index a9538ff435..0abc0de834 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -26,6 +26,10 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector& input, std::vec return ZCullGetInfo(input, output); case IoctlCommand::IocZbcSetTable: return ZBCSetTable(input, output); + case IoctlCommand::IocZbcQueryTable: + return ZBCQueryTable(input, output); + case IoctlCommand::IocFlushL2: + return FlushL2(input, output); } UNIMPLEMENTED_MSG("Unimplemented ioctl"); return 0; @@ -136,4 +140,22 @@ u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector& input, std::vector& return 0; } +u32 nvhost_ctrl_gpu::ZBCQueryTable(const std::vector& input, std::vector& output) { + NGLOG_WARNING(Service_NVDRV, "(STUBBED) called"); + IoctlZbcQueryTable params{}; + std::memcpy(¶ms, input.data(), input.size()); + // TODO : To implement properly + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + +u32 nvhost_ctrl_gpu::FlushL2(const std::vector& input, std::vector& output) { + NGLOG_WARNING(Service_NVDRV, "(STUBBED) called"); + IoctlFlushL2 params{}; + std::memcpy(¶ms, input.data(), input.size()); + // TODO : To implement properly + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 1d5ba2e672..f09113e678 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -26,6 +26,18 @@ private: IocZcullGetCtxSizeCommand = 0x80044701, IocZcullGetInfo = 0x80284702, IocZbcSetTable = 0x402C4703, + IocZbcQueryTable = 0xC0344704, + IocFlushL2 = 0x40084707, + IocInvalICache = 0x4008470D, + IocSetMmudebugMode = 0x4008470E, + IocSetSmDebugMode = 0x4010470F, + IocWaitForPause = 0xC0084710, + IocGetTcpExceptionEnStatus = 0x80084711, + IocNumVsms = 0x80084712, + IocVsmsMapping = 0xC0044713, + IocGetErrorChannelUserData = 0xC008471B, + IocGetGpuTime = 0xC010471C, + IocGetCpuTimeCorrelationInfo = 0xC108471D, }; struct IoctlGpuCharacteristics { @@ -127,12 +139,31 @@ private: }; static_assert(sizeof(IoctlZbcSetTable) == 44, "IoctlZbcSetTable is incorrect size"); + struct IoctlZbcQueryTable { + u32_le color_ds[4]; + u32_le color_l2[4]; + u32_le depth; + u32_le ref_cnt; + u32_le format; + u32_le type; + u32_le index_size; + }; + static_assert(sizeof(IoctlZbcQueryTable) == 52, "IoctlZbcQueryTable is incorrect size"); + + struct IoctlFlushL2 { + u32_le flush; // l2_flush | l2_invalidate << 1 | fb_flush << 2 + u32_le reserved; + }; + static_assert(sizeof(IoctlFlushL2) == 8, "IoctlFlushL2 is incorrect size"); + u32 GetCharacteristics(const std::vector& input, std::vector& output); u32 GetTPCMasks(const std::vector& input, std::vector& output); u32 GetActiveSlotMask(const std::vector& input, std::vector& output); u32 ZCullGetCtxSize(const std::vector& input, std::vector& output); u32 ZCullGetInfo(const std::vector& input, std::vector& output); u32 ZBCSetTable(const std::vector& input, std::vector& output); + u32 ZBCQueryTable(const std::vector& input, std::vector& output); + u32 FlushL2(const std::vector& input, std::vector& output); }; } // namespace Service::Nvidia::Devices diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 38757c0383..4eb5073256 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -173,6 +173,13 @@ enum class SubOp : u64 { Min = 0x8, }; +enum class FloatRoundingOp : u64 { + None = 0, + Floor = 1, + Ceil = 2, + Trunc = 3, +}; + union Instruction { Instruction& operator=(const Instruction& instr) { value = instr.value; @@ -290,11 +297,20 @@ union Instruction { union { BitField<10, 2, Register::Size> size; - BitField<13, 1, u64> is_signed; + BitField<12, 1, u64> is_output_signed; + BitField<13, 1, u64> is_input_signed; BitField<41, 2, u64> selector; BitField<45, 1, u64> negate_a; BitField<49, 1, u64> abs_a; BitField<50, 1, u64> saturate_a; + + union { + BitField<39, 2, FloatRoundingOp> rounding; + } f2i; + + union { + BitField<39, 4, u64> rounding; + } f2f; } conversion; union { @@ -560,9 +576,9 @@ private: INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"), INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"), INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), - INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), - INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), - INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), + INST("0100110010110---", Id::F2I_C, Type::Conversion, "F2I_C"), + INST("0101110010110---", Id::F2I_R, Type::Conversion, "F2I_R"), + INST("0011100-10110---", Id::F2I_IMM, Type::Conversion, "F2I_IMM"), INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 756518ee70..66351fe6e4 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -26,6 +26,10 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { ASSERT(format != RenderTargetFormat::NONE); switch (format) { + case RenderTargetFormat::RGBA32_FLOAT: + return 16; + case RenderTargetFormat::RGBA16_FLOAT: + return 8; case RenderTargetFormat::RGBA8_UNORM: case RenderTargetFormat::RGB10_A2_UNORM: return 4; diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index f168a51712..5852b96199 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -15,10 +15,12 @@ namespace Tegra { enum class RenderTargetFormat : u32 { NONE = 0x0, + RGBA32_FLOAT = 0xC0, RGBA16_FLOAT = 0xCA, RGB10_A2_UNORM = 0xD1, RGBA8_UNORM = 0xD5, RGBA8_SRGB = 0xD6, + R11G11B10_FLOAT = 0xE0, }; /// Returns the number of bytes per pixel of each rendertarget format. diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index d6048f6392..9164d7f344 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -50,6 +50,7 @@ static constexpr std::array tex_form {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false}, // A1B5G5R5 {GL_R8, GL_RED, GL_UNSIGNED_BYTE, false}, // R8 {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false}, // RGBA16F + {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false}, // R11FG11FB10F {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45 @@ -60,8 +61,10 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); if (type == SurfaceType::ColorTexture) { ASSERT(static_cast(pixel_format) < tex_format_tuples.size()); - // For now only UNORM components are supported, or RGBA16F which is type FLOAT - ASSERT(component_type == ComponentType::UNorm || pixel_format == PixelFormat::RGBA16F); + // For now only UNORM components are supported, or either R11FG11FB10F or RGBA16F which are + // type FLOAT + ASSERT(component_type == ComponentType::UNorm || pixel_format == PixelFormat::RGBA16F || + pixel_format == PixelFormat::R11FG11FB10F); return tex_format_tuples[static_cast(pixel_format)]; } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { // TODO(Subv): Implement depth formats @@ -110,11 +113,12 @@ static constexpr std::array morton_to_gl_fns = { - MortonCopy, MortonCopy, - MortonCopy, MortonCopy, - MortonCopy, MortonCopy, - MortonCopy, MortonCopy, - MortonCopy, MortonCopy, + MortonCopy, MortonCopy, + MortonCopy, MortonCopy, + MortonCopy, MortonCopy, + MortonCopy, MortonCopy, + MortonCopy, MortonCopy, + MortonCopy, }; static constexpr std::array, MortonCopy, MortonCopy, + MortonCopy, // TODO(Subv): Swizzling the DXT1/DXT23/DXT45/DXN1 formats is not yet supported nullptr, nullptr, diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 6f08678ab2..0f43e863d0 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -60,10 +60,11 @@ struct SurfaceParams { A1B5G5R5 = 3, R8 = 4, RGBA16F = 5, - DXT1 = 6, - DXT23 = 7, - DXT45 = 8, - DXN1 = 9, // This is also known as BC4 + R11FG11FB10F = 6, + DXT1 = 7, + DXT23 = 8, + DXT45 = 9, + DXN1 = 10, // This is also known as BC4 Max, Invalid = 255, @@ -104,7 +105,8 @@ struct SurfaceParams { 1, // A2B10G10R10 1, // A1B5G5R5 1, // R8 - 2, // RGBA16F + 1, // RGBA16F + 1, // R11FG11FB10F 4, // DXT1 4, // DXT23 4, // DXT45 @@ -129,6 +131,7 @@ struct SurfaceParams { 16, // A1B5G5R5 8, // R8 64, // RGBA16F + 32, // R11FG11FB10F 64, // DXT1 128, // DXT23 128, // DXT45 @@ -151,6 +154,8 @@ struct SurfaceParams { return PixelFormat::A2B10G10R10; case Tegra::RenderTargetFormat::RGBA16_FLOAT: return PixelFormat::RGBA16F; + case Tegra::RenderTargetFormat::R11G11B10_FLOAT: + return PixelFormat::R11FG11FB10F; default: NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast(format)); UNREACHABLE(); @@ -182,6 +187,8 @@ struct SurfaceParams { return PixelFormat::R8; case Tegra::Texture::TextureFormat::R16_G16_B16_A16: return PixelFormat::RGBA16F; + case Tegra::Texture::TextureFormat::BF10GF11RF11: + return PixelFormat::R11FG11FB10F; case Tegra::Texture::TextureFormat::DXT1: return PixelFormat::DXT1; case Tegra::Texture::TextureFormat::DXT23: @@ -211,6 +218,8 @@ struct SurfaceParams { return Tegra::Texture::TextureFormat::R8; case PixelFormat::RGBA16F: return Tegra::Texture::TextureFormat::R16_G16_B16_A16; + case PixelFormat::R11FG11FB10F: + return Tegra::Texture::TextureFormat::BF10GF11RF11; case PixelFormat::DXT1: return Tegra::Texture::TextureFormat::DXT1; case PixelFormat::DXT23: @@ -243,6 +252,7 @@ struct SurfaceParams { case Tegra::RenderTargetFormat::RGB10_A2_UNORM: return ComponentType::UNorm; case Tegra::RenderTargetFormat::RGBA16_FLOAT: + case Tegra::RenderTargetFormat::R11G11B10_FLOAT: return ComponentType::Float; default: NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast(format)); diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index f886e49ca7..7a59ecccf3 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -895,7 +895,7 @@ private: } case OpCode::Type::Shift: { - std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false); + std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true); std::string op_b; if (instr.is_b_imm) { @@ -991,18 +991,20 @@ private: ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); std::string op_a = - regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); + regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); if (instr.conversion.abs_a) { op_a = "abs(" + op_a + ')'; } - regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); + regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, + 1); break; } case OpCode::Id::I2F_R: { + ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); std::string op_a = - regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); + regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); if (instr.conversion.abs_a) { op_a = "abs(" + op_a + ')'; @@ -1012,6 +1014,8 @@ private: break; } case OpCode::Id::F2F_R: { + // TODO(Subv): Implement rounding operations. + ASSERT_MSG(instr.conversion.f2f.rounding == 0, "Unimplemented rounding operation"); std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); if (instr.conversion.abs_a) { @@ -1021,6 +1025,43 @@ private: regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); break; } + case OpCode::Id::F2I_R: { + std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); + + if (instr.conversion.abs_a) { + op_a = "abs(" + op_a + ')'; + } + + using Tegra::Shader::FloatRoundingOp; + switch (instr.conversion.f2i.rounding) { + case FloatRoundingOp::None: + break; + case FloatRoundingOp::Floor: + op_a = "floor(" + op_a + ')'; + break; + case FloatRoundingOp::Ceil: + op_a = "ceil(" + op_a + ')'; + break; + case FloatRoundingOp::Trunc: + op_a = "trunc(" + op_a + ')'; + break; + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented f2i rounding mode {}", + static_cast(instr.conversion.f2i.rounding.Value())); + UNREACHABLE(); + break; + } + + if (instr.conversion.is_output_signed) { + op_a = "int(" + op_a + ')'; + } else { + op_a = "uint(" + op_a + ')'; + } + + regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, + 1); + break; + } default: { NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); UNREACHABLE(); diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index a630610d80..cf11983cf8 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -100,6 +100,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { switch (wrap_mode) { case Tegra::Texture::WrapMode::Wrap: return GL_REPEAT; + case Tegra::Texture::WrapMode::Mirror: + return GL_MIRRORED_REPEAT; case Tegra::Texture::WrapMode::ClampToEdge: return GL_CLAMP_TO_EDGE; case Tegra::Texture::WrapMode::ClampOGL: diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 2d2af55548..7bf9c4c4b1 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -55,6 +55,7 @@ u32 BytesPerPixel(TextureFormat format) { return 16; case TextureFormat::A8R8G8B8: case TextureFormat::A2B10G10R10: + case TextureFormat::BF10GF11RF11: return 4; case TextureFormat::A1B5G5R5: case TextureFormat::B5G6R5: @@ -92,6 +93,7 @@ std::vector UnswizzleTexture(VAddr address, TextureFormat format, u32 width, case TextureFormat::B5G6R5: case TextureFormat::R8: case TextureFormat::R16_G16_B16_A16: + case TextureFormat::BF10GF11RF11: CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, unswizzled_data.data(), true, block_height); break; @@ -118,6 +120,7 @@ std::vector DecodeTexture(const std::vector& texture_data, TextureFormat case TextureFormat::A1B5G5R5: case TextureFormat::B5G6R5: case TextureFormat::R8: + case TextureFormat::BF10GF11RF11: // TODO(Subv): For the time being just forward the same data without any decoding. rgba_data = texture_data; break;