diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nfp/nfp.cpp | 108 | ||||
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 35 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 59 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 21 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 16 |
9 files changed, 234 insertions, 33 deletions
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 2af4465de..2a9f84037 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/event.h" | ||
| 8 | #include "core/hle/service/hid/hid.h" | ||
| 7 | #include "core/hle/service/nfp/nfp.h" | 9 | #include "core/hle/service/nfp/nfp.h" |
| 8 | #include "core/hle/service/nfp/nfp_user.h" | 10 | #include "core/hle/service/nfp/nfp_user.h" |
| 9 | 11 | ||
| @@ -18,7 +20,7 @@ public: | |||
| 18 | static const FunctionInfo functions[] = { | 20 | static const FunctionInfo functions[] = { |
| 19 | {0, &IUser::Initialize, "Initialize"}, | 21 | {0, &IUser::Initialize, "Initialize"}, |
| 20 | {1, nullptr, "Finalize"}, | 22 | {1, nullptr, "Finalize"}, |
| 21 | {2, nullptr, "ListDevices"}, | 23 | {2, &IUser::ListDevices, "ListDevices"}, |
| 22 | {3, nullptr, "StartDetection"}, | 24 | {3, nullptr, "StartDetection"}, |
| 23 | {4, nullptr, "StopDetection"}, | 25 | {4, nullptr, "StopDetection"}, |
| 24 | {5, nullptr, "Mount"}, | 26 | {5, nullptr, "Mount"}, |
| @@ -33,24 +35,116 @@ public: | |||
| 33 | {14, nullptr, "GetRegisterInfo"}, | 35 | {14, nullptr, "GetRegisterInfo"}, |
| 34 | {15, nullptr, "GetCommonInfo"}, | 36 | {15, nullptr, "GetCommonInfo"}, |
| 35 | {16, nullptr, "GetModelInfo"}, | 37 | {16, nullptr, "GetModelInfo"}, |
| 36 | {17, nullptr, "AttachActivateEvent"}, | 38 | {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, |
| 37 | {18, nullptr, "AttachDeactivateEvent"}, | 39 | {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, |
| 38 | {19, nullptr, "GetState"}, | 40 | {19, &IUser::GetState, "GetState"}, |
| 39 | {20, nullptr, "GetDeviceState"}, | 41 | {20, &IUser::GetDeviceState, "GetDeviceState"}, |
| 40 | {21, nullptr, "GetNpadId"}, | 42 | {21, &IUser::GetNpadId, "GetNpadId"}, |
| 41 | {22, nullptr, "GetApplicationArea2"}, | 43 | {22, nullptr, "GetApplicationArea2"}, |
| 42 | {23, nullptr, "AttachAvailabilityChangeEvent"}, | 44 | {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, |
| 43 | {24, nullptr, "RecreateApplicationArea"}, | 45 | {24, nullptr, "RecreateApplicationArea"}, |
| 44 | }; | 46 | }; |
| 45 | RegisterHandlers(functions); | 47 | RegisterHandlers(functions); |
| 48 | |||
| 49 | activate_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:ActivateEvent"); | ||
| 50 | deactivate_event = | ||
| 51 | Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); | ||
| 52 | availability_change_event = | ||
| 53 | Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent"); | ||
| 46 | } | 54 | } |
| 47 | 55 | ||
| 48 | private: | 56 | private: |
| 57 | enum class State : u32 { | ||
| 58 | NonInitialized = 0, | ||
| 59 | Initialized = 1, | ||
| 60 | }; | ||
| 61 | |||
| 62 | enum class DeviceState : u32 { | ||
| 63 | Initialized = 0, | ||
| 64 | }; | ||
| 65 | |||
| 49 | void Initialize(Kernel::HLERequestContext& ctx) { | 66 | void Initialize(Kernel::HLERequestContext& ctx) { |
| 50 | NGLOG_WARNING(Service_NFP, "(STUBBED) called"); | 67 | NGLOG_WARNING(Service_NFP, "(STUBBED) called"); |
| 68 | |||
| 69 | state = State::Initialized; | ||
| 70 | |||
| 51 | IPC::ResponseBuilder rb{ctx, 2}; | 71 | IPC::ResponseBuilder rb{ctx, 2}; |
| 52 | rb.Push(RESULT_SUCCESS); | 72 | rb.Push(RESULT_SUCCESS); |
| 53 | } | 73 | } |
| 74 | |||
| 75 | void ListDevices(Kernel::HLERequestContext& ctx) { | ||
| 76 | IPC::RequestParser rp{ctx}; | ||
| 77 | const u32 array_size = rp.Pop<u32>(); | ||
| 78 | |||
| 79 | ctx.WriteBuffer(&device_handle, sizeof(device_handle)); | ||
| 80 | |||
| 81 | NGLOG_WARNING(Service_NFP, "(STUBBED) called, array_size={}", array_size); | ||
| 82 | |||
| 83 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 84 | rb.Push(RESULT_SUCCESS); | ||
| 85 | rb.Push<u32>(0); | ||
| 86 | } | ||
| 87 | |||
| 88 | void AttachActivateEvent(Kernel::HLERequestContext& ctx) { | ||
| 89 | IPC::RequestParser rp{ctx}; | ||
| 90 | const u64 dev_handle = rp.Pop<u64>(); | ||
| 91 | NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); | ||
| 92 | |||
| 93 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 94 | rb.Push(RESULT_SUCCESS); | ||
| 95 | rb.PushCopyObjects(activate_event); | ||
| 96 | } | ||
| 97 | |||
| 98 | void AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { | ||
| 99 | IPC::RequestParser rp{ctx}; | ||
| 100 | const u64 dev_handle = rp.Pop<u64>(); | ||
| 101 | NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); | ||
| 102 | |||
| 103 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 104 | rb.Push(RESULT_SUCCESS); | ||
| 105 | rb.PushCopyObjects(deactivate_event); | ||
| 106 | } | ||
| 107 | |||
| 108 | void GetState(Kernel::HLERequestContext& ctx) { | ||
| 109 | NGLOG_WARNING(Service_NFP, "(STUBBED) called"); | ||
| 110 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 111 | rb.Push(RESULT_SUCCESS); | ||
| 112 | rb.Push<u32>(static_cast<u32>(state)); | ||
| 113 | } | ||
| 114 | |||
| 115 | void GetDeviceState(Kernel::HLERequestContext& ctx) { | ||
| 116 | NGLOG_WARNING(Service_NFP, "(STUBBED) called"); | ||
| 117 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 118 | rb.Push(RESULT_SUCCESS); | ||
| 119 | rb.Push<u32>(static_cast<u32>(device_state)); | ||
| 120 | } | ||
| 121 | |||
| 122 | void GetNpadId(Kernel::HLERequestContext& ctx) { | ||
| 123 | IPC::RequestParser rp{ctx}; | ||
| 124 | const u64 dev_handle = rp.Pop<u64>(); | ||
| 125 | NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); | ||
| 126 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 127 | rb.Push(RESULT_SUCCESS); | ||
| 128 | rb.Push<u32>(npad_id); | ||
| 129 | } | ||
| 130 | |||
| 131 | void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { | ||
| 132 | IPC::RequestParser rp{ctx}; | ||
| 133 | const u64 dev_handle = rp.Pop<u64>(); | ||
| 134 | NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); | ||
| 135 | |||
| 136 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 137 | rb.Push(RESULT_SUCCESS); | ||
| 138 | rb.PushCopyObjects(availability_change_event); | ||
| 139 | } | ||
| 140 | |||
| 141 | const u64 device_handle{0xDEAD}; | ||
| 142 | const HID::ControllerID npad_id{HID::Controller_Player1}; | ||
| 143 | State state{State::NonInitialized}; | ||
| 144 | DeviceState device_state{DeviceState::Initialized}; | ||
| 145 | Kernel::SharedPtr<Kernel::Event> activate_event; | ||
| 146 | Kernel::SharedPtr<Kernel::Event> deactivate_event; | ||
| 147 | Kernel::SharedPtr<Kernel::Event> availability_change_event; | ||
| 54 | }; | 148 | }; |
| 55 | 149 | ||
| 56 | void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) { | 150 | void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) { |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index af18c2d81..2cda1e63e 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -168,13 +168,22 @@ enum class SubOp : u64 { | |||
| 168 | Min = 0x8, | 168 | Min = 0x8, |
| 169 | }; | 169 | }; |
| 170 | 170 | ||
| 171 | enum class FloatRoundingOp : u64 { | 171 | enum class F2iRoundingOp : u64 { |
| 172 | None = 0, | 172 | None = 0, |
| 173 | Floor = 1, | 173 | Floor = 1, |
| 174 | Ceil = 2, | 174 | Ceil = 2, |
| 175 | Trunc = 3, | 175 | Trunc = 3, |
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | enum class F2fRoundingOp : u64 { | ||
| 179 | None = 0, | ||
| 180 | Pass = 3, | ||
| 181 | Round = 8, | ||
| 182 | Floor = 9, | ||
| 183 | Ceil = 10, | ||
| 184 | Trunc = 11, | ||
| 185 | }; | ||
| 186 | |||
| 178 | enum class UniformType : u64 { | 187 | enum class UniformType : u64 { |
| 179 | UnsignedByte = 0, | 188 | UnsignedByte = 0, |
| 180 | SignedByte = 1, | 189 | SignedByte = 1, |
| @@ -314,11 +323,11 @@ union Instruction { | |||
| 314 | BitField<50, 1, u64> saturate_a; | 323 | BitField<50, 1, u64> saturate_a; |
| 315 | 324 | ||
| 316 | union { | 325 | union { |
| 317 | BitField<39, 2, FloatRoundingOp> rounding; | 326 | BitField<39, 2, F2iRoundingOp> rounding; |
| 318 | } f2i; | 327 | } f2i; |
| 319 | 328 | ||
| 320 | union { | 329 | union { |
| 321 | BitField<39, 4, u64> rounding; | 330 | BitField<39, 4, F2fRoundingOp> rounding; |
| 322 | } f2f; | 331 | } f2f; |
| 323 | } conversion; | 332 | } conversion; |
| 324 | 333 | ||
| @@ -390,6 +399,9 @@ class OpCode { | |||
| 390 | public: | 399 | public: |
| 391 | enum class Id { | 400 | enum class Id { |
| 392 | KIL, | 401 | KIL, |
| 402 | BFE_C, | ||
| 403 | BFE_R, | ||
| 404 | BFE_IMM, | ||
| 393 | BRA, | 405 | BRA, |
| 394 | LD_A, | 406 | LD_A, |
| 395 | LD_C, | 407 | LD_C, |
| @@ -444,6 +456,9 @@ public: | |||
| 444 | FMNMX_C, | 456 | FMNMX_C, |
| 445 | FMNMX_R, | 457 | FMNMX_R, |
| 446 | FMNMX_IMM, | 458 | FMNMX_IMM, |
| 459 | IMNMX_C, | ||
| 460 | IMNMX_R, | ||
| 461 | IMNMX_IMM, | ||
| 447 | FSETP_C, // Set Predicate | 462 | FSETP_C, // Set Predicate |
| 448 | FSETP_R, | 463 | FSETP_R, |
| 449 | FSETP_IMM, | 464 | FSETP_IMM, |
| @@ -454,6 +469,10 @@ public: | |||
| 454 | ISETP_IMM, | 469 | ISETP_IMM, |
| 455 | ISETP_R, | 470 | ISETP_R, |
| 456 | PSETP, | 471 | PSETP, |
| 472 | XMAD_IMM, | ||
| 473 | XMAD_CR, | ||
| 474 | XMAD_RC, | ||
| 475 | XMAD_RR, | ||
| 457 | }; | 476 | }; |
| 458 | 477 | ||
| 459 | enum class Type { | 478 | enum class Type { |
| @@ -565,6 +584,9 @@ private: | |||
| 565 | std::vector<Matcher> table = { | 584 | std::vector<Matcher> table = { |
| 566 | #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) | 585 | #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) |
| 567 | INST("111000110011----", Id::KIL, Type::Flow, "KIL"), | 586 | INST("111000110011----", Id::KIL, Type::Flow, "KIL"), |
| 587 | INST("0100110000000---", Id::BFE_C, Type::Flow, "BFE_C"), | ||
| 588 | INST("0101110000000---", Id::BFE_R, Type::Flow, "BFE_R"), | ||
| 589 | INST("0011100-00000---", Id::BFE_IMM, Type::Flow, "BFE_IMM"), | ||
| 568 | INST("111000100100----", Id::BRA, Type::Flow, "BRA"), | 590 | INST("111000100100----", Id::BRA, Type::Flow, "BRA"), |
| 569 | INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), | 591 | INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), |
| 570 | INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), | 592 | INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), |
| @@ -606,6 +628,9 @@ private: | |||
| 606 | INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), | 628 | INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), |
| 607 | INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), | 629 | INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), |
| 608 | INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), | 630 | INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), |
| 631 | INST("0100110000100---", Id::IMNMX_C, Type::Arithmetic, "FMNMX_IMM"), | ||
| 632 | INST("0101110000100---", Id::IMNMX_R, Type::Arithmetic, "FMNMX_IMM"), | ||
| 633 | INST("0011100-00100---", Id::IMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), | ||
| 609 | INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), | 634 | INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), |
| 610 | INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), | 635 | INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), |
| 611 | INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), | 636 | INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), |
| @@ -629,6 +654,10 @@ private: | |||
| 629 | INST("010110110110----", Id::ISETP_R, Type::IntegerSetPredicate, "ISETP_R"), | 654 | INST("010110110110----", Id::ISETP_R, Type::IntegerSetPredicate, "ISETP_R"), |
| 630 | INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerSetPredicate, "ISETP_IMM"), | 655 | INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerSetPredicate, "ISETP_IMM"), |
| 631 | INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), | 656 | INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), |
| 657 | INST("0011011-00------", Id::XMAD_IMM, Type::Arithmetic, "XMAD_IMM"), | ||
| 658 | INST("0100111---------", Id::XMAD_CR, Type::Arithmetic, "XMAD_CR"), | ||
| 659 | INST("010100010-------", Id::XMAD_RC, Type::Arithmetic, "XMAD_RC"), | ||
| 660 | INST("0101101100------", Id::XMAD_RR, Type::Arithmetic, "XMAD_RR"), | ||
| 632 | }; | 661 | }; |
| 633 | #undef INST | 662 | #undef INST |
| 634 | std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) { | 663 | std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b23b8fb29..2e90ebcf4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -681,6 +681,14 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, GLuint program, | |||
| 681 | Surface surface = res_cache.GetTextureSurface(texture); | 681 | Surface surface = res_cache.GetTextureSurface(texture); |
| 682 | if (surface != nullptr) { | 682 | if (surface != nullptr) { |
| 683 | state.texture_units[current_bindpoint].texture_2d = surface->texture.handle; | 683 | state.texture_units[current_bindpoint].texture_2d = surface->texture.handle; |
| 684 | state.texture_units[current_bindpoint].swizzle.r = | ||
| 685 | MaxwellToGL::SwizzleSource(texture.tic.x_source); | ||
| 686 | state.texture_units[current_bindpoint].swizzle.g = | ||
| 687 | MaxwellToGL::SwizzleSource(texture.tic.y_source); | ||
| 688 | state.texture_units[current_bindpoint].swizzle.b = | ||
| 689 | MaxwellToGL::SwizzleSource(texture.tic.z_source); | ||
| 690 | state.texture_units[current_bindpoint].swizzle.a = | ||
| 691 | MaxwellToGL::SwizzleSource(texture.tic.w_source); | ||
| 684 | } else { | 692 | } else { |
| 685 | // Can occur when texture addr is null or its memory is unmapped/invalid | 693 | // Can occur when texture addr is null or its memory is unmapped/invalid |
| 686 | state.texture_units[current_bindpoint].texture_2d = 0; | 694 | state.texture_units[current_bindpoint].texture_2d = 0; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 3067ce3b3..8e249584f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -1056,10 +1056,27 @@ private: | |||
| 1056 | break; | 1056 | break; |
| 1057 | } | 1057 | } |
| 1058 | case OpCode::Id::F2F_R: { | 1058 | case OpCode::Id::F2F_R: { |
| 1059 | // TODO(Subv): Implement rounding operations. | ||
| 1060 | ASSERT_MSG(instr.conversion.f2f.rounding == 0, "Unimplemented rounding operation"); | ||
| 1061 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 1059 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 1062 | 1060 | ||
| 1061 | switch (instr.conversion.f2f.rounding) { | ||
| 1062 | case Tegra::Shader::F2fRoundingOp::None: | ||
| 1063 | break; | ||
| 1064 | case Tegra::Shader::F2fRoundingOp::Floor: | ||
| 1065 | op_a = "floor(" + op_a + ')'; | ||
| 1066 | break; | ||
| 1067 | case Tegra::Shader::F2fRoundingOp::Ceil: | ||
| 1068 | op_a = "ceil(" + op_a + ')'; | ||
| 1069 | break; | ||
| 1070 | case Tegra::Shader::F2fRoundingOp::Trunc: | ||
| 1071 | op_a = "trunc(" + op_a + ')'; | ||
| 1072 | break; | ||
| 1073 | default: | ||
| 1074 | NGLOG_CRITICAL(HW_GPU, "Unimplemented f2f rounding mode {}", | ||
| 1075 | static_cast<u32>(instr.conversion.f2f.rounding.Value())); | ||
| 1076 | UNREACHABLE(); | ||
| 1077 | break; | ||
| 1078 | } | ||
| 1079 | |||
| 1063 | if (instr.conversion.abs_a) { | 1080 | if (instr.conversion.abs_a) { |
| 1064 | op_a = "abs(" + op_a + ')'; | 1081 | op_a = "abs(" + op_a + ')'; |
| 1065 | } | 1082 | } |
| @@ -1074,17 +1091,16 @@ private: | |||
| 1074 | op_a = "abs(" + op_a + ')'; | 1091 | op_a = "abs(" + op_a + ')'; |
| 1075 | } | 1092 | } |
| 1076 | 1093 | ||
| 1077 | using Tegra::Shader::FloatRoundingOp; | ||
| 1078 | switch (instr.conversion.f2i.rounding) { | 1094 | switch (instr.conversion.f2i.rounding) { |
| 1079 | case FloatRoundingOp::None: | 1095 | case Tegra::Shader::F2iRoundingOp::None: |
| 1080 | break; | 1096 | break; |
| 1081 | case FloatRoundingOp::Floor: | 1097 | case Tegra::Shader::F2iRoundingOp::Floor: |
| 1082 | op_a = "floor(" + op_a + ')'; | 1098 | op_a = "floor(" + op_a + ')'; |
| 1083 | break; | 1099 | break; |
| 1084 | case FloatRoundingOp::Ceil: | 1100 | case Tegra::Shader::F2iRoundingOp::Ceil: |
| 1085 | op_a = "ceil(" + op_a + ')'; | 1101 | op_a = "ceil(" + op_a + ')'; |
| 1086 | break; | 1102 | break; |
| 1087 | case FloatRoundingOp::Trunc: | 1103 | case Tegra::Shader::F2iRoundingOp::Trunc: |
| 1088 | op_a = "trunc(" + op_a + ')'; | 1104 | op_a = "trunc(" + op_a + ')'; |
| 1089 | break; | 1105 | break; |
| 1090 | default: | 1106 | default: |
| @@ -1112,13 +1128,11 @@ private: | |||
| 1112 | break; | 1128 | break; |
| 1113 | } | 1129 | } |
| 1114 | case OpCode::Type::Memory: { | 1130 | case OpCode::Type::Memory: { |
| 1115 | const Attribute::Index attribute = instr.attribute.fmt20.index; | ||
| 1116 | |||
| 1117 | switch (opcode->GetId()) { | 1131 | switch (opcode->GetId()) { |
| 1118 | case OpCode::Id::LD_A: { | 1132 | case OpCode::Id::LD_A: { |
| 1119 | ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); | 1133 | ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); |
| 1120 | regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element, | 1134 | regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element, |
| 1121 | attribute); | 1135 | instr.attribute.fmt20.index); |
| 1122 | break; | 1136 | break; |
| 1123 | } | 1137 | } |
| 1124 | case OpCode::Id::LD_C: { | 1138 | case OpCode::Id::LD_C: { |
| @@ -1150,12 +1164,11 @@ private: | |||
| 1150 | } | 1164 | } |
| 1151 | case OpCode::Id::ST_A: { | 1165 | case OpCode::Id::ST_A: { |
| 1152 | ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); | 1166 | ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); |
| 1153 | regs.SetOutputAttributeToRegister(attribute, instr.attribute.fmt20.element, | 1167 | regs.SetOutputAttributeToRegister(instr.attribute.fmt20.index, |
| 1154 | instr.gpr0); | 1168 | instr.attribute.fmt20.element, instr.gpr0); |
| 1155 | break; | 1169 | break; |
| 1156 | } | 1170 | } |
| 1157 | case OpCode::Id::TEX: { | 1171 | case OpCode::Id::TEX: { |
| 1158 | ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); | ||
| 1159 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1172 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 1160 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 1173 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 1161 | const std::string sampler = GetSampler(instr.sampler); | 1174 | const std::string sampler = GetSampler(instr.sampler); |
| @@ -1168,7 +1181,7 @@ private: | |||
| 1168 | const std::string texture = "texture(" + sampler + ", coords)"; | 1181 | const std::string texture = "texture(" + sampler + ", coords)"; |
| 1169 | 1182 | ||
| 1170 | size_t dest_elem{}; | 1183 | size_t dest_elem{}; |
| 1171 | for (size_t elem = 0; elem < instr.attribute.fmt20.size; ++elem) { | 1184 | for (size_t elem = 0; elem < 4; ++elem) { |
| 1172 | if (!instr.tex.IsComponentEnabled(elem)) { | 1185 | if (!instr.tex.IsComponentEnabled(elem)) { |
| 1173 | // Skip disabled components | 1186 | // Skip disabled components |
| 1174 | continue; | 1187 | continue; |
| @@ -1181,7 +1194,6 @@ private: | |||
| 1181 | break; | 1194 | break; |
| 1182 | } | 1195 | } |
| 1183 | case OpCode::Id::TEXS: { | 1196 | case OpCode::Id::TEXS: { |
| 1184 | ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); | ||
| 1185 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1197 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 1186 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); | 1198 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); |
| 1187 | const std::string sampler = GetSampler(instr.sampler); | 1199 | const std::string sampler = GetSampler(instr.sampler); |
| @@ -1278,16 +1290,17 @@ private: | |||
| 1278 | } | 1290 | } |
| 1279 | case OpCode::Type::IntegerSetPredicate: { | 1291 | case OpCode::Type::IntegerSetPredicate: { |
| 1280 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); | 1292 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); |
| 1293 | std::string op_b; | ||
| 1281 | 1294 | ||
| 1282 | std::string op_b{}; | 1295 | if (instr.is_b_imm) { |
| 1283 | 1296 | op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')'; | |
| 1284 | ASSERT_MSG(!instr.is_b_imm, "ISETP_IMM not implemented"); | ||
| 1285 | |||
| 1286 | if (instr.is_b_gpr) { | ||
| 1287 | op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.isetp.is_signed); | ||
| 1288 | } else { | 1297 | } else { |
| 1289 | op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, | 1298 | if (instr.is_b_gpr) { |
| 1290 | GLSLRegister::Type::Integer); | 1299 | op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.isetp.is_signed); |
| 1300 | } else { | ||
| 1301 | op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, | ||
| 1302 | GLSLRegister::Type::Integer); | ||
| 1303 | } | ||
| 1291 | } | 1304 | } |
| 1292 | 1305 | ||
| 1293 | using Tegra::Shader::Pred; | 1306 | using Tegra::Shader::Pred; |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index f91dfe36a..44f0c8a01 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -50,6 +50,10 @@ OpenGLState::OpenGLState() { | |||
| 50 | for (auto& texture_unit : texture_units) { | 50 | for (auto& texture_unit : texture_units) { |
| 51 | texture_unit.texture_2d = 0; | 51 | texture_unit.texture_2d = 0; |
| 52 | texture_unit.sampler = 0; | 52 | texture_unit.sampler = 0; |
| 53 | texture_unit.swizzle.r = GL_RED; | ||
| 54 | texture_unit.swizzle.g = GL_GREEN; | ||
| 55 | texture_unit.swizzle.b = GL_BLUE; | ||
| 56 | texture_unit.swizzle.a = GL_ALPHA; | ||
| 53 | } | 57 | } |
| 54 | 58 | ||
| 55 | lighting_lut.texture_buffer = 0; | 59 | lighting_lut.texture_buffer = 0; |
| @@ -200,6 +204,15 @@ void OpenGLState::Apply() const { | |||
| 200 | if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { | 204 | if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { |
| 201 | glBindSampler(i, texture_units[i].sampler); | 205 | glBindSampler(i, texture_units[i].sampler); |
| 202 | } | 206 | } |
| 207 | // Update the texture swizzle | ||
| 208 | if (texture_units[i].swizzle.r != cur_state.texture_units[i].swizzle.r || | ||
| 209 | texture_units[i].swizzle.g != cur_state.texture_units[i].swizzle.g || | ||
| 210 | texture_units[i].swizzle.b != cur_state.texture_units[i].swizzle.b || | ||
| 211 | texture_units[i].swizzle.a != cur_state.texture_units[i].swizzle.a) { | ||
| 212 | std::array<GLint, 4> mask = {texture_units[i].swizzle.r, texture_units[i].swizzle.g, | ||
| 213 | texture_units[i].swizzle.b, texture_units[i].swizzle.a}; | ||
| 214 | glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); | ||
| 215 | } | ||
| 203 | } | 216 | } |
| 204 | 217 | ||
| 205 | // Constbuffers | 218 | // Constbuffers |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 75c08e645..839e50e93 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -85,6 +85,12 @@ public: | |||
| 85 | struct { | 85 | struct { |
| 86 | GLuint texture_2d; // GL_TEXTURE_BINDING_2D | 86 | GLuint texture_2d; // GL_TEXTURE_BINDING_2D |
| 87 | GLuint sampler; // GL_SAMPLER_BINDING | 87 | GLuint sampler; // GL_SAMPLER_BINDING |
| 88 | struct { | ||
| 89 | GLint r; // GL_TEXTURE_SWIZZLE_R | ||
| 90 | GLint g; // GL_TEXTURE_SWIZZLE_G | ||
| 91 | GLint b; // GL_TEXTURE_SWIZZLE_B | ||
| 92 | GLint a; // GL_TEXTURE_SWIZZLE_A | ||
| 93 | } swizzle; | ||
| 88 | } texture_units[32]; | 94 | } texture_units[32]; |
| 89 | 95 | ||
| 90 | struct { | 96 | struct { |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index cf11983cf..2155fb019 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -180,4 +180,25 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) { | |||
| 180 | return {}; | 180 | return {}; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) { | ||
| 184 | switch (source) { | ||
| 185 | case Tegra::Texture::SwizzleSource::Zero: | ||
| 186 | return GL_ZERO; | ||
| 187 | case Tegra::Texture::SwizzleSource::R: | ||
| 188 | return GL_RED; | ||
| 189 | case Tegra::Texture::SwizzleSource::G: | ||
| 190 | return GL_GREEN; | ||
| 191 | case Tegra::Texture::SwizzleSource::B: | ||
| 192 | return GL_BLUE; | ||
| 193 | case Tegra::Texture::SwizzleSource::A: | ||
| 194 | return GL_ALPHA; | ||
| 195 | case Tegra::Texture::SwizzleSource::OneInt: | ||
| 196 | case Tegra::Texture::SwizzleSource::OneFloat: | ||
| 197 | return GL_ONE; | ||
| 198 | } | ||
| 199 | NGLOG_CRITICAL(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source)); | ||
| 200 | UNREACHABLE(); | ||
| 201 | return {}; | ||
| 202 | } | ||
| 203 | |||
| 183 | } // namespace MaxwellToGL | 204 | } // namespace MaxwellToGL |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 3440d2190..f33766bfd 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -316,6 +316,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, | |||
| 316 | }}; | 316 | }}; |
| 317 | 317 | ||
| 318 | state.texture_units[0].texture_2d = screen_info.display_texture; | 318 | state.texture_units[0].texture_2d = screen_info.display_texture; |
| 319 | state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; | ||
| 319 | state.Apply(); | 320 | state.Apply(); |
| 320 | 321 | ||
| 321 | glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); | 322 | glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); |
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index f48ca30b8..a17eaf19d 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h | |||
| @@ -122,6 +122,17 @@ enum class ComponentType : u32 { | |||
| 122 | FLOAT = 7 | 122 | FLOAT = 7 |
| 123 | }; | 123 | }; |
| 124 | 124 | ||
| 125 | enum class SwizzleSource : u32 { | ||
| 126 | Zero = 0, | ||
| 127 | |||
| 128 | R = 2, | ||
| 129 | G = 3, | ||
| 130 | B = 4, | ||
| 131 | A = 5, | ||
| 132 | OneInt = 6, | ||
| 133 | OneFloat = 7, | ||
| 134 | }; | ||
| 135 | |||
| 125 | union TextureHandle { | 136 | union TextureHandle { |
| 126 | u32 raw; | 137 | u32 raw; |
| 127 | BitField<0, 20, u32> tic_id; | 138 | BitField<0, 20, u32> tic_id; |
| @@ -139,6 +150,11 @@ struct TICEntry { | |||
| 139 | BitField<10, 3, ComponentType> g_type; | 150 | BitField<10, 3, ComponentType> g_type; |
| 140 | BitField<13, 3, ComponentType> b_type; | 151 | BitField<13, 3, ComponentType> b_type; |
| 141 | BitField<16, 3, ComponentType> a_type; | 152 | BitField<16, 3, ComponentType> a_type; |
| 153 | |||
| 154 | BitField<19, 3, SwizzleSource> x_source; | ||
| 155 | BitField<22, 3, SwizzleSource> y_source; | ||
| 156 | BitField<25, 3, SwizzleSource> z_source; | ||
| 157 | BitField<28, 3, SwizzleSource> w_source; | ||
| 142 | }; | 158 | }; |
| 143 | u32 address_low; | 159 | u32 address_low; |
| 144 | union { | 160 | union { |