diff options
| -rw-r--r-- | src/core/core.cpp | 2 | ||||
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 9 | ||||
| -rw-r--r-- | src/core/gdbstub/gdbstub.h | 7 | ||||
| -rw-r--r-- | src/core/hle/service/sm/controller.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 25 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 23 | ||||
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 67 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.cpp | 85 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 8 |
11 files changed, 184 insertions, 60 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 218508126..d1bc9340d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -166,7 +166,7 @@ struct System::Impl { | |||
| 166 | service_manager = std::make_shared<Service::SM::ServiceManager>(); | 166 | service_manager = std::make_shared<Service::SM::ServiceManager>(); |
| 167 | 167 | ||
| 168 | Service::Init(service_manager, system); | 168 | Service::Init(service_manager, system); |
| 169 | GDBStub::Init(); | 169 | GDBStub::DeferStart(); |
| 170 | 170 | ||
| 171 | renderer = VideoCore::CreateRenderer(emu_window, system); | 171 | renderer = VideoCore::CreateRenderer(emu_window, system); |
| 172 | if (!renderer->Init()) { | 172 | if (!renderer->Init()) { |
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index e8d8871a7..6d15aeed9 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -141,6 +141,7 @@ constexpr char target_xml[] = | |||
| 141 | )"; | 141 | )"; |
| 142 | 142 | ||
| 143 | int gdbserver_socket = -1; | 143 | int gdbserver_socket = -1; |
| 144 | bool defer_start = false; | ||
| 144 | 145 | ||
| 145 | u8 command_buffer[GDB_BUFFER_SIZE]; | 146 | u8 command_buffer[GDB_BUFFER_SIZE]; |
| 146 | u32 command_length; | 147 | u32 command_length; |
| @@ -1166,6 +1167,9 @@ static void RemoveBreakpoint() { | |||
| 1166 | 1167 | ||
| 1167 | void HandlePacket() { | 1168 | void HandlePacket() { |
| 1168 | if (!IsConnected()) { | 1169 | if (!IsConnected()) { |
| 1170 | if (defer_start) { | ||
| 1171 | ToggleServer(true); | ||
| 1172 | } | ||
| 1169 | return; | 1173 | return; |
| 1170 | } | 1174 | } |
| 1171 | 1175 | ||
| @@ -1256,6 +1260,10 @@ void ToggleServer(bool status) { | |||
| 1256 | } | 1260 | } |
| 1257 | } | 1261 | } |
| 1258 | 1262 | ||
| 1263 | void DeferStart() { | ||
| 1264 | defer_start = true; | ||
| 1265 | } | ||
| 1266 | |||
| 1259 | static void Init(u16 port) { | 1267 | static void Init(u16 port) { |
| 1260 | if (!server_enabled) { | 1268 | if (!server_enabled) { |
| 1261 | // Set the halt loop to false in case the user enabled the gdbstub mid-execution. | 1269 | // Set the halt loop to false in case the user enabled the gdbstub mid-execution. |
| @@ -1341,6 +1349,7 @@ void Shutdown() { | |||
| 1341 | if (!server_enabled) { | 1349 | if (!server_enabled) { |
| 1342 | return; | 1350 | return; |
| 1343 | } | 1351 | } |
| 1352 | defer_start = false; | ||
| 1344 | 1353 | ||
| 1345 | LOG_INFO(Debug_GDBStub, "Stopping GDB ..."); | 1354 | LOG_INFO(Debug_GDBStub, "Stopping GDB ..."); |
| 1346 | if (gdbserver_socket != -1) { | 1355 | if (gdbserver_socket != -1) { |
diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h index 5a36524b2..8fe3c320b 100644 --- a/src/core/gdbstub/gdbstub.h +++ b/src/core/gdbstub/gdbstub.h | |||
| @@ -43,6 +43,13 @@ void ToggleServer(bool status); | |||
| 43 | /// Start the gdbstub server. | 43 | /// Start the gdbstub server. |
| 44 | void Init(); | 44 | void Init(); |
| 45 | 45 | ||
| 46 | /** | ||
| 47 | * Defer initialization of the gdbstub to the first packet processing functions. | ||
| 48 | * This avoids a case where the gdbstub thread is frozen after initialization | ||
| 49 | * and fails to respond in time to packets. | ||
| 50 | */ | ||
| 51 | void DeferStart(); | ||
| 52 | |||
| 46 | /// Stop gdbstub server. | 53 | /// Stop gdbstub server. |
| 47 | void Shutdown(); | 54 | void Shutdown(); |
| 48 | 55 | ||
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index c45b285f8..9cca84b31 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp | |||
| @@ -44,7 +44,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 44 | 44 | ||
| 45 | IPC::ResponseBuilder rb{ctx, 3}; | 45 | IPC::ResponseBuilder rb{ctx, 3}; |
| 46 | rb.Push(RESULT_SUCCESS); | 46 | rb.Push(RESULT_SUCCESS); |
| 47 | rb.Push<u16>(0x500); | 47 | rb.Push<u16>(0x1000); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | Controller::Controller() : ServiceFramework("IpcController") { | 50 | Controller::Controller() : ServiceFramework("IpcController") { |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index ce536e29b..ba63b44b4 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -98,6 +98,8 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 98 | regs.framebuffer_srgb = 1; | 98 | regs.framebuffer_srgb = 1; |
| 99 | regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise; | 99 | regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise; |
| 100 | 100 | ||
| 101 | shadow_state = regs; | ||
| 102 | |||
| 101 | mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true; | 103 | mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true; |
| 102 | mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true; | 104 | mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true; |
| 103 | mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; | 105 | mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; |
| @@ -160,8 +162,17 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { | |||
| 160 | ASSERT_MSG(method < Regs::NUM_REGS, | 162 | ASSERT_MSG(method < Regs::NUM_REGS, |
| 161 | "Invalid Maxwell3D register, increase the size of the Regs structure"); | 163 | "Invalid Maxwell3D register, increase the size of the Regs structure"); |
| 162 | 164 | ||
| 163 | if (regs.reg_array[method] != method_call.argument) { | 165 | u32 arg = method_call.argument; |
| 164 | regs.reg_array[method] = method_call.argument; | 166 | // Keep track of the register value in shadow_state when requested. |
| 167 | if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Track || | ||
| 168 | shadow_state.shadow_ram_control == Regs::ShadowRamControl::TrackWithFilter) { | ||
| 169 | shadow_state.reg_array[method] = arg; | ||
| 170 | } else if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Replay) { | ||
| 171 | arg = shadow_state.reg_array[method]; | ||
| 172 | } | ||
| 173 | |||
| 174 | if (regs.reg_array[method] != arg) { | ||
| 175 | regs.reg_array[method] = arg; | ||
| 165 | 176 | ||
| 166 | for (const auto& table : dirty.tables) { | 177 | for (const auto& table : dirty.tables) { |
| 167 | dirty.flags[table[method]] = true; | 178 | dirty.flags[table[method]] = true; |
| @@ -169,12 +180,16 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { | |||
| 169 | } | 180 | } |
| 170 | 181 | ||
| 171 | switch (method) { | 182 | switch (method) { |
| 183 | case MAXWELL3D_REG_INDEX(shadow_ram_control): { | ||
| 184 | shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(method_call.argument); | ||
| 185 | break; | ||
| 186 | } | ||
| 172 | case MAXWELL3D_REG_INDEX(macros.data): { | 187 | case MAXWELL3D_REG_INDEX(macros.data): { |
| 173 | ProcessMacroUpload(method_call.argument); | 188 | ProcessMacroUpload(arg); |
| 174 | break; | 189 | break; |
| 175 | } | 190 | } |
| 176 | case MAXWELL3D_REG_INDEX(macros.bind): { | 191 | case MAXWELL3D_REG_INDEX(macros.bind): { |
| 177 | ProcessMacroBind(method_call.argument); | 192 | ProcessMacroBind(arg); |
| 178 | break; | 193 | break; |
| 179 | } | 194 | } |
| 180 | case MAXWELL3D_REG_INDEX(firmware[4]): { | 195 | case MAXWELL3D_REG_INDEX(firmware[4]): { |
| @@ -250,7 +265,7 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { | |||
| 250 | } | 265 | } |
| 251 | case MAXWELL3D_REG_INDEX(data_upload): { | 266 | case MAXWELL3D_REG_INDEX(data_upload): { |
| 252 | const bool is_last_call = method_call.IsLastCall(); | 267 | const bool is_last_call = method_call.IsLastCall(); |
| 253 | upload_state.ProcessData(method_call.argument, is_last_call); | 268 | upload_state.ProcessData(arg, is_last_call); |
| 254 | if (is_last_call) { | 269 | if (is_last_call) { |
| 255 | OnMemoryWrite(); | 270 | OnMemoryWrite(); |
| 256 | } | 271 | } |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 8a9e9992e..d24c9f657 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -531,6 +531,17 @@ public: | |||
| 531 | Fill = 0x1b02, | 531 | Fill = 0x1b02, |
| 532 | }; | 532 | }; |
| 533 | 533 | ||
| 534 | enum class ShadowRamControl : u32 { | ||
| 535 | // write value to shadow ram | ||
| 536 | Track = 0, | ||
| 537 | // write value to shadow ram ( with validation ??? ) | ||
| 538 | TrackWithFilter = 1, | ||
| 539 | // only write to real hw register | ||
| 540 | Passthrough = 2, | ||
| 541 | // write value from shadow ram to real hw register | ||
| 542 | Replay = 3, | ||
| 543 | }; | ||
| 544 | |||
| 534 | struct RenderTargetConfig { | 545 | struct RenderTargetConfig { |
| 535 | u32 address_high; | 546 | u32 address_high; |
| 536 | u32 address_low; | 547 | u32 address_low; |
| @@ -674,7 +685,9 @@ public: | |||
| 674 | u32 bind; | 685 | u32 bind; |
| 675 | } macros; | 686 | } macros; |
| 676 | 687 | ||
| 677 | INSERT_UNION_PADDING_WORDS(0x17); | 688 | ShadowRamControl shadow_ram_control; |
| 689 | |||
| 690 | INSERT_UNION_PADDING_WORDS(0x16); | ||
| 678 | 691 | ||
| 679 | Upload::Registers upload; | 692 | Upload::Registers upload; |
| 680 | struct { | 693 | struct { |
| @@ -1263,7 +1276,12 @@ public: | |||
| 1263 | }; | 1276 | }; |
| 1264 | std::array<u32, NUM_REGS> reg_array; | 1277 | std::array<u32, NUM_REGS> reg_array; |
| 1265 | }; | 1278 | }; |
| 1266 | } regs{}; | 1279 | }; |
| 1280 | |||
| 1281 | Regs regs{}; | ||
| 1282 | |||
| 1283 | /// Store temporary hw register values, used by some calls to restore state after a operation | ||
| 1284 | Regs shadow_state; | ||
| 1267 | 1285 | ||
| 1268 | static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size"); | 1286 | static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size"); |
| 1269 | static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable"); | 1287 | static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable"); |
| @@ -1458,6 +1476,7 @@ private: | |||
| 1458 | "Field " #field_name " has invalid position") | 1476 | "Field " #field_name " has invalid position") |
| 1459 | 1477 | ||
| 1460 | ASSERT_REG_POSITION(macros, 0x45); | 1478 | ASSERT_REG_POSITION(macros, 0x45); |
| 1479 | ASSERT_REG_POSITION(shadow_ram_control, 0x49); | ||
| 1461 | ASSERT_REG_POSITION(upload, 0x60); | 1480 | ASSERT_REG_POSITION(upload, 0x60); |
| 1462 | ASSERT_REG_POSITION(exec_upload, 0x6C); | 1481 | ASSERT_REG_POSITION(exec_upload, 0x6C); |
| 1463 | ASSERT_REG_POSITION(data_upload, 0x6D); | 1482 | ASSERT_REG_POSITION(data_upload, 0x6D); |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index eba42deb4..49dc5abe0 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -82,6 +82,10 @@ union Attribute { | |||
| 82 | Position = 7, | 82 | Position = 7, |
| 83 | Attribute_0 = 8, | 83 | Attribute_0 = 8, |
| 84 | Attribute_31 = 39, | 84 | Attribute_31 = 39, |
| 85 | FrontColor = 40, | ||
| 86 | FrontSecondaryColor = 41, | ||
| 87 | BackColor = 42, | ||
| 88 | BackSecondaryColor = 43, | ||
| 85 | ClipDistances0123 = 44, | 89 | ClipDistances0123 = 44, |
| 86 | ClipDistances4567 = 45, | 90 | ClipDistances4567 = 45, |
| 87 | PointCoord = 46, | 91 | PointCoord = 46, |
| @@ -89,6 +93,8 @@ union Attribute { | |||
| 89 | // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval | 93 | // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval |
| 90 | // shader. | 94 | // shader. |
| 91 | TessCoordInstanceIDVertexID = 47, | 95 | TessCoordInstanceIDVertexID = 47, |
| 96 | TexCoord_0 = 48, | ||
| 97 | TexCoord_7 = 55, | ||
| 92 | // This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment | 98 | // This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment |
| 93 | // shader. It is unknown what the other values contain. | 99 | // shader. It is unknown what the other values contain. |
| 94 | FrontFacing = 63, | 100 | FrontFacing = 63, |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 063f41327..826eee7df 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -933,13 +933,15 @@ void RasterizerOpenGL::SyncViewport() { | |||
| 933 | } | 933 | } |
| 934 | flags[Dirty::Viewport0 + i] = false; | 934 | flags[Dirty::Viewport0 + i] = false; |
| 935 | 935 | ||
| 936 | const Common::Rectangle<f32> rect{regs.viewport_transform[i].GetRect()}; | 936 | const auto& src = regs.viewport_transform[i]; |
| 937 | const Common::Rectangle<f32> rect{src.GetRect()}; | ||
| 937 | glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(), | 938 | glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(), |
| 938 | rect.GetHeight()); | 939 | rect.GetHeight()); |
| 939 | 940 | ||
| 940 | const auto& src = regs.viewports[i]; | 941 | const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; |
| 941 | glDepthRangeIndexed(static_cast<GLuint>(i), static_cast<GLdouble>(src.depth_range_near), | 942 | const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z; |
| 942 | static_cast<GLdouble>(src.depth_range_far)); | 943 | const GLdouble far_depth = src.translate_z + src.scale_z; |
| 944 | glDepthRangeIndexed(static_cast<GLuint>(i), near_depth, far_depth); | ||
| 943 | } | 945 | } |
| 944 | } | 946 | } |
| 945 | } | 947 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 2c38f57fd..8aa4a7ac9 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -366,10 +366,19 @@ constexpr bool IsGenericAttribute(Attribute::Index index) { | |||
| 366 | return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31; | 366 | return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | constexpr bool IsLegacyTexCoord(Attribute::Index index) { | ||
| 370 | return static_cast<int>(index) >= static_cast<int>(Attribute::Index::TexCoord_0) && | ||
| 371 | static_cast<int>(index) <= static_cast<int>(Attribute::Index::TexCoord_7); | ||
| 372 | } | ||
| 373 | |||
| 369 | constexpr Attribute::Index ToGenericAttribute(u64 value) { | 374 | constexpr Attribute::Index ToGenericAttribute(u64 value) { |
| 370 | return static_cast<Attribute::Index>(value + static_cast<u64>(Attribute::Index::Attribute_0)); | 375 | return static_cast<Attribute::Index>(value + static_cast<u64>(Attribute::Index::Attribute_0)); |
| 371 | } | 376 | } |
| 372 | 377 | ||
| 378 | constexpr int GetLegacyTexCoordIndex(Attribute::Index index) { | ||
| 379 | return static_cast<int>(index) - static_cast<int>(Attribute::Index::TexCoord_0); | ||
| 380 | } | ||
| 381 | |||
| 373 | u32 GetGenericAttributeIndex(Attribute::Index index) { | 382 | u32 GetGenericAttributeIndex(Attribute::Index index) { |
| 374 | ASSERT(IsGenericAttribute(index)); | 383 | ASSERT(IsGenericAttribute(index)); |
| 375 | return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0); | 384 | return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0); |
| @@ -498,7 +507,7 @@ private: | |||
| 498 | if (!identifier.empty()) { | 507 | if (!identifier.empty()) { |
| 499 | code.AddLine("// {}", identifier); | 508 | code.AddLine("// {}", identifier); |
| 500 | } | 509 | } |
| 501 | code.AddLine("#version 440 core"); | 510 | code.AddLine("#version 440 {}", ir.UsesLegacyVaryings() ? "compatibility" : "core"); |
| 502 | code.AddLine("#extension GL_ARB_separate_shader_objects : enable"); | 511 | code.AddLine("#extension GL_ARB_separate_shader_objects : enable"); |
| 503 | if (device.HasShaderBallot()) { | 512 | if (device.HasShaderBallot()) { |
| 504 | code.AddLine("#extension GL_ARB_shader_ballot : require"); | 513 | code.AddLine("#extension GL_ARB_shader_ballot : require"); |
| @@ -561,6 +570,16 @@ private: | |||
| 561 | if (stage != ShaderType::Fragment) { | 570 | if (stage != ShaderType::Fragment) { |
| 562 | return; | 571 | return; |
| 563 | } | 572 | } |
| 573 | if (ir.UsesLegacyVaryings()) { | ||
| 574 | code.AddLine("in gl_PerFragment {{"); | ||
| 575 | ++code.scope; | ||
| 576 | code.AddLine("vec4 gl_TexCoord[8];"); | ||
| 577 | code.AddLine("vec4 gl_Color;"); | ||
| 578 | code.AddLine("vec4 gl_SecondaryColor;"); | ||
| 579 | --code.scope; | ||
| 580 | code.AddLine("}};"); | ||
| 581 | } | ||
| 582 | |||
| 564 | for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { | 583 | for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { |
| 565 | code.AddLine("layout (location = {}) out vec4 frag_color{};", rt, rt); | 584 | code.AddLine("layout (location = {}) out vec4 frag_color{};", rt, rt); |
| 566 | } | 585 | } |
| @@ -617,12 +636,12 @@ private: | |||
| 617 | code.AddLine("float gl_PointSize;"); | 636 | code.AddLine("float gl_PointSize;"); |
| 618 | } | 637 | } |
| 619 | 638 | ||
| 620 | if (ir.UsesInstanceId()) { | 639 | if (ir.UsesLegacyVaryings()) { |
| 621 | code.AddLine("int gl_InstanceID;"); | 640 | code.AddLine("vec4 gl_TexCoord[8];"); |
| 622 | } | 641 | code.AddLine("vec4 gl_FrontColor;"); |
| 623 | 642 | code.AddLine("vec4 gl_FrontSecondaryColor;"); | |
| 624 | if (ir.UsesVertexId()) { | 643 | code.AddLine("vec4 gl_BackColor;"); |
| 625 | code.AddLine("int gl_VertexID;"); | 644 | code.AddLine("vec4 gl_BackSecondaryColor;"); |
| 626 | } | 645 | } |
| 627 | 646 | ||
| 628 | --code.scope; | 647 | --code.scope; |
| @@ -1128,6 +1147,10 @@ private: | |||
| 1128 | default: | 1147 | default: |
| 1129 | UNREACHABLE(); | 1148 | UNREACHABLE(); |
| 1130 | } | 1149 | } |
| 1150 | case Attribute::Index::FrontColor: | ||
| 1151 | return {"gl_Color"s + GetSwizzle(element), Type::Float}; | ||
| 1152 | case Attribute::Index::FrontSecondaryColor: | ||
| 1153 | return {"gl_SecondaryColor"s + GetSwizzle(element), Type::Float}; | ||
| 1131 | case Attribute::Index::PointCoord: | 1154 | case Attribute::Index::PointCoord: |
| 1132 | switch (element) { | 1155 | switch (element) { |
| 1133 | case 0: | 1156 | case 0: |
| @@ -1168,6 +1191,12 @@ private: | |||
| 1168 | return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element), | 1191 | return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element), |
| 1169 | Type::Float}; | 1192 | Type::Float}; |
| 1170 | } | 1193 | } |
| 1194 | if (IsLegacyTexCoord(attribute)) { | ||
| 1195 | UNIMPLEMENTED_IF(stage == ShaderType::Geometry); | ||
| 1196 | return {fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute), | ||
| 1197 | GetSwizzle(element)), | ||
| 1198 | Type::Float}; | ||
| 1199 | } | ||
| 1171 | break; | 1200 | break; |
| 1172 | } | 1201 | } |
| 1173 | UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); | 1202 | UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); |
| @@ -1206,11 +1235,12 @@ private: | |||
| 1206 | } | 1235 | } |
| 1207 | 1236 | ||
| 1208 | std::optional<Expression> GetOutputAttribute(const AbufNode* abuf) { | 1237 | std::optional<Expression> GetOutputAttribute(const AbufNode* abuf) { |
| 1238 | const u32 element = abuf->GetElement(); | ||
| 1209 | switch (const auto attribute = abuf->GetIndex()) { | 1239 | switch (const auto attribute = abuf->GetIndex()) { |
| 1210 | case Attribute::Index::Position: | 1240 | case Attribute::Index::Position: |
| 1211 | return {{"gl_Position"s + GetSwizzle(abuf->GetElement()), Type::Float}}; | 1241 | return {{"gl_Position"s + GetSwizzle(element), Type::Float}}; |
| 1212 | case Attribute::Index::LayerViewportPointSize: | 1242 | case Attribute::Index::LayerViewportPointSize: |
| 1213 | switch (abuf->GetElement()) { | 1243 | switch (element) { |
| 1214 | case 0: | 1244 | case 0: |
| 1215 | UNIMPLEMENTED(); | 1245 | UNIMPLEMENTED(); |
| 1216 | return {}; | 1246 | return {}; |
| @@ -1228,13 +1258,26 @@ private: | |||
| 1228 | return {{"gl_PointSize", Type::Float}}; | 1258 | return {{"gl_PointSize", Type::Float}}; |
| 1229 | } | 1259 | } |
| 1230 | return {}; | 1260 | return {}; |
| 1261 | case Attribute::Index::FrontColor: | ||
| 1262 | return {{"gl_FrontColor"s + GetSwizzle(element), Type::Float}}; | ||
| 1263 | case Attribute::Index::FrontSecondaryColor: | ||
| 1264 | return {{"gl_FrontSecondaryColor"s + GetSwizzle(element), Type::Float}}; | ||
| 1265 | case Attribute::Index::BackColor: | ||
| 1266 | return {{"gl_BackColor"s + GetSwizzle(element), Type::Float}}; | ||
| 1267 | case Attribute::Index::BackSecondaryColor: | ||
| 1268 | return {{"gl_BackSecondaryColor"s + GetSwizzle(element), Type::Float}}; | ||
| 1231 | case Attribute::Index::ClipDistances0123: | 1269 | case Attribute::Index::ClipDistances0123: |
| 1232 | return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), Type::Float}}; | 1270 | return {{fmt::format("gl_ClipDistance[{}]", element), Type::Float}}; |
| 1233 | case Attribute::Index::ClipDistances4567: | 1271 | case Attribute::Index::ClipDistances4567: |
| 1234 | return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), Type::Float}}; | 1272 | return {{fmt::format("gl_ClipDistance[{}]", element + 4), Type::Float}}; |
| 1235 | default: | 1273 | default: |
| 1236 | if (IsGenericAttribute(attribute)) { | 1274 | if (IsGenericAttribute(attribute)) { |
| 1237 | return {{GetGenericOutputAttribute(attribute, abuf->GetElement()), Type::Float}}; | 1275 | return {{GetGenericOutputAttribute(attribute, element), Type::Float}}; |
| 1276 | } | ||
| 1277 | if (IsLegacyTexCoord(attribute)) { | ||
| 1278 | return {{fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute), | ||
| 1279 | GetSwizzle(element)), | ||
| 1280 | Type::Float}}; | ||
| 1238 | } | 1281 | } |
| 1239 | UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute)); | 1282 | UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute)); |
| 1240 | return {}; | 1283 | return {}; |
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 425927777..baf7188d2 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp | |||
| @@ -96,6 +96,7 @@ Node ShaderIR::GetPredicate(bool immediate) { | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) { | 98 | Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) { |
| 99 | MarkAttributeUsage(index, element); | ||
| 99 | used_input_attributes.emplace(index); | 100 | used_input_attributes.emplace(index); |
| 100 | return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); | 101 | return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); |
| 101 | } | 102 | } |
| @@ -106,42 +107,8 @@ Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_addres | |||
| 106 | } | 107 | } |
| 107 | 108 | ||
| 108 | Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { | 109 | Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { |
| 109 | if (index == Attribute::Index::LayerViewportPointSize) { | 110 | MarkAttributeUsage(index, element); |
| 110 | switch (element) { | ||
| 111 | case 0: | ||
| 112 | UNIMPLEMENTED(); | ||
| 113 | break; | ||
| 114 | case 1: | ||
| 115 | uses_layer = true; | ||
| 116 | break; | ||
| 117 | case 2: | ||
| 118 | uses_viewport_index = true; | ||
| 119 | break; | ||
| 120 | case 3: | ||
| 121 | uses_point_size = true; | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | if (index == Attribute::Index::TessCoordInstanceIDVertexID) { | ||
| 126 | switch (element) { | ||
| 127 | case 2: | ||
| 128 | uses_instance_id = true; | ||
| 129 | break; | ||
| 130 | case 3: | ||
| 131 | uses_vertex_id = true; | ||
| 132 | break; | ||
| 133 | default: | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | if (index == Attribute::Index::ClipDistances0123 || | ||
| 138 | index == Attribute::Index::ClipDistances4567) { | ||
| 139 | const auto clip_index = | ||
| 140 | static_cast<u32>((index == Attribute::Index::ClipDistances4567 ? 1 : 0) + element); | ||
| 141 | used_clip_distances.at(clip_index) = true; | ||
| 142 | } | ||
| 143 | used_output_attributes.insert(index); | 111 | used_output_attributes.insert(index); |
| 144 | |||
| 145 | return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); | 112 | return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); |
| 146 | } | 113 | } |
| 147 | 114 | ||
| @@ -452,6 +419,54 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) { | |||
| 452 | Immediate(bits)); | 419 | Immediate(bits)); |
| 453 | } | 420 | } |
| 454 | 421 | ||
| 422 | void ShaderIR::MarkAttributeUsage(Attribute::Index index, u64 element) { | ||
| 423 | switch (index) { | ||
| 424 | case Attribute::Index::LayerViewportPointSize: | ||
| 425 | switch (element) { | ||
| 426 | case 0: | ||
| 427 | UNIMPLEMENTED(); | ||
| 428 | break; | ||
| 429 | case 1: | ||
| 430 | uses_layer = true; | ||
| 431 | break; | ||
| 432 | case 2: | ||
| 433 | uses_viewport_index = true; | ||
| 434 | break; | ||
| 435 | case 3: | ||
| 436 | uses_point_size = true; | ||
| 437 | break; | ||
| 438 | } | ||
| 439 | break; | ||
| 440 | case Attribute::Index::TessCoordInstanceIDVertexID: | ||
| 441 | switch (element) { | ||
| 442 | case 2: | ||
| 443 | uses_instance_id = true; | ||
| 444 | break; | ||
| 445 | case 3: | ||
| 446 | uses_vertex_id = true; | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | break; | ||
| 450 | case Attribute::Index::ClipDistances0123: | ||
| 451 | case Attribute::Index::ClipDistances4567: { | ||
| 452 | const u64 clip_index = (index == Attribute::Index::ClipDistances4567 ? 4 : 0) + element; | ||
| 453 | used_clip_distances.at(clip_index) = true; | ||
| 454 | break; | ||
| 455 | } | ||
| 456 | case Attribute::Index::FrontColor: | ||
| 457 | case Attribute::Index::FrontSecondaryColor: | ||
| 458 | case Attribute::Index::BackColor: | ||
| 459 | case Attribute::Index::BackSecondaryColor: | ||
| 460 | uses_legacy_varyings = true; | ||
| 461 | break; | ||
| 462 | default: | ||
| 463 | if (index >= Attribute::Index::TexCoord_0 && index <= Attribute::Index::TexCoord_7) { | ||
| 464 | uses_legacy_varyings = true; | ||
| 465 | } | ||
| 466 | break; | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 455 | std::size_t ShaderIR::DeclareAmend(Node new_amend) { | 470 | std::size_t ShaderIR::DeclareAmend(Node new_amend) { |
| 456 | const std::size_t id = amend_code.size(); | 471 | const std::size_t id = amend_code.size(); |
| 457 | amend_code.push_back(new_amend); | 472 | amend_code.push_back(new_amend); |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index dde036b40..80fc9b82c 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -137,6 +137,10 @@ public: | |||
| 137 | return uses_vertex_id; | 137 | return uses_vertex_id; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | bool UsesLegacyVaryings() const { | ||
| 141 | return uses_legacy_varyings; | ||
| 142 | } | ||
| 143 | |||
| 140 | bool UsesWarps() const { | 144 | bool UsesWarps() const { |
| 141 | return uses_warps; | 145 | return uses_warps; |
| 142 | } | 146 | } |
| @@ -343,6 +347,9 @@ private: | |||
| 343 | /// Inserts a sequence of bits from a node | 347 | /// Inserts a sequence of bits from a node |
| 344 | Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits); | 348 | Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits); |
| 345 | 349 | ||
| 350 | /// Marks the usage of a input or output attribute. | ||
| 351 | void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element); | ||
| 352 | |||
| 346 | void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, | 353 | void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, |
| 347 | const Node4& components); | 354 | const Node4& components); |
| 348 | 355 | ||
| @@ -443,6 +450,7 @@ private: | |||
| 443 | bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes | 450 | bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes |
| 444 | bool uses_instance_id{}; | 451 | bool uses_instance_id{}; |
| 445 | bool uses_vertex_id{}; | 452 | bool uses_vertex_id{}; |
| 453 | bool uses_legacy_varyings{}; | ||
| 446 | bool uses_warps{}; | 454 | bool uses_warps{}; |
| 447 | bool uses_indexed_samplers{}; | 455 | bool uses_indexed_samplers{}; |
| 448 | 456 | ||