diff options
| author | 2017-02-08 22:07:34 -0800 | |
|---|---|---|
| committer | 2017-02-08 22:07:34 -0800 | |
| commit | 2889372e47624e368df0d0361cb38b8100f047dd (patch) | |
| tree | 183cd1cd6edb60ab566bd1fe181b712643bef30c /src | |
| parent | Merge pull request #2539 from Kloen/re-killing-warnings (diff) | |
| parent | VideoCore: Move Regs to its own file (diff) | |
| download | yuzu-2889372e47624e368df0d0361cb38b8100f047dd.tar.gz yuzu-2889372e47624e368df0d0361cb38b8100f047dd.tar.xz yuzu-2889372e47624e368df0d0361cb38b8100f047dd.zip | |
Merge pull request #2482 from yuriks/pica-refactor
Split up monolithic Regs struct
Diffstat (limited to 'src')
37 files changed, 2635 insertions, 2427 deletions
diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp index ee79f0edf..536548f36 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp | |||
| @@ -18,8 +18,8 @@ | |||
| 18 | #include "citra_qt/util/util.h" | 18 | #include "citra_qt/util/util.h" |
| 19 | #include "common/vector_math.h" | 19 | #include "common/vector_math.h" |
| 20 | #include "video_core/debug_utils/debug_utils.h" | 20 | #include "video_core/debug_utils/debug_utils.h" |
| 21 | #include "video_core/pica.h" | ||
| 22 | #include "video_core/pica_state.h" | 21 | #include "video_core/pica_state.h" |
| 22 | #include "video_core/regs.h" | ||
| 23 | #include "video_core/texture/texture_decode.h" | 23 | #include "video_core/texture/texture_decode.h" |
| 24 | 24 | ||
| 25 | namespace { | 25 | namespace { |
| @@ -123,15 +123,16 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& | |||
| 123 | void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { | 123 | void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { |
| 124 | const unsigned int command_id = | 124 | const unsigned int command_id = |
| 125 | list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | 125 | list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); |
| 126 | if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || | 126 | if (COMMAND_IN_RANGE(command_id, texturing.texture0) || |
| 127 | COMMAND_IN_RANGE(command_id, texture2)) { | 127 | COMMAND_IN_RANGE(command_id, texturing.texture1) || |
| 128 | COMMAND_IN_RANGE(command_id, texturing.texture2)) { | ||
| 128 | 129 | ||
| 129 | unsigned texture_index; | 130 | unsigned texture_index; |
| 130 | if (COMMAND_IN_RANGE(command_id, texture0)) { | 131 | if (COMMAND_IN_RANGE(command_id, texturing.texture0)) { |
| 131 | texture_index = 0; | 132 | texture_index = 0; |
| 132 | } else if (COMMAND_IN_RANGE(command_id, texture1)) { | 133 | } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) { |
| 133 | texture_index = 1; | 134 | texture_index = 1; |
| 134 | } else if (COMMAND_IN_RANGE(command_id, texture2)) { | 135 | } else if (COMMAND_IN_RANGE(command_id, texturing.texture2)) { |
| 135 | texture_index = 2; | 136 | texture_index = 2; |
| 136 | } else { | 137 | } else { |
| 137 | UNREACHABLE_MSG("Unknown texture command"); | 138 | UNREACHABLE_MSG("Unknown texture command"); |
| @@ -146,19 +147,20 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { | |||
| 146 | 147 | ||
| 147 | const unsigned int command_id = | 148 | const unsigned int command_id = |
| 148 | list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | 149 | list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); |
| 149 | if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || | 150 | if (COMMAND_IN_RANGE(command_id, texturing.texture0) || |
| 150 | COMMAND_IN_RANGE(command_id, texture2)) { | 151 | COMMAND_IN_RANGE(command_id, texturing.texture1) || |
| 152 | COMMAND_IN_RANGE(command_id, texturing.texture2)) { | ||
| 151 | 153 | ||
| 152 | unsigned texture_index; | 154 | unsigned texture_index; |
| 153 | if (COMMAND_IN_RANGE(command_id, texture0)) { | 155 | if (COMMAND_IN_RANGE(command_id, texturing.texture0)) { |
| 154 | texture_index = 0; | 156 | texture_index = 0; |
| 155 | } else if (COMMAND_IN_RANGE(command_id, texture1)) { | 157 | } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) { |
| 156 | texture_index = 1; | 158 | texture_index = 1; |
| 157 | } else { | 159 | } else { |
| 158 | texture_index = 2; | 160 | texture_index = 2; |
| 159 | } | 161 | } |
| 160 | 162 | ||
| 161 | const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; | 163 | const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index]; |
| 162 | const auto config = texture.config; | 164 | const auto config = texture.config; |
| 163 | const auto format = texture.format; | 165 | const auto format = texture.format; |
| 164 | 166 | ||
diff --git a/src/citra_qt/debugger/graphics/graphics_surface.cpp b/src/citra_qt/debugger/graphics/graphics_surface.cpp index bd82b00d4..f83c1f96c 100644 --- a/src/citra_qt/debugger/graphics/graphics_surface.cpp +++ b/src/citra_qt/debugger/graphics/graphics_surface.cpp | |||
| @@ -16,8 +16,8 @@ | |||
| 16 | #include "common/color.h" | 16 | #include "common/color.h" |
| 17 | #include "core/hw/gpu.h" | 17 | #include "core/hw/gpu.h" |
| 18 | #include "core/memory.h" | 18 | #include "core/memory.h" |
| 19 | #include "video_core/pica.h" | ||
| 20 | #include "video_core/pica_state.h" | 19 | #include "video_core/pica_state.h" |
| 20 | #include "video_core/regs.h" | ||
| 21 | #include "video_core/texture/texture_decode.h" | 21 | #include "video_core/texture/texture_decode.h" |
| 22 | #include "video_core/utils.h" | 22 | #include "video_core/utils.h" |
| 23 | 23 | ||
| @@ -414,30 +414,30 @@ void GraphicsSurfaceWidget::OnUpdate() { | |||
| 414 | // TODO: Store a reference to the registers in the debug context instead of accessing them | 414 | // TODO: Store a reference to the registers in the debug context instead of accessing them |
| 415 | // directly... | 415 | // directly... |
| 416 | 416 | ||
| 417 | const auto& framebuffer = Pica::g_state.regs.framebuffer; | 417 | const auto& framebuffer = Pica::g_state.regs.framebuffer.framebuffer; |
| 418 | 418 | ||
| 419 | surface_address = framebuffer.GetColorBufferPhysicalAddress(); | 419 | surface_address = framebuffer.GetColorBufferPhysicalAddress(); |
| 420 | surface_width = framebuffer.GetWidth(); | 420 | surface_width = framebuffer.GetWidth(); |
| 421 | surface_height = framebuffer.GetHeight(); | 421 | surface_height = framebuffer.GetHeight(); |
| 422 | 422 | ||
| 423 | switch (framebuffer.color_format) { | 423 | switch (framebuffer.color_format) { |
| 424 | case Pica::Regs::ColorFormat::RGBA8: | 424 | case Pica::FramebufferRegs::ColorFormat::RGBA8: |
| 425 | surface_format = Format::RGBA8; | 425 | surface_format = Format::RGBA8; |
| 426 | break; | 426 | break; |
| 427 | 427 | ||
| 428 | case Pica::Regs::ColorFormat::RGB8: | 428 | case Pica::FramebufferRegs::ColorFormat::RGB8: |
| 429 | surface_format = Format::RGB8; | 429 | surface_format = Format::RGB8; |
| 430 | break; | 430 | break; |
| 431 | 431 | ||
| 432 | case Pica::Regs::ColorFormat::RGB5A1: | 432 | case Pica::FramebufferRegs::ColorFormat::RGB5A1: |
| 433 | surface_format = Format::RGB5A1; | 433 | surface_format = Format::RGB5A1; |
| 434 | break; | 434 | break; |
| 435 | 435 | ||
| 436 | case Pica::Regs::ColorFormat::RGB565: | 436 | case Pica::FramebufferRegs::ColorFormat::RGB565: |
| 437 | surface_format = Format::RGB565; | 437 | surface_format = Format::RGB565; |
| 438 | break; | 438 | break; |
| 439 | 439 | ||
| 440 | case Pica::Regs::ColorFormat::RGBA4: | 440 | case Pica::FramebufferRegs::ColorFormat::RGBA4: |
| 441 | surface_format = Format::RGBA4; | 441 | surface_format = Format::RGBA4; |
| 442 | break; | 442 | break; |
| 443 | 443 | ||
| @@ -450,22 +450,22 @@ void GraphicsSurfaceWidget::OnUpdate() { | |||
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | case Source::DepthBuffer: { | 452 | case Source::DepthBuffer: { |
| 453 | const auto& framebuffer = Pica::g_state.regs.framebuffer; | 453 | const auto& framebuffer = Pica::g_state.regs.framebuffer.framebuffer; |
| 454 | 454 | ||
| 455 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); | 455 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); |
| 456 | surface_width = framebuffer.GetWidth(); | 456 | surface_width = framebuffer.GetWidth(); |
| 457 | surface_height = framebuffer.GetHeight(); | 457 | surface_height = framebuffer.GetHeight(); |
| 458 | 458 | ||
| 459 | switch (framebuffer.depth_format) { | 459 | switch (framebuffer.depth_format) { |
| 460 | case Pica::Regs::DepthFormat::D16: | 460 | case Pica::FramebufferRegs::DepthFormat::D16: |
| 461 | surface_format = Format::D16; | 461 | surface_format = Format::D16; |
| 462 | break; | 462 | break; |
| 463 | 463 | ||
| 464 | case Pica::Regs::DepthFormat::D24: | 464 | case Pica::FramebufferRegs::DepthFormat::D24: |
| 465 | surface_format = Format::D24; | 465 | surface_format = Format::D24; |
| 466 | break; | 466 | break; |
| 467 | 467 | ||
| 468 | case Pica::Regs::DepthFormat::D24S8: | 468 | case Pica::FramebufferRegs::DepthFormat::D24S8: |
| 469 | surface_format = Format::D24X8; | 469 | surface_format = Format::D24X8; |
| 470 | break; | 470 | break; |
| 471 | 471 | ||
| @@ -478,14 +478,14 @@ void GraphicsSurfaceWidget::OnUpdate() { | |||
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | case Source::StencilBuffer: { | 480 | case Source::StencilBuffer: { |
| 481 | const auto& framebuffer = Pica::g_state.regs.framebuffer; | 481 | const auto& framebuffer = Pica::g_state.regs.framebuffer.framebuffer; |
| 482 | 482 | ||
| 483 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); | 483 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); |
| 484 | surface_width = framebuffer.GetWidth(); | 484 | surface_width = framebuffer.GetWidth(); |
| 485 | surface_height = framebuffer.GetHeight(); | 485 | surface_height = framebuffer.GetHeight(); |
| 486 | 486 | ||
| 487 | switch (framebuffer.depth_format) { | 487 | switch (framebuffer.depth_format) { |
| 488 | case Pica::Regs::DepthFormat::D24S8: | 488 | case Pica::FramebufferRegs::DepthFormat::D24S8: |
| 489 | surface_format = Format::X24S8; | 489 | surface_format = Format::X24S8; |
| 490 | break; | 490 | break; |
| 491 | 491 | ||
| @@ -512,7 +512,7 @@ void GraphicsSurfaceWidget::OnUpdate() { | |||
| 512 | break; | 512 | break; |
| 513 | } | 513 | } |
| 514 | 514 | ||
| 515 | const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; | 515 | const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index]; |
| 516 | auto info = Pica::Texture::TextureInfo::FromPicaRegister(texture.config, texture.format); | 516 | auto info = Pica::Texture::TextureInfo::FromPicaRegister(texture.config, texture.format); |
| 517 | 517 | ||
| 518 | surface_address = info.physical_address; | 518 | surface_address = info.physical_address; |
| @@ -574,7 +574,7 @@ void GraphicsSurfaceWidget::OnUpdate() { | |||
| 574 | info.physical_address = surface_address; | 574 | info.physical_address = surface_address; |
| 575 | info.width = surface_width; | 575 | info.width = surface_width; |
| 576 | info.height = surface_height; | 576 | info.height = surface_height; |
| 577 | info.format = static_cast<Pica::Regs::TextureFormat>(surface_format); | 577 | info.format = static_cast<Pica::TexturingRegs::TextureFormat>(surface_format); |
| 578 | info.SetDefaultStride(); | 578 | info.SetDefaultStride(); |
| 579 | 579 | ||
| 580 | for (unsigned int y = 0; y < surface_height; ++y) { | 580 | for (unsigned int y = 0; y < surface_height; ++y) { |
| @@ -689,7 +689,8 @@ void GraphicsSurfaceWidget::SaveSurface() { | |||
| 689 | 689 | ||
| 690 | unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) { | 690 | unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) { |
| 691 | if (format <= Format::MaxTextureFormat) { | 691 | if (format <= Format::MaxTextureFormat) { |
| 692 | return Pica::Regs::NibblesPerPixel(static_cast<Pica::Regs::TextureFormat>(format)); | 692 | return Pica::TexturingRegs::NibblesPerPixel( |
| 693 | static_cast<Pica::TexturingRegs::TextureFormat>(format)); | ||
| 693 | } | 694 | } |
| 694 | 695 | ||
| 695 | switch (format) { | 696 | switch (format) { |
diff --git a/src/citra_qt/debugger/graphics/graphics_tracing.cpp b/src/citra_qt/debugger/graphics/graphics_tracing.cpp index 17f1c5ce2..40d5bed51 100644 --- a/src/citra_qt/debugger/graphics/graphics_tracing.cpp +++ b/src/citra_qt/debugger/graphics/graphics_tracing.cpp | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include "core/hw/lcd.h" | 18 | #include "core/hw/lcd.h" |
| 19 | #include "core/tracer/recorder.h" | 19 | #include "core/tracer/recorder.h" |
| 20 | #include "nihstro/float24.h" | 20 | #include "nihstro/float24.h" |
| 21 | #include "video_core/pica.h" | ||
| 22 | #include "video_core/pica_state.h" | 21 | #include "video_core/pica_state.h" |
| 23 | 22 | ||
| 24 | GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, | 23 | GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, |
diff --git a/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp index 489ec5f21..e3f3194db 100644 --- a/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp +++ b/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <QTreeView> | 16 | #include <QTreeView> |
| 17 | #include "citra_qt/debugger/graphics/graphics_vertex_shader.h" | 17 | #include "citra_qt/debugger/graphics/graphics_vertex_shader.h" |
| 18 | #include "citra_qt/util/util.h" | 18 | #include "citra_qt/util/util.h" |
| 19 | #include "video_core/pica.h" | ||
| 20 | #include "video_core/pica_state.h" | 19 | #include "video_core/pica_state.h" |
| 21 | #include "video_core/shader/debug_data.h" | 20 | #include "video_core/shader/debug_data.h" |
| 22 | #include "video_core/shader/shader.h" | 21 | #include "video_core/shader/shader.h" |
| @@ -359,7 +358,7 @@ void GraphicsVertexShaderWidget::DumpShader() { | |||
| 359 | auto& config = Pica::g_state.regs.vs; | 358 | auto& config = Pica::g_state.regs.vs; |
| 360 | 359 | ||
| 361 | Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, | 360 | Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, |
| 362 | Pica::g_state.regs.vs_output_attributes); | 361 | Pica::g_state.regs.rasterizer.vs_output_attributes); |
| 363 | } | 362 | } |
| 364 | 363 | ||
| 365 | GraphicsVertexShaderWidget::GraphicsVertexShaderWidget( | 364 | GraphicsVertexShaderWidget::GraphicsVertexShaderWidget( |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index ad984cd94..11bc61e14 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -5,6 +5,7 @@ set(SRCS | |||
| 5 | pica.cpp | 5 | pica.cpp |
| 6 | primitive_assembly.cpp | 6 | primitive_assembly.cpp |
| 7 | rasterizer.cpp | 7 | rasterizer.cpp |
| 8 | regs.cpp | ||
| 8 | renderer_base.cpp | 9 | renderer_base.cpp |
| 9 | renderer_opengl/gl_rasterizer.cpp | 10 | renderer_opengl/gl_rasterizer.cpp |
| 10 | renderer_opengl/gl_rasterizer_cache.cpp | 11 | renderer_opengl/gl_rasterizer_cache.cpp |
| @@ -32,6 +33,13 @@ set(HEADERS | |||
| 32 | primitive_assembly.h | 33 | primitive_assembly.h |
| 33 | rasterizer.h | 34 | rasterizer.h |
| 34 | rasterizer_interface.h | 35 | rasterizer_interface.h |
| 36 | regs.h | ||
| 37 | regs_framebuffer.h | ||
| 38 | regs_lighting.h | ||
| 39 | regs_pipeline.h | ||
| 40 | regs_rasterizer.h | ||
| 41 | regs_shader.h | ||
| 42 | regs_texturing.h | ||
| 35 | renderer_base.h | 43 | renderer_base.h |
| 36 | renderer_opengl/gl_rasterizer.h | 44 | renderer_opengl/gl_rasterizer.h |
| 37 | renderer_opengl/gl_rasterizer_cache.h | 45 | renderer_opengl/gl_rasterizer_cache.h |
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp index 0774ffc53..0f71bbd06 100644 --- a/src/video_core/clipper.cpp +++ b/src/video_core/clipper.cpp | |||
| @@ -12,10 +12,10 @@ | |||
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/vector_math.h" | 13 | #include "common/vector_math.h" |
| 14 | #include "video_core/clipper.h" | 14 | #include "video_core/clipper.h" |
| 15 | #include "video_core/pica.h" | ||
| 16 | #include "video_core/pica_state.h" | 15 | #include "video_core/pica_state.h" |
| 17 | #include "video_core/pica_types.h" | 16 | #include "video_core/pica_types.h" |
| 18 | #include "video_core/rasterizer.h" | 17 | #include "video_core/rasterizer.h" |
| 18 | #include "video_core/regs.h" | ||
| 19 | #include "video_core/shader/shader.h" | 19 | #include "video_core/shader/shader.h" |
| 20 | 20 | ||
| 21 | using Pica::Rasterizer::Vertex; | 21 | using Pica::Rasterizer::Vertex; |
| @@ -64,10 +64,10 @@ static void InitScreenCoordinates(Vertex& vtx) { | |||
| 64 | } viewport; | 64 | } viewport; |
| 65 | 65 | ||
| 66 | const auto& regs = g_state.regs; | 66 | const auto& regs = g_state.regs; |
| 67 | viewport.halfsize_x = float24::FromRaw(regs.viewport_size_x); | 67 | viewport.halfsize_x = float24::FromRaw(regs.rasterizer.viewport_size_x); |
| 68 | viewport.halfsize_y = float24::FromRaw(regs.viewport_size_y); | 68 | viewport.halfsize_y = float24::FromRaw(regs.rasterizer.viewport_size_y); |
| 69 | viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.viewport_corner.x)); | 69 | viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.rasterizer.viewport_corner.x)); |
| 70 | viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.viewport_corner.y)); | 70 | viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.rasterizer.viewport_corner.y)); |
| 71 | 71 | ||
| 72 | float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; | 72 | float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; |
| 73 | vtx.color *= inv_w; | 73 | vtx.color *= inv_w; |
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 4955ff9f9..91c0ca4e6 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp | |||
| @@ -16,11 +16,11 @@ | |||
| 16 | #include "core/tracer/recorder.h" | 16 | #include "core/tracer/recorder.h" |
| 17 | #include "video_core/command_processor.h" | 17 | #include "video_core/command_processor.h" |
| 18 | #include "video_core/debug_utils/debug_utils.h" | 18 | #include "video_core/debug_utils/debug_utils.h" |
| 19 | #include "video_core/pica.h" | ||
| 20 | #include "video_core/pica_state.h" | 19 | #include "video_core/pica_state.h" |
| 21 | #include "video_core/pica_types.h" | 20 | #include "video_core/pica_types.h" |
| 22 | #include "video_core/primitive_assembly.h" | 21 | #include "video_core/primitive_assembly.h" |
| 23 | #include "video_core/rasterizer_interface.h" | 22 | #include "video_core/rasterizer_interface.h" |
| 23 | #include "video_core/regs.h" | ||
| 24 | #include "video_core/renderer_base.h" | 24 | #include "video_core/renderer_base.h" |
| 25 | #include "video_core/shader/shader.h" | 25 | #include "video_core/shader/shader.h" |
| 26 | #include "video_core/vertex_loader.h" | 26 | #include "video_core/vertex_loader.h" |
| @@ -74,23 +74,23 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 74 | Service::GSP::SignalInterrupt(Service::GSP::InterruptId::P3D); | 74 | Service::GSP::SignalInterrupt(Service::GSP::InterruptId::P3D); |
| 75 | break; | 75 | break; |
| 76 | 76 | ||
| 77 | case PICA_REG_INDEX_WORKAROUND(triangle_topology, 0x25E): | 77 | case PICA_REG_INDEX(pipeline.triangle_topology): |
| 78 | g_state.primitive_assembler.Reconfigure(regs.triangle_topology); | 78 | g_state.primitive_assembler.Reconfigure(regs.pipeline.triangle_topology); |
| 79 | break; | 79 | break; |
| 80 | 80 | ||
| 81 | case PICA_REG_INDEX_WORKAROUND(restart_primitive, 0x25F): | 81 | case PICA_REG_INDEX(pipeline.restart_primitive): |
| 82 | g_state.primitive_assembler.Reset(); | 82 | g_state.primitive_assembler.Reset(); |
| 83 | break; | 83 | break; |
| 84 | 84 | ||
| 85 | case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.index, 0x232): | 85 | case PICA_REG_INDEX(pipeline.vs_default_attributes_setup.index): |
| 86 | g_state.immediate.current_attribute = 0; | 86 | g_state.immediate.current_attribute = 0; |
| 87 | default_attr_counter = 0; | 87 | default_attr_counter = 0; |
| 88 | break; | 88 | break; |
| 89 | 89 | ||
| 90 | // Load default vertex input attributes | 90 | // Load default vertex input attributes |
| 91 | case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[0], 0x233): | 91 | case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[0], 0x233): |
| 92 | case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[1], 0x234): | 92 | case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[1], 0x234): |
| 93 | case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[2], 0x235): { | 93 | case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[2], 0x235): { |
| 94 | // TODO: Does actual hardware indeed keep an intermediate buffer or does | 94 | // TODO: Does actual hardware indeed keep an intermediate buffer or does |
| 95 | // it directly write the values? | 95 | // it directly write the values? |
| 96 | default_attr_write_buffer[default_attr_counter++] = value; | 96 | default_attr_write_buffer[default_attr_counter++] = value; |
| @@ -102,7 +102,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 102 | if (default_attr_counter >= 3) { | 102 | if (default_attr_counter >= 3) { |
| 103 | default_attr_counter = 0; | 103 | default_attr_counter = 0; |
| 104 | 104 | ||
| 105 | auto& setup = regs.vs_default_attributes_setup; | 105 | auto& setup = regs.pipeline.vs_default_attributes_setup; |
| 106 | 106 | ||
| 107 | if (setup.index >= 16) { | 107 | if (setup.index >= 16) { |
| 108 | LOG_ERROR(HW_GPU, "Invalid VS default attribute index %d", (int)setup.index); | 108 | LOG_ERROR(HW_GPU, "Invalid VS default attribute index %d", (int)setup.index); |
| @@ -137,7 +137,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 137 | 137 | ||
| 138 | immediate_input.attr[immediate_attribute_id] = attribute; | 138 | immediate_input.attr[immediate_attribute_id] = attribute; |
| 139 | 139 | ||
| 140 | if (immediate_attribute_id < regs.max_input_attrib_index) { | 140 | if (immediate_attribute_id < regs.pipeline.max_input_attrib_index) { |
| 141 | immediate_attribute_id += 1; | 141 | immediate_attribute_id += 1; |
| 142 | } else { | 142 | } else { |
| 143 | MICROPROFILE_SCOPE(GPU_Drawing); | 143 | MICROPROFILE_SCOPE(GPU_Drawing); |
| @@ -165,15 +165,16 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 165 | }; | 165 | }; |
| 166 | 166 | ||
| 167 | g_state.primitive_assembler.SubmitVertex( | 167 | g_state.primitive_assembler.SubmitVertex( |
| 168 | Shader::OutputVertex::FromAttributeBuffer(regs, output), AddTriangle); | 168 | Shader::OutputVertex::FromAttributeBuffer(regs.rasterizer, output), |
| 169 | AddTriangle); | ||
| 169 | } | 170 | } |
| 170 | } | 171 | } |
| 171 | } | 172 | } |
| 172 | break; | 173 | break; |
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | case PICA_REG_INDEX(gpu_mode): | 176 | case PICA_REG_INDEX(pipeline.gpu_mode): |
| 176 | if (regs.gpu_mode == Regs::GPUMode::Configuring) { | 177 | if (regs.pipeline.gpu_mode == PipelineRegs::GPUMode::Configuring) { |
| 177 | MICROPROFILE_SCOPE(GPU_Drawing); | 178 | MICROPROFILE_SCOPE(GPU_Drawing); |
| 178 | 179 | ||
| 179 | // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring | 180 | // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring |
| @@ -185,19 +186,20 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 185 | } | 186 | } |
| 186 | break; | 187 | break; |
| 187 | 188 | ||
| 188 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c): | 189 | case PICA_REG_INDEX_WORKAROUND(pipeline.command_buffer.trigger[0], 0x23c): |
| 189 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d): { | 190 | case PICA_REG_INDEX_WORKAROUND(pipeline.command_buffer.trigger[1], 0x23d): { |
| 190 | unsigned index = static_cast<unsigned>(id - PICA_REG_INDEX(command_buffer.trigger[0])); | 191 | unsigned index = |
| 191 | u32* head_ptr = | 192 | static_cast<unsigned>(id - PICA_REG_INDEX(pipeline.command_buffer.trigger[0])); |
| 192 | (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index)); | 193 | u32* head_ptr = (u32*)Memory::GetPhysicalPointer( |
| 194 | regs.pipeline.command_buffer.GetPhysicalAddress(index)); | ||
| 193 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; | 195 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; |
| 194 | g_state.cmd_list.length = regs.command_buffer.GetSize(index) / sizeof(u32); | 196 | g_state.cmd_list.length = regs.pipeline.command_buffer.GetSize(index) / sizeof(u32); |
| 195 | break; | 197 | break; |
| 196 | } | 198 | } |
| 197 | 199 | ||
| 198 | // It seems like these trigger vertex rendering | 200 | // It seems like these trigger vertex rendering |
| 199 | case PICA_REG_INDEX(trigger_draw): | 201 | case PICA_REG_INDEX(pipeline.trigger_draw): |
| 200 | case PICA_REG_INDEX(trigger_draw_indexed): { | 202 | case PICA_REG_INDEX(pipeline.trigger_draw_indexed): { |
| 201 | MICROPROFILE_SCOPE(GPU_Drawing); | 203 | MICROPROFILE_SCOPE(GPU_Drawing); |
| 202 | 204 | ||
| 203 | #if PICA_LOG_TEV | 205 | #if PICA_LOG_TEV |
| @@ -209,13 +211,13 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 209 | // Processes information about internal vertex attributes to figure out how a vertex is | 211 | // Processes information about internal vertex attributes to figure out how a vertex is |
| 210 | // loaded. | 212 | // loaded. |
| 211 | // Later, these can be compiled and cached. | 213 | // Later, these can be compiled and cached. |
| 212 | const u32 base_address = regs.vertex_attributes.GetPhysicalBaseAddress(); | 214 | const u32 base_address = regs.pipeline.vertex_attributes.GetPhysicalBaseAddress(); |
| 213 | VertexLoader loader(regs); | 215 | VertexLoader loader(regs.pipeline); |
| 214 | 216 | ||
| 215 | // Load vertices | 217 | // Load vertices |
| 216 | bool is_indexed = (id == PICA_REG_INDEX(trigger_draw_indexed)); | 218 | bool is_indexed = (id == PICA_REG_INDEX(pipeline.trigger_draw_indexed)); |
| 217 | 219 | ||
| 218 | const auto& index_info = regs.index_array; | 220 | const auto& index_info = regs.pipeline.index_array; |
| 219 | const u8* index_address_8 = Memory::GetPhysicalPointer(base_address + index_info.offset); | 221 | const u8* index_address_8 = Memory::GetPhysicalPointer(base_address + index_info.offset); |
| 220 | const u16* index_address_16 = reinterpret_cast<const u16*>(index_address_8); | 222 | const u16* index_address_16 = reinterpret_cast<const u16*>(index_address_8); |
| 221 | bool index_u16 = index_info.format != 0; | 223 | bool index_u16 = index_info.format != 0; |
| @@ -224,13 +226,13 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 224 | 226 | ||
| 225 | if (g_debug_context && g_debug_context->recorder) { | 227 | if (g_debug_context && g_debug_context->recorder) { |
| 226 | for (int i = 0; i < 3; ++i) { | 228 | for (int i = 0; i < 3; ++i) { |
| 227 | const auto texture = regs.GetTextures()[i]; | 229 | const auto texture = regs.texturing.GetTextures()[i]; |
| 228 | if (!texture.enabled) | 230 | if (!texture.enabled) |
| 229 | continue; | 231 | continue; |
| 230 | 232 | ||
| 231 | u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); | 233 | u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); |
| 232 | g_debug_context->recorder->MemoryAccessed( | 234 | g_debug_context->recorder->MemoryAccessed( |
| 233 | texture_data, Pica::Regs::NibblesPerPixel(texture.format) * | 235 | texture_data, Pica::TexturingRegs::NibblesPerPixel(texture.format) * |
| 234 | texture.config.width / 2 * texture.config.height, | 236 | texture.config.width / 2 * texture.config.height, |
| 235 | texture.config.GetPhysicalAddress()); | 237 | texture.config.GetPhysicalAddress()); |
| 236 | } | 238 | } |
| @@ -253,11 +255,11 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 253 | 255 | ||
| 254 | shader_engine->SetupBatch(g_state.vs, regs.vs.main_offset); | 256 | shader_engine->SetupBatch(g_state.vs, regs.vs.main_offset); |
| 255 | 257 | ||
| 256 | for (unsigned int index = 0; index < regs.num_vertices; ++index) { | 258 | for (unsigned int index = 0; index < regs.pipeline.num_vertices; ++index) { |
| 257 | // Indexed rendering doesn't use the start offset | 259 | // Indexed rendering doesn't use the start offset |
| 258 | unsigned int vertex = | 260 | unsigned int vertex = |
| 259 | is_indexed ? (index_u16 ? index_address_16[index] : index_address_8[index]) | 261 | is_indexed ? (index_u16 ? index_address_16[index] : index_address_8[index]) |
| 260 | : (index + regs.vertex_offset); | 262 | : (index + regs.pipeline.vertex_offset); |
| 261 | 263 | ||
| 262 | // -1 is a common special value used for primitive restart. Since it's unknown if | 264 | // -1 is a common special value used for primitive restart. Since it's unknown if |
| 263 | // the PICA supports it, and it would mess up the caching, guard against it here. | 265 | // the PICA supports it, and it would mess up the caching, guard against it here. |
| @@ -295,7 +297,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 295 | shader_unit.WriteOutput(regs.vs, output); | 297 | shader_unit.WriteOutput(regs.vs, output); |
| 296 | 298 | ||
| 297 | // Retrieve vertex from register data | 299 | // Retrieve vertex from register data |
| 298 | output_vertex = Shader::OutputVertex::FromAttributeBuffer(regs, output); | 300 | output_vertex = Shader::OutputVertex::FromAttributeBuffer(regs.rasterizer, output); |
| 299 | 301 | ||
| 300 | if (is_indexed) { | 302 | if (is_indexed) { |
| 301 | vertex_cache[vertex_cache_pos] = output_vertex; | 303 | vertex_cache[vertex_cache_pos] = output_vertex; |
| @@ -437,16 +439,16 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 437 | break; | 439 | break; |
| 438 | } | 440 | } |
| 439 | 441 | ||
| 440 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8): | 442 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8): |
| 441 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9): | 443 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9): |
| 442 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea): | 444 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea): |
| 443 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb): | 445 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb): |
| 444 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec): | 446 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec): |
| 445 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed): | 447 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed): |
| 446 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee): | 448 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee): |
| 447 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef): { | 449 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef): { |
| 448 | g_state.fog.lut[regs.fog_lut_offset % 128].raw = value; | 450 | g_state.fog.lut[regs.texturing.fog_lut_offset % 128].raw = value; |
| 449 | regs.fog_lut_offset.Assign(regs.fog_lut_offset + 1); | 451 | regs.texturing.fog_lut_offset.Assign(regs.texturing.fog_lut_offset + 1); |
| 450 | break; | 452 | break; |
| 451 | } | 453 | } |
| 452 | 454 | ||
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 2d40f7d4f..e164e83a1 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp | |||
| @@ -29,10 +29,10 @@ | |||
| 29 | #include "common/math_util.h" | 29 | #include "common/math_util.h" |
| 30 | #include "common/vector_math.h" | 30 | #include "common/vector_math.h" |
| 31 | #include "video_core/debug_utils/debug_utils.h" | 31 | #include "video_core/debug_utils/debug_utils.h" |
| 32 | #include "video_core/pica.h" | ||
| 33 | #include "video_core/pica_state.h" | 32 | #include "video_core/pica_state.h" |
| 34 | #include "video_core/pica_types.h" | 33 | #include "video_core/pica_types.h" |
| 35 | #include "video_core/rasterizer_interface.h" | 34 | #include "video_core/rasterizer_interface.h" |
| 35 | #include "video_core/regs.h" | ||
| 36 | #include "video_core/renderer_base.h" | 36 | #include "video_core/renderer_base.h" |
| 37 | #include "video_core/shader/shader.h" | 37 | #include "video_core/shader/shader.h" |
| 38 | #include "video_core/texture/texture_decode.h" | 38 | #include "video_core/texture/texture_decode.h" |
| @@ -88,9 +88,9 @@ std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this global | |||
| 88 | 88 | ||
| 89 | namespace DebugUtils { | 89 | namespace DebugUtils { |
| 90 | 90 | ||
| 91 | void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, | 91 | void DumpShader(const std::string& filename, const ShaderRegs& config, |
| 92 | const Shader::ShaderSetup& setup, | 92 | const Shader::ShaderSetup& setup, |
| 93 | const Regs::VSOutputAttributes* output_attributes) { | 93 | const RasterizerRegs::VSOutputAttributes* output_attributes) { |
| 94 | struct StuffToWrite { | 94 | struct StuffToWrite { |
| 95 | const u8* pointer; | 95 | const u8* pointer; |
| 96 | u32 size; | 96 | u32 size; |
| @@ -129,7 +129,7 @@ void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, | |||
| 129 | // This is put into a try-catch block to make sure we notice unknown configurations. | 129 | // This is put into a try-catch block to make sure we notice unknown configurations. |
| 130 | std::vector<OutputRegisterInfo> output_info_table; | 130 | std::vector<OutputRegisterInfo> output_info_table; |
| 131 | for (unsigned i = 0; i < 7; ++i) { | 131 | for (unsigned i = 0; i < 7; ++i) { |
| 132 | using OutputAttributes = Pica::Regs::VSOutputAttributes; | 132 | using OutputAttributes = Pica::RasterizerRegs::VSOutputAttributes; |
| 133 | 133 | ||
| 134 | // TODO: It's still unclear how the attribute components map to the register! | 134 | // TODO: It's still unclear how the attribute components map to the register! |
| 135 | // Once we know that, this code probably will not make much sense anymore. | 135 | // Once we know that, this code probably will not make much sense anymore. |
| @@ -331,7 +331,7 @@ static void FlushIOFile(png_structp png_ptr) { | |||
| 331 | } | 331 | } |
| 332 | #endif | 332 | #endif |
| 333 | 333 | ||
| 334 | void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { | 334 | void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data) { |
| 335 | #ifndef HAVE_PNG | 335 | #ifndef HAVE_PNG |
| 336 | return; | 336 | return; |
| 337 | #else | 337 | #else |
| @@ -396,7 +396,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { | |||
| 396 | info.width = texture_config.width; | 396 | info.width = texture_config.width; |
| 397 | info.height = texture_config.height; | 397 | info.height = texture_config.height; |
| 398 | info.stride = row_stride; | 398 | info.stride = row_stride; |
| 399 | info.format = g_state.regs.texture0_format; | 399 | info.format = g_state.regs.texturing.texture0_format; |
| 400 | Math::Vec4<u8> texture_color = Pica::Texture::LookupTexture(data, x, y, info); | 400 | Math::Vec4<u8> texture_color = Pica::Texture::LookupTexture(data, x, y, info); |
| 401 | buf[3 * x + y * row_stride] = texture_color.r(); | 401 | buf[3 * x + y * row_stride] = texture_color.r(); |
| 402 | buf[3 * x + y * row_stride + 1] = texture_color.g(); | 402 | buf[3 * x + y * row_stride + 1] = texture_color.g(); |
| @@ -434,8 +434,10 @@ static std::string ReplacePattern(const std::string& input, const std::string& p | |||
| 434 | return ret; | 434 | return ret; |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfig::Source& source) { | 437 | static std::string GetTevStageConfigSourceString( |
| 438 | using Source = Pica::Regs::TevStageConfig::Source; | 438 | const TexturingRegs::TevStageConfig::Source& source) { |
| 439 | |||
| 440 | using Source = TexturingRegs::TevStageConfig::Source; | ||
| 439 | static const std::map<Source, std::string> source_map = { | 441 | static const std::map<Source, std::string> source_map = { |
| 440 | {Source::PrimaryColor, "PrimaryColor"}, | 442 | {Source::PrimaryColor, "PrimaryColor"}, |
| 441 | {Source::PrimaryFragmentColor, "PrimaryFragmentColor"}, | 443 | {Source::PrimaryFragmentColor, "PrimaryFragmentColor"}, |
| @@ -457,9 +459,10 @@ static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfi | |||
| 457 | } | 459 | } |
| 458 | 460 | ||
| 459 | static std::string GetTevStageConfigColorSourceString( | 461 | static std::string GetTevStageConfigColorSourceString( |
| 460 | const Pica::Regs::TevStageConfig::Source& source, | 462 | const TexturingRegs::TevStageConfig::Source& source, |
| 461 | const Pica::Regs::TevStageConfig::ColorModifier modifier) { | 463 | const TexturingRegs::TevStageConfig::ColorModifier modifier) { |
| 462 | using ColorModifier = Pica::Regs::TevStageConfig::ColorModifier; | 464 | |
| 465 | using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier; | ||
| 463 | static const std::map<ColorModifier, std::string> color_modifier_map = { | 466 | static const std::map<ColorModifier, std::string> color_modifier_map = { |
| 464 | {ColorModifier::SourceColor, "%source.rgb"}, | 467 | {ColorModifier::SourceColor, "%source.rgb"}, |
| 465 | {ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"}, | 468 | {ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"}, |
| @@ -483,9 +486,10 @@ static std::string GetTevStageConfigColorSourceString( | |||
| 483 | } | 486 | } |
| 484 | 487 | ||
| 485 | static std::string GetTevStageConfigAlphaSourceString( | 488 | static std::string GetTevStageConfigAlphaSourceString( |
| 486 | const Pica::Regs::TevStageConfig::Source& source, | 489 | const TexturingRegs::TevStageConfig::Source& source, |
| 487 | const Pica::Regs::TevStageConfig::AlphaModifier modifier) { | 490 | const TexturingRegs::TevStageConfig::AlphaModifier modifier) { |
| 488 | using AlphaModifier = Pica::Regs::TevStageConfig::AlphaModifier; | 491 | |
| 492 | using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier; | ||
| 489 | static const std::map<AlphaModifier, std::string> alpha_modifier_map = { | 493 | static const std::map<AlphaModifier, std::string> alpha_modifier_map = { |
| 490 | {AlphaModifier::SourceAlpha, "%source.a"}, | 494 | {AlphaModifier::SourceAlpha, "%source.a"}, |
| 491 | {AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"}, | 495 | {AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"}, |
| @@ -507,8 +511,9 @@ static std::string GetTevStageConfigAlphaSourceString( | |||
| 507 | } | 511 | } |
| 508 | 512 | ||
| 509 | static std::string GetTevStageConfigOperationString( | 513 | static std::string GetTevStageConfigOperationString( |
| 510 | const Pica::Regs::TevStageConfig::Operation& operation) { | 514 | const TexturingRegs::TevStageConfig::Operation& operation) { |
| 511 | using Operation = Pica::Regs::TevStageConfig::Operation; | 515 | |
| 516 | using Operation = TexturingRegs::TevStageConfig::Operation; | ||
| 512 | static const std::map<Operation, std::string> combiner_map = { | 517 | static const std::map<Operation, std::string> combiner_map = { |
| 513 | {Operation::Replace, "%source1"}, | 518 | {Operation::Replace, "%source1"}, |
| 514 | {Operation::Modulate, "(%source1 * %source2)"}, | 519 | {Operation::Modulate, "(%source1 * %source2)"}, |
| @@ -528,7 +533,7 @@ static std::string GetTevStageConfigOperationString( | |||
| 528 | return op_it->second; | 533 | return op_it->second; |
| 529 | } | 534 | } |
| 530 | 535 | ||
| 531 | std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage) { | 536 | std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage) { |
| 532 | auto op_str = GetTevStageConfigOperationString(tev_stage.color_op); | 537 | auto op_str = GetTevStageConfigOperationString(tev_stage.color_op); |
| 533 | op_str = ReplacePattern( | 538 | op_str = ReplacePattern( |
| 534 | op_str, "%source1", | 539 | op_str, "%source1", |
| @@ -541,7 +546,7 @@ std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfi | |||
| 541 | GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3)); | 546 | GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3)); |
| 542 | } | 547 | } |
| 543 | 548 | ||
| 544 | std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage) { | 549 | std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage) { |
| 545 | auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op); | 550 | auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op); |
| 546 | op_str = ReplacePattern( | 551 | op_str = ReplacePattern( |
| 547 | op_str, "%source1", | 552 | op_str, "%source1", |
| @@ -554,7 +559,7 @@ std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfi | |||
| 554 | GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3)); | 559 | GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3)); |
| 555 | } | 560 | } |
| 556 | 561 | ||
| 557 | void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig, 6>& stages) { | 562 | void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages) { |
| 558 | std::string stage_info = "Tev setup:\n"; | 563 | std::string stage_info = "Tev setup:\n"; |
| 559 | for (size_t index = 0; index < stages.size(); ++index) { | 564 | for (size_t index = 0; index < stages.size(); ++index) { |
| 560 | const auto& tev_stage = stages[index]; | 565 | const auto& tev_stage = stages[index]; |
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h index 938a2e1b5..fd94bdbb8 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include <vector> | 17 | #include <vector> |
| 18 | #include "common/common_types.h" | 18 | #include "common/common_types.h" |
| 19 | #include "common/vector_math.h" | 19 | #include "common/vector_math.h" |
| 20 | #include "video_core/pica.h" | 20 | #include "video_core/regs.h" |
| 21 | 21 | ||
| 22 | namespace CiTrace { | 22 | namespace CiTrace { |
| 23 | class Recorder; | 23 | class Recorder; |
| @@ -182,9 +182,9 @@ namespace DebugUtils { | |||
| 182 | #define PICA_DUMP_TEXTURES 0 | 182 | #define PICA_DUMP_TEXTURES 0 |
| 183 | #define PICA_LOG_TEV 0 | 183 | #define PICA_LOG_TEV 0 |
| 184 | 184 | ||
| 185 | void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, | 185 | void DumpShader(const std::string& filename, const ShaderRegs& config, |
| 186 | const Shader::ShaderSetup& setup, | 186 | const Shader::ShaderSetup& setup, |
| 187 | const Regs::VSOutputAttributes* output_attributes); | 187 | const RasterizerRegs::VSOutputAttributes* output_attributes); |
| 188 | 188 | ||
| 189 | // Utility class to log Pica commands. | 189 | // Utility class to log Pica commands. |
| 190 | struct PicaTrace { | 190 | struct PicaTrace { |
| @@ -205,13 +205,13 @@ inline bool IsPicaTracing() { | |||
| 205 | void OnPicaRegWrite(PicaTrace::Write write); | 205 | void OnPicaRegWrite(PicaTrace::Write write); |
| 206 | std::unique_ptr<PicaTrace> FinishPicaTracing(); | 206 | std::unique_ptr<PicaTrace> FinishPicaTracing(); |
| 207 | 207 | ||
| 208 | void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data); | 208 | void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data); |
| 209 | 209 | ||
| 210 | std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage); | 210 | std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage); |
| 211 | std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage); | 211 | std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage); |
| 212 | 212 | ||
| 213 | /// Dumps the Tev stage config to log at trace level | 213 | /// Dumps the Tev stage config to log at trace level |
| 214 | void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig, 6>& stages); | 214 | void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages); |
| 215 | 215 | ||
| 216 | /** | 216 | /** |
| 217 | * Used in the vertex loader to merge access records. TODO: Investigate if actually useful. | 217 | * Used in the vertex loader to merge access records. TODO: Investigate if actually useful. |
diff --git a/src/video_core/pica.cpp b/src/video_core/pica.cpp index b4a77c632..13f0a4ab9 100644 --- a/src/video_core/pica.cpp +++ b/src/video_core/pica.cpp | |||
| @@ -3,497 +3,14 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <iterator> | ||
| 7 | #include <unordered_map> | ||
| 8 | #include <utility> | ||
| 9 | #include "video_core/pica.h" | 6 | #include "video_core/pica.h" |
| 10 | #include "video_core/pica_state.h" | 7 | #include "video_core/pica_state.h" |
| 11 | #include "video_core/primitive_assembly.h" | 8 | #include "video_core/regs.h" |
| 12 | #include "video_core/shader/shader.h" | ||
| 13 | 9 | ||
| 14 | namespace Pica { | 10 | namespace Pica { |
| 15 | 11 | ||
| 16 | State g_state; | 12 | State g_state; |
| 17 | 13 | ||
| 18 | static const std::pair<u16, const char*> register_names[] = { | ||
| 19 | {0x010, "GPUREG_FINALIZE"}, | ||
| 20 | |||
| 21 | {0x040, "GPUREG_FACECULLING_CONFIG"}, | ||
| 22 | {0x041, "GPUREG_VIEWPORT_WIDTH"}, | ||
| 23 | {0x042, "GPUREG_VIEWPORT_INVW"}, | ||
| 24 | {0x043, "GPUREG_VIEWPORT_HEIGHT"}, | ||
| 25 | {0x044, "GPUREG_VIEWPORT_INVH"}, | ||
| 26 | |||
| 27 | {0x047, "GPUREG_FRAGOP_CLIP"}, | ||
| 28 | {0x048, "GPUREG_FRAGOP_CLIP_DATA0"}, | ||
| 29 | {0x049, "GPUREG_FRAGOP_CLIP_DATA1"}, | ||
| 30 | {0x04A, "GPUREG_FRAGOP_CLIP_DATA2"}, | ||
| 31 | {0x04B, "GPUREG_FRAGOP_CLIP_DATA3"}, | ||
| 32 | |||
| 33 | {0x04D, "GPUREG_DEPTHMAP_SCALE"}, | ||
| 34 | {0x04E, "GPUREG_DEPTHMAP_OFFSET"}, | ||
| 35 | {0x04F, "GPUREG_SH_OUTMAP_TOTAL"}, | ||
| 36 | {0x050, "GPUREG_SH_OUTMAP_O0"}, | ||
| 37 | {0x051, "GPUREG_SH_OUTMAP_O1"}, | ||
| 38 | {0x052, "GPUREG_SH_OUTMAP_O2"}, | ||
| 39 | {0x053, "GPUREG_SH_OUTMAP_O3"}, | ||
| 40 | {0x054, "GPUREG_SH_OUTMAP_O4"}, | ||
| 41 | {0x055, "GPUREG_SH_OUTMAP_O5"}, | ||
| 42 | {0x056, "GPUREG_SH_OUTMAP_O6"}, | ||
| 43 | |||
| 44 | {0x061, "GPUREG_EARLYDEPTH_FUNC"}, | ||
| 45 | {0x062, "GPUREG_EARLYDEPTH_TEST1"}, | ||
| 46 | {0x063, "GPUREG_EARLYDEPTH_CLEAR"}, | ||
| 47 | {0x064, "GPUREG_SH_OUTATTR_MODE"}, | ||
| 48 | {0x065, "GPUREG_SCISSORTEST_MODE"}, | ||
| 49 | {0x066, "GPUREG_SCISSORTEST_POS"}, | ||
| 50 | {0x067, "GPUREG_SCISSORTEST_DIM"}, | ||
| 51 | {0x068, "GPUREG_VIEWPORT_XY"}, | ||
| 52 | |||
| 53 | {0x06A, "GPUREG_EARLYDEPTH_DATA"}, | ||
| 54 | |||
| 55 | {0x06D, "GPUREG_DEPTHMAP_ENABLE"}, | ||
| 56 | {0x06E, "GPUREG_RENDERBUF_DIM"}, | ||
| 57 | {0x06F, "GPUREG_SH_OUTATTR_CLOCK"}, | ||
| 58 | |||
| 59 | {0x080, "GPUREG_TEXUNIT_CONFIG"}, | ||
| 60 | {0x081, "GPUREG_TEXUNIT0_BORDER_COLOR"}, | ||
| 61 | {0x082, "GPUREG_TEXUNIT0_DIM"}, | ||
| 62 | {0x083, "GPUREG_TEXUNIT0_PARAM"}, | ||
| 63 | {0x084, "GPUREG_TEXUNIT0_LOD"}, | ||
| 64 | {0x085, "GPUREG_TEXUNIT0_ADDR1"}, | ||
| 65 | {0x086, "GPUREG_TEXUNIT0_ADDR2"}, | ||
| 66 | {0x087, "GPUREG_TEXUNIT0_ADDR3"}, | ||
| 67 | {0x088, "GPUREG_TEXUNIT0_ADDR4"}, | ||
| 68 | {0x089, "GPUREG_TEXUNIT0_ADDR5"}, | ||
| 69 | {0x08A, "GPUREG_TEXUNIT0_ADDR6"}, | ||
| 70 | {0x08B, "GPUREG_TEXUNIT0_SHADOW"}, | ||
| 71 | |||
| 72 | {0x08E, "GPUREG_TEXUNIT0_TYPE"}, | ||
| 73 | {0x08F, "GPUREG_LIGHTING_ENABLE0"}, | ||
| 74 | |||
| 75 | {0x091, "GPUREG_TEXUNIT1_BORDER_COLOR"}, | ||
| 76 | {0x092, "GPUREG_TEXUNIT1_DIM"}, | ||
| 77 | {0x093, "GPUREG_TEXUNIT1_PARAM"}, | ||
| 78 | {0x094, "GPUREG_TEXUNIT1_LOD"}, | ||
| 79 | {0x095, "GPUREG_TEXUNIT1_ADDR"}, | ||
| 80 | {0x096, "GPUREG_TEXUNIT1_TYPE"}, | ||
| 81 | |||
| 82 | {0x099, "GPUREG_TEXUNIT2_BORDER_COLOR"}, | ||
| 83 | {0x09A, "GPUREG_TEXUNIT2_DIM"}, | ||
| 84 | {0x09B, "GPUREG_TEXUNIT2_PARAM"}, | ||
| 85 | {0x09C, "GPUREG_TEXUNIT2_LOD"}, | ||
| 86 | {0x09D, "GPUREG_TEXUNIT2_ADDR"}, | ||
| 87 | {0x09E, "GPUREG_TEXUNIT2_TYPE"}, | ||
| 88 | |||
| 89 | {0x0A8, "GPUREG_TEXUNIT3_PROCTEX0"}, | ||
| 90 | {0x0A9, "GPUREG_TEXUNIT3_PROCTEX1"}, | ||
| 91 | {0x0AA, "GPUREG_TEXUNIT3_PROCTEX2"}, | ||
| 92 | {0x0AB, "GPUREG_TEXUNIT3_PROCTEX3"}, | ||
| 93 | {0x0AC, "GPUREG_TEXUNIT3_PROCTEX4"}, | ||
| 94 | {0x0AD, "GPUREG_TEXUNIT3_PROCTEX5"}, | ||
| 95 | |||
| 96 | {0x0AF, "GPUREG_PROCTEX_LUT"}, | ||
| 97 | {0x0B0, "GPUREG_PROCTEX_LUT_DATA0"}, | ||
| 98 | {0x0B1, "GPUREG_PROCTEX_LUT_DATA1"}, | ||
| 99 | {0x0B2, "GPUREG_PROCTEX_LUT_DATA2"}, | ||
| 100 | {0x0B3, "GPUREG_PROCTEX_LUT_DATA3"}, | ||
| 101 | {0x0B4, "GPUREG_PROCTEX_LUT_DATA4"}, | ||
| 102 | {0x0B5, "GPUREG_PROCTEX_LUT_DATA5"}, | ||
| 103 | {0x0B6, "GPUREG_PROCTEX_LUT_DATA6"}, | ||
| 104 | {0x0B7, "GPUREG_PROCTEX_LUT_DATA7"}, | ||
| 105 | |||
| 106 | {0x0C0, "GPUREG_TEXENV0_SOURCE"}, | ||
| 107 | {0x0C1, "GPUREG_TEXENV0_OPERAND"}, | ||
| 108 | {0x0C2, "GPUREG_TEXENV0_COMBINER"}, | ||
| 109 | {0x0C3, "GPUREG_TEXENV0_COLOR"}, | ||
| 110 | {0x0C4, "GPUREG_TEXENV0_SCALE"}, | ||
| 111 | |||
| 112 | {0x0C8, "GPUREG_TEXENV1_SOURCE"}, | ||
| 113 | {0x0C9, "GPUREG_TEXENV1_OPERAND"}, | ||
| 114 | {0x0CA, "GPUREG_TEXENV1_COMBINER"}, | ||
| 115 | {0x0CB, "GPUREG_TEXENV1_COLOR"}, | ||
| 116 | {0x0CC, "GPUREG_TEXENV1_SCALE"}, | ||
| 117 | |||
| 118 | {0x0D0, "GPUREG_TEXENV2_SOURCE"}, | ||
| 119 | {0x0D1, "GPUREG_TEXENV2_OPERAND"}, | ||
| 120 | {0x0D2, "GPUREG_TEXENV2_COMBINER"}, | ||
| 121 | {0x0D3, "GPUREG_TEXENV2_COLOR"}, | ||
| 122 | {0x0D4, "GPUREG_TEXENV2_SCALE"}, | ||
| 123 | |||
| 124 | {0x0D8, "GPUREG_TEXENV3_SOURCE"}, | ||
| 125 | {0x0D9, "GPUREG_TEXENV3_OPERAND"}, | ||
| 126 | {0x0DA, "GPUREG_TEXENV3_COMBINER"}, | ||
| 127 | {0x0DB, "GPUREG_TEXENV3_COLOR"}, | ||
| 128 | {0x0DC, "GPUREG_TEXENV3_SCALE"}, | ||
| 129 | |||
| 130 | {0x0E0, "GPUREG_TEXENV_UPDATE_BUFFER"}, | ||
| 131 | {0x0E1, "GPUREG_FOG_COLOR"}, | ||
| 132 | |||
| 133 | {0x0E4, "GPUREG_GAS_ATTENUATION"}, | ||
| 134 | {0x0E5, "GPUREG_GAS_ACCMAX"}, | ||
| 135 | {0x0E6, "GPUREG_FOG_LUT_INDEX"}, | ||
| 136 | |||
| 137 | {0x0E8, "GPUREG_FOG_LUT_DATA0"}, | ||
| 138 | {0x0E9, "GPUREG_FOG_LUT_DATA1"}, | ||
| 139 | {0x0EA, "GPUREG_FOG_LUT_DATA2"}, | ||
| 140 | {0x0EB, "GPUREG_FOG_LUT_DATA3"}, | ||
| 141 | {0x0EC, "GPUREG_FOG_LUT_DATA4"}, | ||
| 142 | {0x0ED, "GPUREG_FOG_LUT_DATA5"}, | ||
| 143 | {0x0EE, "GPUREG_FOG_LUT_DATA6"}, | ||
| 144 | {0x0EF, "GPUREG_FOG_LUT_DATA7"}, | ||
| 145 | {0x0F0, "GPUREG_TEXENV4_SOURCE"}, | ||
| 146 | {0x0F1, "GPUREG_TEXENV4_OPERAND"}, | ||
| 147 | {0x0F2, "GPUREG_TEXENV4_COMBINER"}, | ||
| 148 | {0x0F3, "GPUREG_TEXENV4_COLOR"}, | ||
| 149 | {0x0F4, "GPUREG_TEXENV4_SCALE"}, | ||
| 150 | |||
| 151 | {0x0F8, "GPUREG_TEXENV5_SOURCE"}, | ||
| 152 | {0x0F9, "GPUREG_TEXENV5_OPERAND"}, | ||
| 153 | {0x0FA, "GPUREG_TEXENV5_COMBINER"}, | ||
| 154 | {0x0FB, "GPUREG_TEXENV5_COLOR"}, | ||
| 155 | {0x0FC, "GPUREG_TEXENV5_SCALE"}, | ||
| 156 | {0x0FD, "GPUREG_TEXENV_BUFFER_COLOR"}, | ||
| 157 | |||
| 158 | {0x100, "GPUREG_COLOR_OPERATION"}, | ||
| 159 | {0x101, "GPUREG_BLEND_FUNC"}, | ||
| 160 | {0x102, "GPUREG_LOGIC_OP"}, | ||
| 161 | {0x103, "GPUREG_BLEND_COLOR"}, | ||
| 162 | {0x104, "GPUREG_FRAGOP_ALPHA_TEST"}, | ||
| 163 | {0x105, "GPUREG_STENCIL_TEST"}, | ||
| 164 | {0x106, "GPUREG_STENCIL_OP"}, | ||
| 165 | {0x107, "GPUREG_DEPTH_COLOR_MASK"}, | ||
| 166 | |||
| 167 | {0x110, "GPUREG_FRAMEBUFFER_INVALIDATE"}, | ||
| 168 | {0x111, "GPUREG_FRAMEBUFFER_FLUSH"}, | ||
| 169 | {0x112, "GPUREG_COLORBUFFER_READ"}, | ||
| 170 | {0x113, "GPUREG_COLORBUFFER_WRITE"}, | ||
| 171 | {0x114, "GPUREG_DEPTHBUFFER_READ"}, | ||
| 172 | {0x115, "GPUREG_DEPTHBUFFER_WRITE"}, | ||
| 173 | {0x116, "GPUREG_DEPTHBUFFER_FORMAT"}, | ||
| 174 | {0x117, "GPUREG_COLORBUFFER_FORMAT"}, | ||
| 175 | {0x118, "GPUREG_EARLYDEPTH_TEST2"}, | ||
| 176 | |||
| 177 | {0x11B, "GPUREG_FRAMEBUFFER_BLOCK32"}, | ||
| 178 | {0x11C, "GPUREG_DEPTHBUFFER_LOC"}, | ||
| 179 | {0x11D, "GPUREG_COLORBUFFER_LOC"}, | ||
| 180 | {0x11E, "GPUREG_FRAMEBUFFER_DIM"}, | ||
| 181 | |||
| 182 | {0x120, "GPUREG_GAS_LIGHT_XY"}, | ||
| 183 | {0x121, "GPUREG_GAS_LIGHT_Z"}, | ||
| 184 | {0x122, "GPUREG_GAS_LIGHT_Z_COLOR"}, | ||
| 185 | {0x123, "GPUREG_GAS_LUT_INDEX"}, | ||
| 186 | {0x124, "GPUREG_GAS_LUT_DATA"}, | ||
| 187 | |||
| 188 | {0x126, "GPUREG_GAS_DELTAZ_DEPTH"}, | ||
| 189 | |||
| 190 | {0x130, "GPUREG_FRAGOP_SHADOW"}, | ||
| 191 | |||
| 192 | {0x140, "GPUREG_LIGHT0_SPECULAR0"}, | ||
| 193 | {0x141, "GPUREG_LIGHT0_SPECULAR1"}, | ||
| 194 | {0x142, "GPUREG_LIGHT0_DIFFUSE"}, | ||
| 195 | {0x143, "GPUREG_LIGHT0_AMBIENT"}, | ||
| 196 | {0x144, "GPUREG_LIGHT0_XY"}, | ||
| 197 | {0x145, "GPUREG_LIGHT0_Z"}, | ||
| 198 | {0x146, "GPUREG_LIGHT0_SPOTDIR_XY"}, | ||
| 199 | {0x147, "GPUREG_LIGHT0_SPOTDIR_Z"}, | ||
| 200 | |||
| 201 | {0x149, "GPUREG_LIGHT0_CONFIG"}, | ||
| 202 | {0x14A, "GPUREG_LIGHT0_ATTENUATION_BIAS"}, | ||
| 203 | {0x14B, "GPUREG_LIGHT0_ATTENUATION_SCALE"}, | ||
| 204 | |||
| 205 | {0x150, "GPUREG_LIGHT1_SPECULAR0"}, | ||
| 206 | {0x151, "GPUREG_LIGHT1_SPECULAR1"}, | ||
| 207 | {0x152, "GPUREG_LIGHT1_DIFFUSE"}, | ||
| 208 | {0x153, "GPUREG_LIGHT1_AMBIENT"}, | ||
| 209 | {0x154, "GPUREG_LIGHT1_XY"}, | ||
| 210 | {0x155, "GPUREG_LIGHT1_Z"}, | ||
| 211 | {0x156, "GPUREG_LIGHT1_SPOTDIR_XY"}, | ||
| 212 | {0x157, "GPUREG_LIGHT1_SPOTDIR_Z"}, | ||
| 213 | |||
| 214 | {0x159, "GPUREG_LIGHT1_CONFIG"}, | ||
| 215 | {0x15A, "GPUREG_LIGHT1_ATTENUATION_BIAS"}, | ||
| 216 | {0x15B, "GPUREG_LIGHT1_ATTENUATION_SCALE"}, | ||
| 217 | |||
| 218 | {0x160, "GPUREG_LIGHT2_SPECULAR0"}, | ||
| 219 | {0x161, "GPUREG_LIGHT2_SPECULAR1"}, | ||
| 220 | {0x162, "GPUREG_LIGHT2_DIFFUSE"}, | ||
| 221 | {0x163, "GPUREG_LIGHT2_AMBIENT"}, | ||
| 222 | {0x164, "GPUREG_LIGHT2_XY"}, | ||
| 223 | {0x165, "GPUREG_LIGHT2_Z"}, | ||
| 224 | {0x166, "GPUREG_LIGHT2_SPOTDIR_XY"}, | ||
| 225 | {0x167, "GPUREG_LIGHT2_SPOTDIR_Z"}, | ||
| 226 | |||
| 227 | {0x169, "GPUREG_LIGHT2_CONFIG"}, | ||
| 228 | {0x16A, "GPUREG_LIGHT2_ATTENUATION_BIAS"}, | ||
| 229 | {0x16B, "GPUREG_LIGHT2_ATTENUATION_SCALE"}, | ||
| 230 | |||
| 231 | {0x170, "GPUREG_LIGHT3_SPECULAR0"}, | ||
| 232 | {0x171, "GPUREG_LIGHT3_SPECULAR1"}, | ||
| 233 | {0x172, "GPUREG_LIGHT3_DIFFUSE"}, | ||
| 234 | {0x173, "GPUREG_LIGHT3_AMBIENT"}, | ||
| 235 | {0x174, "GPUREG_LIGHT3_XY"}, | ||
| 236 | {0x175, "GPUREG_LIGHT3_Z"}, | ||
| 237 | {0x176, "GPUREG_LIGHT3_SPOTDIR_XY"}, | ||
| 238 | {0x177, "GPUREG_LIGHT3_SPOTDIR_Z"}, | ||
| 239 | |||
| 240 | {0x179, "GPUREG_LIGHT3_CONFIG"}, | ||
| 241 | {0x17A, "GPUREG_LIGHT3_ATTENUATION_BIAS"}, | ||
| 242 | {0x17B, "GPUREG_LIGHT3_ATTENUATION_SCALE"}, | ||
| 243 | |||
| 244 | {0x180, "GPUREG_LIGHT4_SPECULAR0"}, | ||
| 245 | {0x181, "GPUREG_LIGHT4_SPECULAR1"}, | ||
| 246 | {0x182, "GPUREG_LIGHT4_DIFFUSE"}, | ||
| 247 | {0x183, "GPUREG_LIGHT4_AMBIENT"}, | ||
| 248 | {0x184, "GPUREG_LIGHT4_XY"}, | ||
| 249 | {0x185, "GPUREG_LIGHT4_Z"}, | ||
| 250 | {0x186, "GPUREG_LIGHT4_SPOTDIR_XY"}, | ||
| 251 | {0x187, "GPUREG_LIGHT4_SPOTDIR_Z"}, | ||
| 252 | |||
| 253 | {0x189, "GPUREG_LIGHT4_CONFIG"}, | ||
| 254 | {0x18A, "GPUREG_LIGHT4_ATTENUATION_BIAS"}, | ||
| 255 | {0x18B, "GPUREG_LIGHT4_ATTENUATION_SCALE"}, | ||
| 256 | |||
| 257 | {0x190, "GPUREG_LIGHT5_SPECULAR0"}, | ||
| 258 | {0x191, "GPUREG_LIGHT5_SPECULAR1"}, | ||
| 259 | {0x192, "GPUREG_LIGHT5_DIFFUSE"}, | ||
| 260 | {0x193, "GPUREG_LIGHT5_AMBIENT"}, | ||
| 261 | {0x194, "GPUREG_LIGHT5_XY"}, | ||
| 262 | {0x195, "GPUREG_LIGHT5_Z"}, | ||
| 263 | {0x196, "GPUREG_LIGHT5_SPOTDIR_XY"}, | ||
| 264 | {0x197, "GPUREG_LIGHT5_SPOTDIR_Z"}, | ||
| 265 | |||
| 266 | {0x199, "GPUREG_LIGHT5_CONFIG"}, | ||
| 267 | {0x19A, "GPUREG_LIGHT5_ATTENUATION_BIAS"}, | ||
| 268 | {0x19B, "GPUREG_LIGHT5_ATTENUATION_SCALE"}, | ||
| 269 | |||
| 270 | {0x1A0, "GPUREG_LIGHT6_SPECULAR0"}, | ||
| 271 | {0x1A1, "GPUREG_LIGHT6_SPECULAR1"}, | ||
| 272 | {0x1A2, "GPUREG_LIGHT6_DIFFUSE"}, | ||
| 273 | {0x1A3, "GPUREG_LIGHT6_AMBIENT"}, | ||
| 274 | {0x1A4, "GPUREG_LIGHT6_XY"}, | ||
| 275 | {0x1A5, "GPUREG_LIGHT6_Z"}, | ||
| 276 | {0x1A6, "GPUREG_LIGHT6_SPOTDIR_XY"}, | ||
| 277 | {0x1A7, "GPUREG_LIGHT6_SPOTDIR_Z"}, | ||
| 278 | |||
| 279 | {0x1A9, "GPUREG_LIGHT6_CONFIG"}, | ||
| 280 | {0x1AA, "GPUREG_LIGHT6_ATTENUATION_BIAS"}, | ||
| 281 | {0x1AB, "GPUREG_LIGHT6_ATTENUATION_SCALE"}, | ||
| 282 | |||
| 283 | {0x1B0, "GPUREG_LIGHT7_SPECULAR0"}, | ||
| 284 | {0x1B1, "GPUREG_LIGHT7_SPECULAR1"}, | ||
| 285 | {0x1B2, "GPUREG_LIGHT7_DIFFUSE"}, | ||
| 286 | {0x1B3, "GPUREG_LIGHT7_AMBIENT"}, | ||
| 287 | {0x1B4, "GPUREG_LIGHT7_XY"}, | ||
| 288 | {0x1B5, "GPUREG_LIGHT7_Z"}, | ||
| 289 | {0x1B6, "GPUREG_LIGHT7_SPOTDIR_XY"}, | ||
| 290 | {0x1B7, "GPUREG_LIGHT7_SPOTDIR_Z"}, | ||
| 291 | |||
| 292 | {0x1B9, "GPUREG_LIGHT7_CONFIG"}, | ||
| 293 | {0x1BA, "GPUREG_LIGHT7_ATTENUATION_BIAS"}, | ||
| 294 | {0x1BB, "GPUREG_LIGHT7_ATTENUATION_SCALE"}, | ||
| 295 | |||
| 296 | {0x1C0, "GPUREG_LIGHTING_AMBIENT"}, | ||
| 297 | |||
| 298 | {0x1C2, "GPUREG_LIGHTING_NUM_LIGHTS"}, | ||
| 299 | {0x1C3, "GPUREG_LIGHTING_CONFIG0"}, | ||
| 300 | {0x1C4, "GPUREG_LIGHTING_CONFIG1"}, | ||
| 301 | {0x1C5, "GPUREG_LIGHTING_LUT_INDEX"}, | ||
| 302 | {0x1C6, "GPUREG_LIGHTING_ENABLE1"}, | ||
| 303 | |||
| 304 | {0x1C8, "GPUREG_LIGHTING_LUT_DATA0"}, | ||
| 305 | {0x1C9, "GPUREG_LIGHTING_LUT_DATA1"}, | ||
| 306 | {0x1CA, "GPUREG_LIGHTING_LUT_DATA2"}, | ||
| 307 | {0x1CB, "GPUREG_LIGHTING_LUT_DATA3"}, | ||
| 308 | {0x1CC, "GPUREG_LIGHTING_LUT_DATA4"}, | ||
| 309 | {0x1CD, "GPUREG_LIGHTING_LUT_DATA5"}, | ||
| 310 | {0x1CE, "GPUREG_LIGHTING_LUT_DATA6"}, | ||
| 311 | {0x1CF, "GPUREG_LIGHTING_LUT_DATA7"}, | ||
| 312 | {0x1D0, "GPUREG_LIGHTING_LUTINPUT_ABS"}, | ||
| 313 | {0x1D1, "GPUREG_LIGHTING_LUTINPUT_SELECT"}, | ||
| 314 | {0x1D2, "GPUREG_LIGHTING_LUTINPUT_SCALE"}, | ||
| 315 | |||
| 316 | {0x1D9, "GPUREG_LIGHTING_LIGHT_PERMUTATION"}, | ||
| 317 | |||
| 318 | {0x200, "GPUREG_ATTRIBBUFFERS_LOC"}, | ||
| 319 | {0x201, "GPUREG_ATTRIBBUFFERS_FORMAT_LOW"}, | ||
| 320 | {0x202, "GPUREG_ATTRIBBUFFERS_FORMAT_HIGH"}, | ||
| 321 | {0x203, "GPUREG_ATTRIBBUFFER0_OFFSET"}, | ||
| 322 | {0x204, "GPUREG_ATTRIBBUFFER0_CONFIG1"}, | ||
| 323 | {0x205, "GPUREG_ATTRIBBUFFER0_CONFIG2"}, | ||
| 324 | {0x206, "GPUREG_ATTRIBBUFFER1_OFFSET"}, | ||
| 325 | {0x207, "GPUREG_ATTRIBBUFFER1_CONFIG1"}, | ||
| 326 | {0x208, "GPUREG_ATTRIBBUFFER1_CONFIG2"}, | ||
| 327 | {0x209, "GPUREG_ATTRIBBUFFER2_OFFSET"}, | ||
| 328 | {0x20A, "GPUREG_ATTRIBBUFFER2_CONFIG1"}, | ||
| 329 | {0x20B, "GPUREG_ATTRIBBUFFER2_CONFIG2"}, | ||
| 330 | {0x20C, "GPUREG_ATTRIBBUFFER3_OFFSET"}, | ||
| 331 | {0x20D, "GPUREG_ATTRIBBUFFER3_CONFIG1"}, | ||
| 332 | {0x20E, "GPUREG_ATTRIBBUFFER3_CONFIG2"}, | ||
| 333 | {0x20F, "GPUREG_ATTRIBBUFFER4_OFFSET"}, | ||
| 334 | {0x210, "GPUREG_ATTRIBBUFFER4_CONFIG1"}, | ||
| 335 | {0x211, "GPUREG_ATTRIBBUFFER4_CONFIG2"}, | ||
| 336 | {0x212, "GPUREG_ATTRIBBUFFER5_OFFSET"}, | ||
| 337 | {0x213, "GPUREG_ATTRIBBUFFER5_CONFIG1"}, | ||
| 338 | {0x214, "GPUREG_ATTRIBBUFFER5_CONFIG2"}, | ||
| 339 | {0x215, "GPUREG_ATTRIBBUFFER6_OFFSET"}, | ||
| 340 | {0x216, "GPUREG_ATTRIBBUFFER6_CONFIG1"}, | ||
| 341 | {0x217, "GPUREG_ATTRIBBUFFER6_CONFIG2"}, | ||
| 342 | {0x218, "GPUREG_ATTRIBBUFFER7_OFFSET"}, | ||
| 343 | {0x219, "GPUREG_ATTRIBBUFFER7_CONFIG1"}, | ||
| 344 | {0x21A, "GPUREG_ATTRIBBUFFER7_CONFIG2"}, | ||
| 345 | {0x21B, "GPUREG_ATTRIBBUFFER8_OFFSET"}, | ||
| 346 | {0x21C, "GPUREG_ATTRIBBUFFER8_CONFIG1"}, | ||
| 347 | {0x21D, "GPUREG_ATTRIBBUFFER8_CONFIG2"}, | ||
| 348 | {0x21E, "GPUREG_ATTRIBBUFFER9_OFFSET"}, | ||
| 349 | {0x21F, "GPUREG_ATTRIBBUFFER9_CONFIG1"}, | ||
| 350 | {0x220, "GPUREG_ATTRIBBUFFER9_CONFIG2"}, | ||
| 351 | {0x221, "GPUREG_ATTRIBBUFFER10_OFFSET"}, | ||
| 352 | {0x222, "GPUREG_ATTRIBBUFFER10_CONFIG1"}, | ||
| 353 | {0x223, "GPUREG_ATTRIBBUFFER10_CONFIG2"}, | ||
| 354 | {0x224, "GPUREG_ATTRIBBUFFER11_OFFSET"}, | ||
| 355 | {0x225, "GPUREG_ATTRIBBUFFER11_CONFIG1"}, | ||
| 356 | {0x226, "GPUREG_ATTRIBBUFFER11_CONFIG2"}, | ||
| 357 | {0x227, "GPUREG_INDEXBUFFER_CONFIG"}, | ||
| 358 | {0x228, "GPUREG_NUMVERTICES"}, | ||
| 359 | {0x229, "GPUREG_GEOSTAGE_CONFIG"}, | ||
| 360 | {0x22A, "GPUREG_VERTEX_OFFSET"}, | ||
| 361 | |||
| 362 | {0x22D, "GPUREG_POST_VERTEX_CACHE_NUM"}, | ||
| 363 | {0x22E, "GPUREG_DRAWARRAYS"}, | ||
| 364 | {0x22F, "GPUREG_DRAWELEMENTS"}, | ||
| 365 | |||
| 366 | {0x231, "GPUREG_VTX_FUNC"}, | ||
| 367 | {0x232, "GPUREG_FIXEDATTRIB_INDEX"}, | ||
| 368 | {0x233, "GPUREG_FIXEDATTRIB_DATA0"}, | ||
| 369 | {0x234, "GPUREG_FIXEDATTRIB_DATA1"}, | ||
| 370 | {0x235, "GPUREG_FIXEDATTRIB_DATA2"}, | ||
| 371 | |||
| 372 | {0x238, "GPUREG_CMDBUF_SIZE0"}, | ||
| 373 | {0x239, "GPUREG_CMDBUF_SIZE1"}, | ||
| 374 | {0x23A, "GPUREG_CMDBUF_ADDR0"}, | ||
| 375 | {0x23B, "GPUREG_CMDBUF_ADDR1"}, | ||
| 376 | {0x23C, "GPUREG_CMDBUF_JUMP0"}, | ||
| 377 | {0x23D, "GPUREG_CMDBUF_JUMP1"}, | ||
| 378 | |||
| 379 | {0x242, "GPUREG_VSH_NUM_ATTR"}, | ||
| 380 | |||
| 381 | {0x244, "GPUREG_VSH_COM_MODE"}, | ||
| 382 | {0x245, "GPUREG_START_DRAW_FUNC0"}, | ||
| 383 | |||
| 384 | {0x24A, "GPUREG_VSH_OUTMAP_TOTAL1"}, | ||
| 385 | |||
| 386 | {0x251, "GPUREG_VSH_OUTMAP_TOTAL2"}, | ||
| 387 | {0x252, "GPUREG_GSH_MISC0"}, | ||
| 388 | {0x253, "GPUREG_GEOSTAGE_CONFIG2"}, | ||
| 389 | {0x254, "GPUREG_GSH_MISC1"}, | ||
| 390 | |||
| 391 | {0x25E, "GPUREG_PRIMITIVE_CONFIG"}, | ||
| 392 | {0x25F, "GPUREG_RESTART_PRIMITIVE"}, | ||
| 393 | |||
| 394 | {0x280, "GPUREG_GSH_BOOLUNIFORM"}, | ||
| 395 | {0x281, "GPUREG_GSH_INTUNIFORM_I0"}, | ||
| 396 | {0x282, "GPUREG_GSH_INTUNIFORM_I1"}, | ||
| 397 | {0x283, "GPUREG_GSH_INTUNIFORM_I2"}, | ||
| 398 | {0x284, "GPUREG_GSH_INTUNIFORM_I3"}, | ||
| 399 | |||
| 400 | {0x289, "GPUREG_GSH_INPUTBUFFER_CONFIG"}, | ||
| 401 | {0x28A, "GPUREG_GSH_ENTRYPOINT"}, | ||
| 402 | {0x28B, "GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW"}, | ||
| 403 | {0x28C, "GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH"}, | ||
| 404 | {0x28D, "GPUREG_GSH_OUTMAP_MASK"}, | ||
| 405 | |||
| 406 | {0x28F, "GPUREG_GSH_CODETRANSFER_END"}, | ||
| 407 | {0x290, "GPUREG_GSH_FLOATUNIFORM_INDEX"}, | ||
| 408 | {0x291, "GPUREG_GSH_FLOATUNIFORM_DATA0"}, | ||
| 409 | {0x292, "GPUREG_GSH_FLOATUNIFORM_DATA1"}, | ||
| 410 | {0x293, "GPUREG_GSH_FLOATUNIFORM_DATA2"}, | ||
| 411 | {0x294, "GPUREG_GSH_FLOATUNIFORM_DATA3"}, | ||
| 412 | {0x295, "GPUREG_GSH_FLOATUNIFORM_DATA4"}, | ||
| 413 | {0x296, "GPUREG_GSH_FLOATUNIFORM_DATA5"}, | ||
| 414 | {0x297, "GPUREG_GSH_FLOATUNIFORM_DATA6"}, | ||
| 415 | {0x298, "GPUREG_GSH_FLOATUNIFORM_DATA7"}, | ||
| 416 | |||
| 417 | {0x29B, "GPUREG_GSH_CODETRANSFER_INDEX"}, | ||
| 418 | {0x29C, "GPUREG_GSH_CODETRANSFER_DATA0"}, | ||
| 419 | {0x29D, "GPUREG_GSH_CODETRANSFER_DATA1"}, | ||
| 420 | {0x29E, "GPUREG_GSH_CODETRANSFER_DATA2"}, | ||
| 421 | {0x29F, "GPUREG_GSH_CODETRANSFER_DATA3"}, | ||
| 422 | {0x2A0, "GPUREG_GSH_CODETRANSFER_DATA4"}, | ||
| 423 | {0x2A1, "GPUREG_GSH_CODETRANSFER_DATA5"}, | ||
| 424 | {0x2A2, "GPUREG_GSH_CODETRANSFER_DATA6"}, | ||
| 425 | {0x2A3, "GPUREG_GSH_CODETRANSFER_DATA7"}, | ||
| 426 | |||
| 427 | {0x2A5, "GPUREG_GSH_OPDESCS_INDEX"}, | ||
| 428 | {0x2A6, "GPUREG_GSH_OPDESCS_DATA0"}, | ||
| 429 | {0x2A7, "GPUREG_GSH_OPDESCS_DATA1"}, | ||
| 430 | {0x2A8, "GPUREG_GSH_OPDESCS_DATA2"}, | ||
| 431 | {0x2A9, "GPUREG_GSH_OPDESCS_DATA3"}, | ||
| 432 | {0x2AA, "GPUREG_GSH_OPDESCS_DATA4"}, | ||
| 433 | {0x2AB, "GPUREG_GSH_OPDESCS_DATA5"}, | ||
| 434 | {0x2AC, "GPUREG_GSH_OPDESCS_DATA6"}, | ||
| 435 | {0x2AD, "GPUREG_GSH_OPDESCS_DATA7"}, | ||
| 436 | |||
| 437 | {0x2B0, "GPUREG_VSH_BOOLUNIFORM"}, | ||
| 438 | {0x2B1, "GPUREG_VSH_INTUNIFORM_I0"}, | ||
| 439 | {0x2B2, "GPUREG_VSH_INTUNIFORM_I1"}, | ||
| 440 | {0x2B3, "GPUREG_VSH_INTUNIFORM_I2"}, | ||
| 441 | {0x2B4, "GPUREG_VSH_INTUNIFORM_I3"}, | ||
| 442 | |||
| 443 | {0x2B9, "GPUREG_VSH_INPUTBUFFER_CONFIG"}, | ||
| 444 | {0x2BA, "GPUREG_VSH_ENTRYPOINT"}, | ||
| 445 | {0x2BB, "GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW"}, | ||
| 446 | {0x2BC, "GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH"}, | ||
| 447 | {0x2BD, "GPUREG_VSH_OUTMAP_MASK"}, | ||
| 448 | |||
| 449 | {0x2BF, "GPUREG_VSH_CODETRANSFER_END"}, | ||
| 450 | {0x2C0, "GPUREG_VSH_FLOATUNIFORM_INDEX"}, | ||
| 451 | {0x2C1, "GPUREG_VSH_FLOATUNIFORM_DATA0"}, | ||
| 452 | {0x2C2, "GPUREG_VSH_FLOATUNIFORM_DATA1"}, | ||
| 453 | {0x2C3, "GPUREG_VSH_FLOATUNIFORM_DATA2"}, | ||
| 454 | {0x2C4, "GPUREG_VSH_FLOATUNIFORM_DATA3"}, | ||
| 455 | {0x2C5, "GPUREG_VSH_FLOATUNIFORM_DATA4"}, | ||
| 456 | {0x2C6, "GPUREG_VSH_FLOATUNIFORM_DATA5"}, | ||
| 457 | {0x2C7, "GPUREG_VSH_FLOATUNIFORM_DATA6"}, | ||
| 458 | {0x2C8, "GPUREG_VSH_FLOATUNIFORM_DATA7"}, | ||
| 459 | |||
| 460 | {0x2CB, "GPUREG_VSH_CODETRANSFER_INDEX"}, | ||
| 461 | {0x2CC, "GPUREG_VSH_CODETRANSFER_DATA0"}, | ||
| 462 | {0x2CD, "GPUREG_VSH_CODETRANSFER_DATA1"}, | ||
| 463 | {0x2CE, "GPUREG_VSH_CODETRANSFER_DATA2"}, | ||
| 464 | {0x2CF, "GPUREG_VSH_CODETRANSFER_DATA3"}, | ||
| 465 | {0x2D0, "GPUREG_VSH_CODETRANSFER_DATA4"}, | ||
| 466 | {0x2D1, "GPUREG_VSH_CODETRANSFER_DATA5"}, | ||
| 467 | {0x2D2, "GPUREG_VSH_CODETRANSFER_DATA6"}, | ||
| 468 | {0x2D3, "GPUREG_VSH_CODETRANSFER_DATA7"}, | ||
| 469 | |||
| 470 | {0x2D5, "GPUREG_VSH_OPDESCS_INDEX"}, | ||
| 471 | {0x2D6, "GPUREG_VSH_OPDESCS_DATA0"}, | ||
| 472 | {0x2D7, "GPUREG_VSH_OPDESCS_DATA1"}, | ||
| 473 | {0x2D8, "GPUREG_VSH_OPDESCS_DATA2"}, | ||
| 474 | {0x2D9, "GPUREG_VSH_OPDESCS_DATA3"}, | ||
| 475 | {0x2DA, "GPUREG_VSH_OPDESCS_DATA4"}, | ||
| 476 | {0x2DB, "GPUREG_VSH_OPDESCS_DATA5"}, | ||
| 477 | {0x2DC, "GPUREG_VSH_OPDESCS_DATA6"}, | ||
| 478 | {0x2DD, "GPUREG_VSH_OPDESCS_DATA7"}, | ||
| 479 | }; | ||
| 480 | |||
| 481 | std::string Regs::GetCommandName(int index) { | ||
| 482 | static std::unordered_map<u32, const char*> map; | ||
| 483 | |||
| 484 | if (map.empty()) { | ||
| 485 | map.insert(std::begin(register_names), std::end(register_names)); | ||
| 486 | } | ||
| 487 | |||
| 488 | // Return empty string if no match is found | ||
| 489 | auto it = map.find(index); | ||
| 490 | if (it != map.end()) { | ||
| 491 | return it->second; | ||
| 492 | } else { | ||
| 493 | return std::string(); | ||
| 494 | } | ||
| 495 | } | ||
| 496 | |||
| 497 | void Init() { | 14 | void Init() { |
| 498 | g_state.Reset(); | 15 | g_state.Reset(); |
| 499 | } | 16 | } |
| @@ -513,6 +30,6 @@ void State::Reset() { | |||
| 513 | Zero(gs); | 30 | Zero(gs); |
| 514 | Zero(cmd_list); | 31 | Zero(cmd_list); |
| 515 | Zero(immediate); | 32 | Zero(immediate); |
| 516 | primitive_assembler.Reconfigure(Regs::TriangleTopology::List); | 33 | primitive_assembler.Reconfigure(PipelineRegs::TriangleTopology::List); |
| 517 | } | 34 | } |
| 518 | } | 35 | } |
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 731540b99..dc8aa6670 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -4,1400 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include "video_core/regs_texturing.h" |
| 8 | #include <cstddef> | ||
| 9 | #include <string> | ||
| 10 | |||
| 11 | #ifndef _MSC_VER | ||
| 12 | #include <type_traits> // for std::enable_if | ||
| 13 | #endif | ||
| 14 | |||
| 15 | #include "common/assert.h" | ||
| 16 | #include "common/bit_field.h" | ||
| 17 | #include "common/common_funcs.h" | ||
| 18 | #include "common/common_types.h" | ||
| 19 | #include "common/logging/log.h" | ||
| 20 | #include "common/vector_math.h" | ||
| 21 | |||
| 22 | namespace Pica { | 8 | namespace Pica { |
| 23 | 9 | ||
| 24 | // Returns index corresponding to the Regs member labeled by field_name | ||
| 25 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions | ||
| 26 | // when used with array elements (e.g. PICA_REG_INDEX(vs_uniform_setup.set_value[1])). | ||
| 27 | // For details cf. | ||
| 28 | // https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | ||
| 29 | // Hopefully, this will be fixed sometime in the future. | ||
| 30 | // For lack of better alternatives, we currently hardcode the offsets when constant | ||
| 31 | // expressions are needed via PICA_REG_INDEX_WORKAROUND (on sane compilers, static_asserts | ||
| 32 | // will then make sure the offsets indeed match the automatically calculated ones). | ||
| 33 | #define PICA_REG_INDEX(field_name) (offsetof(Pica::Regs, field_name) / sizeof(u32)) | ||
| 34 | #if defined(_MSC_VER) | ||
| 35 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) (backup_workaround_index) | ||
| 36 | #else | ||
| 37 | // NOTE: Yeah, hacking in a static_assert here just to workaround the lacking MSVC compiler | ||
| 38 | // really is this annoying. This macro just forwards its first argument to PICA_REG_INDEX | ||
| 39 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected | ||
| 40 | // field offset. Otherwise, the compiler will fail to compile this code. | ||
| 41 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ | ||
| 42 | ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \ | ||
| 43 | size_t>::type)PICA_REG_INDEX(field_name)) | ||
| 44 | #endif // _MSC_VER | ||
| 45 | |||
| 46 | struct Regs { | ||
| 47 | |||
| 48 | INSERT_PADDING_WORDS(0x10); | ||
| 49 | |||
| 50 | u32 trigger_irq; | ||
| 51 | |||
| 52 | INSERT_PADDING_WORDS(0x2f); | ||
| 53 | |||
| 54 | enum class CullMode : u32 { | ||
| 55 | // Select which polygons are considered to be "frontfacing". | ||
| 56 | KeepAll = 0, | ||
| 57 | KeepClockWise = 1, | ||
| 58 | KeepCounterClockWise = 2, | ||
| 59 | // TODO: What does the third value imply? | ||
| 60 | }; | ||
| 61 | |||
| 62 | union { | ||
| 63 | BitField<0, 2, CullMode> cull_mode; | ||
| 64 | }; | ||
| 65 | |||
| 66 | BitField<0, 24, u32> viewport_size_x; | ||
| 67 | |||
| 68 | INSERT_PADDING_WORDS(0x1); | ||
| 69 | |||
| 70 | BitField<0, 24, u32> viewport_size_y; | ||
| 71 | |||
| 72 | INSERT_PADDING_WORDS(0x9); | ||
| 73 | |||
| 74 | BitField<0, 24, u32> viewport_depth_range; // float24 | ||
| 75 | BitField<0, 24, u32> viewport_depth_near_plane; // float24 | ||
| 76 | |||
| 77 | BitField<0, 3, u32> vs_output_total; | ||
| 78 | |||
| 79 | union VSOutputAttributes { | ||
| 80 | // Maps components of output vertex attributes to semantics | ||
| 81 | enum Semantic : u32 { | ||
| 82 | POSITION_X = 0, | ||
| 83 | POSITION_Y = 1, | ||
| 84 | POSITION_Z = 2, | ||
| 85 | POSITION_W = 3, | ||
| 86 | |||
| 87 | QUATERNION_X = 4, | ||
| 88 | QUATERNION_Y = 5, | ||
| 89 | QUATERNION_Z = 6, | ||
| 90 | QUATERNION_W = 7, | ||
| 91 | |||
| 92 | COLOR_R = 8, | ||
| 93 | COLOR_G = 9, | ||
| 94 | COLOR_B = 10, | ||
| 95 | COLOR_A = 11, | ||
| 96 | |||
| 97 | TEXCOORD0_U = 12, | ||
| 98 | TEXCOORD0_V = 13, | ||
| 99 | TEXCOORD1_U = 14, | ||
| 100 | TEXCOORD1_V = 15, | ||
| 101 | |||
| 102 | TEXCOORD0_W = 16, | ||
| 103 | |||
| 104 | VIEW_X = 18, | ||
| 105 | VIEW_Y = 19, | ||
| 106 | VIEW_Z = 20, | ||
| 107 | |||
| 108 | TEXCOORD2_U = 22, | ||
| 109 | TEXCOORD2_V = 23, | ||
| 110 | |||
| 111 | INVALID = 31, | ||
| 112 | }; | ||
| 113 | |||
| 114 | BitField<0, 5, Semantic> map_x; | ||
| 115 | BitField<8, 5, Semantic> map_y; | ||
| 116 | BitField<16, 5, Semantic> map_z; | ||
| 117 | BitField<24, 5, Semantic> map_w; | ||
| 118 | } vs_output_attributes[7]; | ||
| 119 | |||
| 120 | INSERT_PADDING_WORDS(0xe); | ||
| 121 | |||
| 122 | enum class ScissorMode : u32 { | ||
| 123 | Disabled = 0, | ||
| 124 | Exclude = 1, // Exclude pixels inside the scissor box | ||
| 125 | |||
| 126 | Include = 3 // Exclude pixels outside the scissor box | ||
| 127 | }; | ||
| 128 | |||
| 129 | struct { | ||
| 130 | BitField<0, 2, ScissorMode> mode; | ||
| 131 | |||
| 132 | union { | ||
| 133 | BitField<0, 16, u32> x1; | ||
| 134 | BitField<16, 16, u32> y1; | ||
| 135 | }; | ||
| 136 | |||
| 137 | union { | ||
| 138 | BitField<0, 16, u32> x2; | ||
| 139 | BitField<16, 16, u32> y2; | ||
| 140 | }; | ||
| 141 | } scissor_test; | ||
| 142 | |||
| 143 | union { | ||
| 144 | BitField<0, 10, s32> x; | ||
| 145 | BitField<16, 10, s32> y; | ||
| 146 | } viewport_corner; | ||
| 147 | |||
| 148 | INSERT_PADDING_WORDS(0x1); | ||
| 149 | |||
| 150 | // TODO: early depth | ||
| 151 | INSERT_PADDING_WORDS(0x1); | ||
| 152 | |||
| 153 | INSERT_PADDING_WORDS(0x2); | ||
| 154 | |||
| 155 | enum DepthBuffering : u32 { | ||
| 156 | WBuffering = 0, | ||
| 157 | ZBuffering = 1, | ||
| 158 | }; | ||
| 159 | BitField<0, 1, DepthBuffering> depthmap_enable; | ||
| 160 | |||
| 161 | INSERT_PADDING_WORDS(0x12); | ||
| 162 | |||
| 163 | struct TextureConfig { | ||
| 164 | enum TextureType : u32 { | ||
| 165 | Texture2D = 0, | ||
| 166 | TextureCube = 1, | ||
| 167 | Shadow2D = 2, | ||
| 168 | Projection2D = 3, | ||
| 169 | ShadowCube = 4, | ||
| 170 | Disabled = 5, | ||
| 171 | }; | ||
| 172 | |||
| 173 | enum WrapMode : u32 { | ||
| 174 | ClampToEdge = 0, | ||
| 175 | ClampToBorder = 1, | ||
| 176 | Repeat = 2, | ||
| 177 | MirroredRepeat = 3, | ||
| 178 | }; | ||
| 179 | |||
| 180 | enum TextureFilter : u32 { | ||
| 181 | Nearest = 0, | ||
| 182 | Linear = 1, | ||
| 183 | }; | ||
| 184 | |||
| 185 | union { | ||
| 186 | u32 raw; | ||
| 187 | BitField<0, 8, u32> r; | ||
| 188 | BitField<8, 8, u32> g; | ||
| 189 | BitField<16, 8, u32> b; | ||
| 190 | BitField<24, 8, u32> a; | ||
| 191 | } border_color; | ||
| 192 | |||
| 193 | union { | ||
| 194 | BitField<0, 16, u32> height; | ||
| 195 | BitField<16, 16, u32> width; | ||
| 196 | }; | ||
| 197 | |||
| 198 | union { | ||
| 199 | BitField<1, 1, TextureFilter> mag_filter; | ||
| 200 | BitField<2, 1, TextureFilter> min_filter; | ||
| 201 | BitField<8, 2, WrapMode> wrap_t; | ||
| 202 | BitField<12, 2, WrapMode> wrap_s; | ||
| 203 | BitField<28, 2, TextureType> | ||
| 204 | type; ///< @note Only valid for texture 0 according to 3DBrew. | ||
| 205 | }; | ||
| 206 | |||
| 207 | INSERT_PADDING_WORDS(0x1); | ||
| 208 | |||
| 209 | u32 address; | ||
| 210 | |||
| 211 | u32 GetPhysicalAddress() const { | ||
| 212 | return DecodeAddressRegister(address); | ||
| 213 | } | ||
| 214 | |||
| 215 | // texture1 and texture2 store the texture format directly after the address | ||
| 216 | // whereas texture0 inserts some additional flags inbetween. | ||
| 217 | // Hence, we store the format separately so that all other parameters can be described | ||
| 218 | // in a single structure. | ||
| 219 | }; | ||
| 220 | |||
| 221 | enum class TextureFormat : u32 { | ||
| 222 | RGBA8 = 0, | ||
| 223 | RGB8 = 1, | ||
| 224 | RGB5A1 = 2, | ||
| 225 | RGB565 = 3, | ||
| 226 | RGBA4 = 4, | ||
| 227 | IA8 = 5, | ||
| 228 | RG8 = 6, ///< @note Also called HILO8 in 3DBrew. | ||
| 229 | I8 = 7, | ||
| 230 | A8 = 8, | ||
| 231 | IA4 = 9, | ||
| 232 | I4 = 10, | ||
| 233 | A4 = 11, | ||
| 234 | ETC1 = 12, // compressed | ||
| 235 | ETC1A4 = 13, // compressed | ||
| 236 | }; | ||
| 237 | |||
| 238 | enum class LogicOp : u32 { | ||
| 239 | Clear = 0, | ||
| 240 | And = 1, | ||
| 241 | AndReverse = 2, | ||
| 242 | Copy = 3, | ||
| 243 | Set = 4, | ||
| 244 | CopyInverted = 5, | ||
| 245 | NoOp = 6, | ||
| 246 | Invert = 7, | ||
| 247 | Nand = 8, | ||
| 248 | Or = 9, | ||
| 249 | Nor = 10, | ||
| 250 | Xor = 11, | ||
| 251 | Equiv = 12, | ||
| 252 | AndInverted = 13, | ||
| 253 | OrReverse = 14, | ||
| 254 | OrInverted = 15, | ||
| 255 | }; | ||
| 256 | |||
| 257 | static unsigned NibblesPerPixel(TextureFormat format) { | ||
| 258 | switch (format) { | ||
| 259 | case TextureFormat::RGBA8: | ||
| 260 | return 8; | ||
| 261 | |||
| 262 | case TextureFormat::RGB8: | ||
| 263 | return 6; | ||
| 264 | |||
| 265 | case TextureFormat::RGB5A1: | ||
| 266 | case TextureFormat::RGB565: | ||
| 267 | case TextureFormat::RGBA4: | ||
| 268 | case TextureFormat::IA8: | ||
| 269 | case TextureFormat::RG8: | ||
| 270 | return 4; | ||
| 271 | |||
| 272 | case TextureFormat::I4: | ||
| 273 | case TextureFormat::A4: | ||
| 274 | return 1; | ||
| 275 | |||
| 276 | case TextureFormat::I8: | ||
| 277 | case TextureFormat::A8: | ||
| 278 | case TextureFormat::IA4: | ||
| 279 | return 2; | ||
| 280 | |||
| 281 | default: // placeholder for yet unknown formats | ||
| 282 | UNIMPLEMENTED(); | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | union { | ||
| 288 | BitField<0, 1, u32> texture0_enable; | ||
| 289 | BitField<1, 1, u32> texture1_enable; | ||
| 290 | BitField<2, 1, u32> texture2_enable; | ||
| 291 | }; | ||
| 292 | TextureConfig texture0; | ||
| 293 | INSERT_PADDING_WORDS(0x8); | ||
| 294 | BitField<0, 4, TextureFormat> texture0_format; | ||
| 295 | BitField<0, 1, u32> fragment_lighting_enable; | ||
| 296 | INSERT_PADDING_WORDS(0x1); | ||
| 297 | TextureConfig texture1; | ||
| 298 | BitField<0, 4, TextureFormat> texture1_format; | ||
| 299 | INSERT_PADDING_WORDS(0x2); | ||
| 300 | TextureConfig texture2; | ||
| 301 | BitField<0, 4, TextureFormat> texture2_format; | ||
| 302 | INSERT_PADDING_WORDS(0x21); | ||
| 303 | |||
| 304 | struct FullTextureConfig { | ||
| 305 | const bool enabled; | ||
| 306 | const TextureConfig config; | ||
| 307 | const TextureFormat format; | ||
| 308 | }; | ||
| 309 | const std::array<FullTextureConfig, 3> GetTextures() const { | ||
| 310 | return {{ | ||
| 311 | {texture0_enable.ToBool(), texture0, texture0_format}, | ||
| 312 | {texture1_enable.ToBool(), texture1, texture1_format}, | ||
| 313 | {texture2_enable.ToBool(), texture2, texture2_format}, | ||
| 314 | }}; | ||
| 315 | } | ||
| 316 | |||
| 317 | // 0xc0-0xff: Texture Combiner (akin to glTexEnv) | ||
| 318 | struct TevStageConfig { | ||
| 319 | enum class Source : u32 { | ||
| 320 | PrimaryColor = 0x0, | ||
| 321 | PrimaryFragmentColor = 0x1, | ||
| 322 | SecondaryFragmentColor = 0x2, | ||
| 323 | |||
| 324 | Texture0 = 0x3, | ||
| 325 | Texture1 = 0x4, | ||
| 326 | Texture2 = 0x5, | ||
| 327 | Texture3 = 0x6, | ||
| 328 | |||
| 329 | PreviousBuffer = 0xd, | ||
| 330 | Constant = 0xe, | ||
| 331 | Previous = 0xf, | ||
| 332 | }; | ||
| 333 | |||
| 334 | enum class ColorModifier : u32 { | ||
| 335 | SourceColor = 0x0, | ||
| 336 | OneMinusSourceColor = 0x1, | ||
| 337 | SourceAlpha = 0x2, | ||
| 338 | OneMinusSourceAlpha = 0x3, | ||
| 339 | SourceRed = 0x4, | ||
| 340 | OneMinusSourceRed = 0x5, | ||
| 341 | |||
| 342 | SourceGreen = 0x8, | ||
| 343 | OneMinusSourceGreen = 0x9, | ||
| 344 | |||
| 345 | SourceBlue = 0xc, | ||
| 346 | OneMinusSourceBlue = 0xd, | ||
| 347 | }; | ||
| 348 | |||
| 349 | enum class AlphaModifier : u32 { | ||
| 350 | SourceAlpha = 0x0, | ||
| 351 | OneMinusSourceAlpha = 0x1, | ||
| 352 | SourceRed = 0x2, | ||
| 353 | OneMinusSourceRed = 0x3, | ||
| 354 | SourceGreen = 0x4, | ||
| 355 | OneMinusSourceGreen = 0x5, | ||
| 356 | SourceBlue = 0x6, | ||
| 357 | OneMinusSourceBlue = 0x7, | ||
| 358 | }; | ||
| 359 | |||
| 360 | enum class Operation : u32 { | ||
| 361 | Replace = 0, | ||
| 362 | Modulate = 1, | ||
| 363 | Add = 2, | ||
| 364 | AddSigned = 3, | ||
| 365 | Lerp = 4, | ||
| 366 | Subtract = 5, | ||
| 367 | Dot3_RGB = 6, | ||
| 368 | |||
| 369 | MultiplyThenAdd = 8, | ||
| 370 | AddThenMultiply = 9, | ||
| 371 | }; | ||
| 372 | |||
| 373 | union { | ||
| 374 | u32 sources_raw; | ||
| 375 | BitField<0, 4, Source> color_source1; | ||
| 376 | BitField<4, 4, Source> color_source2; | ||
| 377 | BitField<8, 4, Source> color_source3; | ||
| 378 | BitField<16, 4, Source> alpha_source1; | ||
| 379 | BitField<20, 4, Source> alpha_source2; | ||
| 380 | BitField<24, 4, Source> alpha_source3; | ||
| 381 | }; | ||
| 382 | |||
| 383 | union { | ||
| 384 | u32 modifiers_raw; | ||
| 385 | BitField<0, 4, ColorModifier> color_modifier1; | ||
| 386 | BitField<4, 4, ColorModifier> color_modifier2; | ||
| 387 | BitField<8, 4, ColorModifier> color_modifier3; | ||
| 388 | BitField<12, 3, AlphaModifier> alpha_modifier1; | ||
| 389 | BitField<16, 3, AlphaModifier> alpha_modifier2; | ||
| 390 | BitField<20, 3, AlphaModifier> alpha_modifier3; | ||
| 391 | }; | ||
| 392 | |||
| 393 | union { | ||
| 394 | u32 ops_raw; | ||
| 395 | BitField<0, 4, Operation> color_op; | ||
| 396 | BitField<16, 4, Operation> alpha_op; | ||
| 397 | }; | ||
| 398 | |||
| 399 | union { | ||
| 400 | u32 const_color; | ||
| 401 | BitField<0, 8, u32> const_r; | ||
| 402 | BitField<8, 8, u32> const_g; | ||
| 403 | BitField<16, 8, u32> const_b; | ||
| 404 | BitField<24, 8, u32> const_a; | ||
| 405 | }; | ||
| 406 | |||
| 407 | union { | ||
| 408 | u32 scales_raw; | ||
| 409 | BitField<0, 2, u32> color_scale; | ||
| 410 | BitField<16, 2, u32> alpha_scale; | ||
| 411 | }; | ||
| 412 | |||
| 413 | inline unsigned GetColorMultiplier() const { | ||
| 414 | return (color_scale < 3) ? (1 << color_scale) : 1; | ||
| 415 | } | ||
| 416 | |||
| 417 | inline unsigned GetAlphaMultiplier() const { | ||
| 418 | return (alpha_scale < 3) ? (1 << alpha_scale) : 1; | ||
| 419 | } | ||
| 420 | }; | ||
| 421 | |||
| 422 | TevStageConfig tev_stage0; | ||
| 423 | INSERT_PADDING_WORDS(0x3); | ||
| 424 | TevStageConfig tev_stage1; | ||
| 425 | INSERT_PADDING_WORDS(0x3); | ||
| 426 | TevStageConfig tev_stage2; | ||
| 427 | INSERT_PADDING_WORDS(0x3); | ||
| 428 | TevStageConfig tev_stage3; | ||
| 429 | INSERT_PADDING_WORDS(0x3); | ||
| 430 | |||
| 431 | enum class FogMode : u32 { | ||
| 432 | None = 0, | ||
| 433 | Fog = 5, | ||
| 434 | Gas = 7, | ||
| 435 | }; | ||
| 436 | |||
| 437 | union { | ||
| 438 | BitField<0, 3, FogMode> fog_mode; | ||
| 439 | BitField<16, 1, u32> fog_flip; | ||
| 440 | |||
| 441 | union { | ||
| 442 | // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in | ||
| 443 | // these masks are set | ||
| 444 | BitField<8, 4, u32> update_mask_rgb; | ||
| 445 | BitField<12, 4, u32> update_mask_a; | ||
| 446 | |||
| 447 | bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { | ||
| 448 | return (stage_index < 4) && (update_mask_rgb & (1 << stage_index)); | ||
| 449 | } | ||
| 450 | |||
| 451 | bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const { | ||
| 452 | return (stage_index < 4) && (update_mask_a & (1 << stage_index)); | ||
| 453 | } | ||
| 454 | } tev_combiner_buffer_input; | ||
| 455 | }; | ||
| 456 | |||
| 457 | union { | ||
| 458 | u32 raw; | ||
| 459 | BitField<0, 8, u32> r; | ||
| 460 | BitField<8, 8, u32> g; | ||
| 461 | BitField<16, 8, u32> b; | ||
| 462 | } fog_color; | ||
| 463 | |||
| 464 | INSERT_PADDING_WORDS(0x4); | ||
| 465 | |||
| 466 | BitField<0, 16, u32> fog_lut_offset; | ||
| 467 | |||
| 468 | INSERT_PADDING_WORDS(0x1); | ||
| 469 | |||
| 470 | u32 fog_lut_data[8]; | ||
| 471 | |||
| 472 | TevStageConfig tev_stage4; | ||
| 473 | INSERT_PADDING_WORDS(0x3); | ||
| 474 | TevStageConfig tev_stage5; | ||
| 475 | |||
| 476 | union { | ||
| 477 | u32 raw; | ||
| 478 | BitField<0, 8, u32> r; | ||
| 479 | BitField<8, 8, u32> g; | ||
| 480 | BitField<16, 8, u32> b; | ||
| 481 | BitField<24, 8, u32> a; | ||
| 482 | } tev_combiner_buffer_color; | ||
| 483 | |||
| 484 | INSERT_PADDING_WORDS(0x2); | ||
| 485 | |||
| 486 | const std::array<Regs::TevStageConfig, 6> GetTevStages() const { | ||
| 487 | return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}}; | ||
| 488 | }; | ||
| 489 | |||
| 490 | enum class BlendEquation : u32 { | ||
| 491 | Add = 0, | ||
| 492 | Subtract = 1, | ||
| 493 | ReverseSubtract = 2, | ||
| 494 | Min = 3, | ||
| 495 | Max = 4, | ||
| 496 | }; | ||
| 497 | |||
| 498 | enum class BlendFactor : u32 { | ||
| 499 | Zero = 0, | ||
| 500 | One = 1, | ||
| 501 | SourceColor = 2, | ||
| 502 | OneMinusSourceColor = 3, | ||
| 503 | DestColor = 4, | ||
| 504 | OneMinusDestColor = 5, | ||
| 505 | SourceAlpha = 6, | ||
| 506 | OneMinusSourceAlpha = 7, | ||
| 507 | DestAlpha = 8, | ||
| 508 | OneMinusDestAlpha = 9, | ||
| 509 | ConstantColor = 10, | ||
| 510 | OneMinusConstantColor = 11, | ||
| 511 | ConstantAlpha = 12, | ||
| 512 | OneMinusConstantAlpha = 13, | ||
| 513 | SourceAlphaSaturate = 14, | ||
| 514 | }; | ||
| 515 | |||
| 516 | enum class CompareFunc : u32 { | ||
| 517 | Never = 0, | ||
| 518 | Always = 1, | ||
| 519 | Equal = 2, | ||
| 520 | NotEqual = 3, | ||
| 521 | LessThan = 4, | ||
| 522 | LessThanOrEqual = 5, | ||
| 523 | GreaterThan = 6, | ||
| 524 | GreaterThanOrEqual = 7, | ||
| 525 | }; | ||
| 526 | |||
| 527 | enum class StencilAction : u32 { | ||
| 528 | Keep = 0, | ||
| 529 | Zero = 1, | ||
| 530 | Replace = 2, | ||
| 531 | Increment = 3, | ||
| 532 | Decrement = 4, | ||
| 533 | Invert = 5, | ||
| 534 | IncrementWrap = 6, | ||
| 535 | DecrementWrap = 7, | ||
| 536 | }; | ||
| 537 | |||
| 538 | struct { | ||
| 539 | union { | ||
| 540 | // If false, logic blending is used | ||
| 541 | BitField<8, 1, u32> alphablend_enable; | ||
| 542 | }; | ||
| 543 | |||
| 544 | union { | ||
| 545 | BitField<0, 8, BlendEquation> blend_equation_rgb; | ||
| 546 | BitField<8, 8, BlendEquation> blend_equation_a; | ||
| 547 | |||
| 548 | BitField<16, 4, BlendFactor> factor_source_rgb; | ||
| 549 | BitField<20, 4, BlendFactor> factor_dest_rgb; | ||
| 550 | |||
| 551 | BitField<24, 4, BlendFactor> factor_source_a; | ||
| 552 | BitField<28, 4, BlendFactor> factor_dest_a; | ||
| 553 | } alpha_blending; | ||
| 554 | |||
| 555 | union { | ||
| 556 | BitField<0, 4, LogicOp> logic_op; | ||
| 557 | }; | ||
| 558 | |||
| 559 | union { | ||
| 560 | u32 raw; | ||
| 561 | BitField<0, 8, u32> r; | ||
| 562 | BitField<8, 8, u32> g; | ||
| 563 | BitField<16, 8, u32> b; | ||
| 564 | BitField<24, 8, u32> a; | ||
| 565 | } blend_const; | ||
| 566 | |||
| 567 | union { | ||
| 568 | BitField<0, 1, u32> enable; | ||
| 569 | BitField<4, 3, CompareFunc> func; | ||
| 570 | BitField<8, 8, u32> ref; | ||
| 571 | } alpha_test; | ||
| 572 | |||
| 573 | struct { | ||
| 574 | union { | ||
| 575 | // Raw value of this register | ||
| 576 | u32 raw_func; | ||
| 577 | |||
| 578 | // If true, enable stencil testing | ||
| 579 | BitField<0, 1, u32> enable; | ||
| 580 | |||
| 581 | // Comparison operation for stencil testing | ||
| 582 | BitField<4, 3, CompareFunc> func; | ||
| 583 | |||
| 584 | // Mask used to control writing to the stencil buffer | ||
| 585 | BitField<8, 8, u32> write_mask; | ||
| 586 | |||
| 587 | // Value to compare against for stencil testing | ||
| 588 | BitField<16, 8, u32> reference_value; | ||
| 589 | |||
| 590 | // Mask to apply on stencil test inputs | ||
| 591 | BitField<24, 8, u32> input_mask; | ||
| 592 | }; | ||
| 593 | |||
| 594 | union { | ||
| 595 | // Raw value of this register | ||
| 596 | u32 raw_op; | ||
| 597 | |||
| 598 | // Action to perform when the stencil test fails | ||
| 599 | BitField<0, 3, StencilAction> action_stencil_fail; | ||
| 600 | |||
| 601 | // Action to perform when stencil testing passed but depth testing fails | ||
| 602 | BitField<4, 3, StencilAction> action_depth_fail; | ||
| 603 | |||
| 604 | // Action to perform when both stencil and depth testing pass | ||
| 605 | BitField<8, 3, StencilAction> action_depth_pass; | ||
| 606 | }; | ||
| 607 | } stencil_test; | ||
| 608 | |||
| 609 | union { | ||
| 610 | BitField<0, 1, u32> depth_test_enable; | ||
| 611 | BitField<4, 3, CompareFunc> depth_test_func; | ||
| 612 | BitField<8, 1, u32> red_enable; | ||
| 613 | BitField<9, 1, u32> green_enable; | ||
| 614 | BitField<10, 1, u32> blue_enable; | ||
| 615 | BitField<11, 1, u32> alpha_enable; | ||
| 616 | BitField<12, 1, u32> depth_write_enable; | ||
| 617 | }; | ||
| 618 | |||
| 619 | INSERT_PADDING_WORDS(0x8); | ||
| 620 | } output_merger; | ||
| 621 | |||
| 622 | // Components are laid out in reverse byte order, most significant bits first. | ||
| 623 | enum class ColorFormat : u32 { | ||
| 624 | RGBA8 = 0, | ||
| 625 | RGB8 = 1, | ||
| 626 | RGB5A1 = 2, | ||
| 627 | RGB565 = 3, | ||
| 628 | RGBA4 = 4, | ||
| 629 | }; | ||
| 630 | |||
| 631 | enum class DepthFormat : u32 { | ||
| 632 | D16 = 0, | ||
| 633 | D24 = 2, | ||
| 634 | D24S8 = 3, | ||
| 635 | }; | ||
| 636 | |||
| 637 | // Returns the number of bytes in the specified color format | ||
| 638 | static unsigned BytesPerColorPixel(ColorFormat format) { | ||
| 639 | switch (format) { | ||
| 640 | case ColorFormat::RGBA8: | ||
| 641 | return 4; | ||
| 642 | case ColorFormat::RGB8: | ||
| 643 | return 3; | ||
| 644 | case ColorFormat::RGB5A1: | ||
| 645 | case ColorFormat::RGB565: | ||
| 646 | case ColorFormat::RGBA4: | ||
| 647 | return 2; | ||
| 648 | default: | ||
| 649 | LOG_CRITICAL(HW_GPU, "Unknown color format %u", format); | ||
| 650 | UNIMPLEMENTED(); | ||
| 651 | } | ||
| 652 | } | ||
| 653 | |||
| 654 | struct FramebufferConfig { | ||
| 655 | INSERT_PADDING_WORDS(0x3); | ||
| 656 | |||
| 657 | union { | ||
| 658 | BitField<0, 4, u32> allow_color_write; // 0 = disable, else enable | ||
| 659 | }; | ||
| 660 | |||
| 661 | INSERT_PADDING_WORDS(0x1); | ||
| 662 | |||
| 663 | union { | ||
| 664 | BitField<0, 2, u32> allow_depth_stencil_write; // 0 = disable, else enable | ||
| 665 | }; | ||
| 666 | |||
| 667 | DepthFormat depth_format; // TODO: Should be a BitField! | ||
| 668 | BitField<16, 3, ColorFormat> color_format; | ||
| 669 | |||
| 670 | INSERT_PADDING_WORDS(0x4); | ||
| 671 | |||
| 672 | u32 depth_buffer_address; | ||
| 673 | u32 color_buffer_address; | ||
| 674 | |||
| 675 | union { | ||
| 676 | // Apparently, the framebuffer width is stored as expected, | ||
| 677 | // while the height is stored as the actual height minus one. | ||
| 678 | // Hence, don't access these fields directly but use the accessors | ||
| 679 | // GetWidth() and GetHeight() instead. | ||
| 680 | BitField<0, 11, u32> width; | ||
| 681 | BitField<12, 10, u32> height; | ||
| 682 | }; | ||
| 683 | |||
| 684 | INSERT_PADDING_WORDS(0x1); | ||
| 685 | |||
| 686 | inline u32 GetColorBufferPhysicalAddress() const { | ||
| 687 | return DecodeAddressRegister(color_buffer_address); | ||
| 688 | } | ||
| 689 | inline u32 GetDepthBufferPhysicalAddress() const { | ||
| 690 | return DecodeAddressRegister(depth_buffer_address); | ||
| 691 | } | ||
| 692 | |||
| 693 | inline u32 GetWidth() const { | ||
| 694 | return width; | ||
| 695 | } | ||
| 696 | |||
| 697 | inline u32 GetHeight() const { | ||
| 698 | return height + 1; | ||
| 699 | } | ||
| 700 | } framebuffer; | ||
| 701 | |||
| 702 | // Returns the number of bytes in the specified depth format | ||
| 703 | static u32 BytesPerDepthPixel(DepthFormat format) { | ||
| 704 | switch (format) { | ||
| 705 | case DepthFormat::D16: | ||
| 706 | return 2; | ||
| 707 | case DepthFormat::D24: | ||
| 708 | return 3; | ||
| 709 | case DepthFormat::D24S8: | ||
| 710 | return 4; | ||
| 711 | default: | ||
| 712 | LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); | ||
| 713 | UNIMPLEMENTED(); | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 717 | // Returns the number of bits per depth component of the specified depth format | ||
| 718 | static u32 DepthBitsPerPixel(DepthFormat format) { | ||
| 719 | switch (format) { | ||
| 720 | case DepthFormat::D16: | ||
| 721 | return 16; | ||
| 722 | case DepthFormat::D24: | ||
| 723 | case DepthFormat::D24S8: | ||
| 724 | return 24; | ||
| 725 | default: | ||
| 726 | LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); | ||
| 727 | UNIMPLEMENTED(); | ||
| 728 | } | ||
| 729 | } | ||
| 730 | |||
| 731 | INSERT_PADDING_WORDS(0x20); | ||
| 732 | |||
| 733 | enum class LightingSampler { | ||
| 734 | Distribution0 = 0, | ||
| 735 | Distribution1 = 1, | ||
| 736 | Fresnel = 3, | ||
| 737 | ReflectBlue = 4, | ||
| 738 | ReflectGreen = 5, | ||
| 739 | ReflectRed = 6, | ||
| 740 | SpotlightAttenuation = 8, | ||
| 741 | DistanceAttenuation = 16, | ||
| 742 | }; | ||
| 743 | |||
| 744 | /** | ||
| 745 | * Pica fragment lighting supports using different LUTs for each lighting component: | ||
| 746 | * Reflectance R, G, and B channels, distribution function for specular components 0 and 1, | ||
| 747 | * fresnel factor, and spotlight attenuation. Furthermore, which LUTs are used for each channel | ||
| 748 | * (or whether a channel is enabled at all) is specified by various pre-defined lighting | ||
| 749 | * configurations. With configurations that require more LUTs, more cycles are required on HW to | ||
| 750 | * perform lighting computations. | ||
| 751 | */ | ||
| 752 | enum class LightingConfig { | ||
| 753 | Config0 = 0, ///< Reflect Red, Distribution 0, Spotlight | ||
| 754 | Config1 = 1, ///< Reflect Red, Fresnel, Spotlight | ||
| 755 | Config2 = 2, ///< Reflect Red, Distribution 0/1 | ||
| 756 | Config3 = 3, ///< Distribution 0/1, Fresnel | ||
| 757 | Config4 = 4, ///< Reflect Red/Green/Blue, Distribution 0/1, Spotlight | ||
| 758 | Config5 = 5, ///< Reflect Red/Green/Blue, Distribution 0, Fresnel, Spotlight | ||
| 759 | Config6 = 6, ///< Reflect Red, Distribution 0/1, Fresnel, Spotlight | ||
| 760 | Config7 = 8, ///< Reflect Red/Green/Blue, Distribution 0/1, Fresnel, Spotlight | ||
| 761 | ///< NOTE: '8' is intentional, '7' does not appear to be a valid configuration | ||
| 762 | }; | ||
| 763 | |||
| 764 | /// Selects which lighting components are affected by fresnel | ||
| 765 | enum class LightingFresnelSelector { | ||
| 766 | None = 0, ///< Fresnel is disabled | ||
| 767 | PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel | ||
| 768 | SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel | ||
| 769 | Both = | ||
| 770 | PrimaryAlpha | | ||
| 771 | SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel | ||
| 772 | }; | ||
| 773 | |||
| 774 | /// Factor used to scale the output of a lighting LUT | ||
| 775 | enum class LightingScale { | ||
| 776 | Scale1 = 0, ///< Scale is 1x | ||
| 777 | Scale2 = 1, ///< Scale is 2x | ||
| 778 | Scale4 = 2, ///< Scale is 4x | ||
| 779 | Scale8 = 3, ///< Scale is 8x | ||
| 780 | Scale1_4 = 6, ///< Scale is 0.25x | ||
| 781 | Scale1_2 = 7, ///< Scale is 0.5x | ||
| 782 | }; | ||
| 783 | |||
| 784 | enum class LightingLutInput { | ||
| 785 | NH = 0, // Cosine of the angle between the normal and half-angle vectors | ||
| 786 | VH = 1, // Cosine of the angle between the view and half-angle vectors | ||
| 787 | NV = 2, // Cosine of the angle between the normal and the view vector | ||
| 788 | LN = 3, // Cosine of the angle between the light and the normal vectors | ||
| 789 | }; | ||
| 790 | |||
| 791 | enum class LightingBumpMode : u32 { | ||
| 792 | None = 0, | ||
| 793 | NormalMap = 1, | ||
| 794 | TangentMap = 2, | ||
| 795 | }; | ||
| 796 | |||
| 797 | union LightColor { | ||
| 798 | BitField<0, 10, u32> b; | ||
| 799 | BitField<10, 10, u32> g; | ||
| 800 | BitField<20, 10, u32> r; | ||
| 801 | |||
| 802 | Math::Vec3f ToVec3f() const { | ||
| 803 | // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color | ||
| 804 | // component | ||
| 805 | return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); | ||
| 806 | } | ||
| 807 | }; | ||
| 808 | |||
| 809 | /// Returns true if the specified lighting sampler is supported by the current Pica lighting | ||
| 810 | /// configuration | ||
| 811 | static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) { | ||
| 812 | switch (sampler) { | ||
| 813 | case LightingSampler::Distribution0: | ||
| 814 | return (config != LightingConfig::Config1); | ||
| 815 | |||
| 816 | case LightingSampler::Distribution1: | ||
| 817 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && | ||
| 818 | (config != LightingConfig::Config5); | ||
| 819 | |||
| 820 | case LightingSampler::Fresnel: | ||
| 821 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && | ||
| 822 | (config != LightingConfig::Config4); | ||
| 823 | |||
| 824 | case LightingSampler::ReflectRed: | ||
| 825 | return (config != LightingConfig::Config3); | ||
| 826 | |||
| 827 | case LightingSampler::ReflectGreen: | ||
| 828 | case LightingSampler::ReflectBlue: | ||
| 829 | return (config == LightingConfig::Config4) || (config == LightingConfig::Config5) || | ||
| 830 | (config == LightingConfig::Config7); | ||
| 831 | default: | ||
| 832 | UNREACHABLE_MSG("Regs::IsLightingSamplerSupported: Reached " | ||
| 833 | "unreachable section, sampler should be one " | ||
| 834 | "of Distribution0, Distribution1, Fresnel, " | ||
| 835 | "ReflectRed, ReflectGreen or ReflectBlue, instead " | ||
| 836 | "got %i", | ||
| 837 | static_cast<int>(config)); | ||
| 838 | } | ||
| 839 | } | ||
| 840 | |||
| 841 | struct { | ||
| 842 | struct LightSrc { | ||
| 843 | LightColor specular_0; // material.specular_0 * light.specular_0 | ||
| 844 | LightColor specular_1; // material.specular_1 * light.specular_1 | ||
| 845 | LightColor diffuse; // material.diffuse * light.diffuse | ||
| 846 | LightColor ambient; // material.ambient * light.ambient | ||
| 847 | |||
| 848 | // Encoded as 16-bit floating point | ||
| 849 | union { | ||
| 850 | BitField<0, 16, u32> x; | ||
| 851 | BitField<16, 16, u32> y; | ||
| 852 | }; | ||
| 853 | union { | ||
| 854 | BitField<0, 16, u32> z; | ||
| 855 | }; | ||
| 856 | |||
| 857 | INSERT_PADDING_WORDS(0x3); | ||
| 858 | |||
| 859 | union { | ||
| 860 | BitField<0, 1, u32> directional; | ||
| 861 | BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0 | ||
| 862 | } config; | ||
| 863 | |||
| 864 | BitField<0, 20, u32> dist_atten_bias; | ||
| 865 | BitField<0, 20, u32> dist_atten_scale; | ||
| 866 | |||
| 867 | INSERT_PADDING_WORDS(0x4); | ||
| 868 | }; | ||
| 869 | static_assert(sizeof(LightSrc) == 0x10 * sizeof(u32), | ||
| 870 | "LightSrc structure must be 0x10 words"); | ||
| 871 | |||
| 872 | LightSrc light[8]; | ||
| 873 | LightColor global_ambient; // Emission + (material.ambient * lighting.ambient) | ||
| 874 | INSERT_PADDING_WORDS(0x1); | ||
| 875 | BitField<0, 3, u32> max_light_index; // Number of enabled lights - 1 | ||
| 876 | |||
| 877 | union { | ||
| 878 | BitField<2, 2, LightingFresnelSelector> fresnel_selector; | ||
| 879 | BitField<4, 4, LightingConfig> config; | ||
| 880 | BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2 | ||
| 881 | BitField<27, 1, u32> clamp_highlights; | ||
| 882 | BitField<28, 2, LightingBumpMode> bump_mode; | ||
| 883 | BitField<30, 1, u32> disable_bump_renorm; | ||
| 884 | } config0; | ||
| 885 | |||
| 886 | union { | ||
| 887 | BitField<16, 1, u32> disable_lut_d0; | ||
| 888 | BitField<17, 1, u32> disable_lut_d1; | ||
| 889 | BitField<19, 1, u32> disable_lut_fr; | ||
| 890 | BitField<20, 1, u32> disable_lut_rr; | ||
| 891 | BitField<21, 1, u32> disable_lut_rg; | ||
| 892 | BitField<22, 1, u32> disable_lut_rb; | ||
| 893 | |||
| 894 | // Each bit specifies whether distance attenuation should be applied for the | ||
| 895 | // corresponding light | ||
| 896 | |||
| 897 | BitField<24, 1, u32> disable_dist_atten_light_0; | ||
| 898 | BitField<25, 1, u32> disable_dist_atten_light_1; | ||
| 899 | BitField<26, 1, u32> disable_dist_atten_light_2; | ||
| 900 | BitField<27, 1, u32> disable_dist_atten_light_3; | ||
| 901 | BitField<28, 1, u32> disable_dist_atten_light_4; | ||
| 902 | BitField<29, 1, u32> disable_dist_atten_light_5; | ||
| 903 | BitField<30, 1, u32> disable_dist_atten_light_6; | ||
| 904 | BitField<31, 1, u32> disable_dist_atten_light_7; | ||
| 905 | } config1; | ||
| 906 | |||
| 907 | bool IsDistAttenDisabled(unsigned index) const { | ||
| 908 | const unsigned disable[] = { | ||
| 909 | config1.disable_dist_atten_light_0, config1.disable_dist_atten_light_1, | ||
| 910 | config1.disable_dist_atten_light_2, config1.disable_dist_atten_light_3, | ||
| 911 | config1.disable_dist_atten_light_4, config1.disable_dist_atten_light_5, | ||
| 912 | config1.disable_dist_atten_light_6, config1.disable_dist_atten_light_7}; | ||
| 913 | return disable[index] != 0; | ||
| 914 | } | ||
| 915 | |||
| 916 | union { | ||
| 917 | BitField<0, 8, u32> index; ///< Index at which to set data in the LUT | ||
| 918 | BitField<8, 5, u32> type; ///< Type of LUT for which to set data | ||
| 919 | } lut_config; | ||
| 920 | |||
| 921 | BitField<0, 1, u32> disable; | ||
| 922 | INSERT_PADDING_WORDS(0x1); | ||
| 923 | |||
| 924 | // When data is written to any of these registers, it gets written to the lookup table of | ||
| 925 | // the selected type at the selected index, specified above in the `lut_config` register. | ||
| 926 | // With each write, `lut_config.index` is incremented. It does not matter which of these | ||
| 927 | // registers is written to, the behavior will be the same. | ||
| 928 | u32 lut_data[8]; | ||
| 929 | |||
| 930 | // These are used to specify if absolute (abs) value should be used for each LUT index. When | ||
| 931 | // abs mode is disabled, LUT indexes are in the range of (-1.0, 1.0). Otherwise, they are in | ||
| 932 | // the range of (0.0, 1.0). | ||
| 933 | union { | ||
| 934 | BitField<1, 1, u32> disable_d0; | ||
| 935 | BitField<5, 1, u32> disable_d1; | ||
| 936 | BitField<9, 1, u32> disable_sp; | ||
| 937 | BitField<13, 1, u32> disable_fr; | ||
| 938 | BitField<17, 1, u32> disable_rb; | ||
| 939 | BitField<21, 1, u32> disable_rg; | ||
| 940 | BitField<25, 1, u32> disable_rr; | ||
| 941 | } abs_lut_input; | ||
| 942 | |||
| 943 | union { | ||
| 944 | BitField<0, 3, LightingLutInput> d0; | ||
| 945 | BitField<4, 3, LightingLutInput> d1; | ||
| 946 | BitField<8, 3, LightingLutInput> sp; | ||
| 947 | BitField<12, 3, LightingLutInput> fr; | ||
| 948 | BitField<16, 3, LightingLutInput> rb; | ||
| 949 | BitField<20, 3, LightingLutInput> rg; | ||
| 950 | BitField<24, 3, LightingLutInput> rr; | ||
| 951 | } lut_input; | ||
| 952 | |||
| 953 | union { | ||
| 954 | BitField<0, 3, LightingScale> d0; | ||
| 955 | BitField<4, 3, LightingScale> d1; | ||
| 956 | BitField<8, 3, LightingScale> sp; | ||
| 957 | BitField<12, 3, LightingScale> fr; | ||
| 958 | BitField<16, 3, LightingScale> rb; | ||
| 959 | BitField<20, 3, LightingScale> rg; | ||
| 960 | BitField<24, 3, LightingScale> rr; | ||
| 961 | |||
| 962 | static float GetScale(LightingScale scale) { | ||
| 963 | switch (scale) { | ||
| 964 | case LightingScale::Scale1: | ||
| 965 | return 1.0f; | ||
| 966 | case LightingScale::Scale2: | ||
| 967 | return 2.0f; | ||
| 968 | case LightingScale::Scale4: | ||
| 969 | return 4.0f; | ||
| 970 | case LightingScale::Scale8: | ||
| 971 | return 8.0f; | ||
| 972 | case LightingScale::Scale1_4: | ||
| 973 | return 0.25f; | ||
| 974 | case LightingScale::Scale1_2: | ||
| 975 | return 0.5f; | ||
| 976 | } | ||
| 977 | return 0.0f; | ||
| 978 | } | ||
| 979 | } lut_scale; | ||
| 980 | |||
| 981 | INSERT_PADDING_WORDS(0x6); | ||
| 982 | |||
| 983 | union { | ||
| 984 | // There are 8 light enable "slots", corresponding to the total number of lights | ||
| 985 | // supported by Pica. For N enabled lights (specified by register 0x1c2, or 'src_num' | ||
| 986 | // above), the first N slots below will be set to integers within the range of 0-7, | ||
| 987 | // corresponding to the actual light that is enabled for each slot. | ||
| 988 | |||
| 989 | BitField<0, 3, u32> slot_0; | ||
| 990 | BitField<4, 3, u32> slot_1; | ||
| 991 | BitField<8, 3, u32> slot_2; | ||
| 992 | BitField<12, 3, u32> slot_3; | ||
| 993 | BitField<16, 3, u32> slot_4; | ||
| 994 | BitField<20, 3, u32> slot_5; | ||
| 995 | BitField<24, 3, u32> slot_6; | ||
| 996 | BitField<28, 3, u32> slot_7; | ||
| 997 | |||
| 998 | unsigned GetNum(unsigned index) const { | ||
| 999 | const unsigned enable_slots[] = {slot_0, slot_1, slot_2, slot_3, | ||
| 1000 | slot_4, slot_5, slot_6, slot_7}; | ||
| 1001 | return enable_slots[index]; | ||
| 1002 | } | ||
| 1003 | } light_enable; | ||
| 1004 | } lighting; | ||
| 1005 | |||
| 1006 | INSERT_PADDING_WORDS(0x26); | ||
| 1007 | |||
| 1008 | enum class VertexAttributeFormat : u64 { | ||
| 1009 | BYTE = 0, | ||
| 1010 | UBYTE = 1, | ||
| 1011 | SHORT = 2, | ||
| 1012 | FLOAT = 3, | ||
| 1013 | }; | ||
| 1014 | |||
| 1015 | struct { | ||
| 1016 | BitField<0, 29, u32> base_address; | ||
| 1017 | |||
| 1018 | u32 GetPhysicalBaseAddress() const { | ||
| 1019 | return DecodeAddressRegister(base_address); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | // Descriptor for internal vertex attributes | ||
| 1023 | union { | ||
| 1024 | BitField<0, 2, VertexAttributeFormat> format0; // size of one element | ||
| 1025 | BitField<2, 2, u64> size0; // number of elements minus 1 | ||
| 1026 | BitField<4, 2, VertexAttributeFormat> format1; | ||
| 1027 | BitField<6, 2, u64> size1; | ||
| 1028 | BitField<8, 2, VertexAttributeFormat> format2; | ||
| 1029 | BitField<10, 2, u64> size2; | ||
| 1030 | BitField<12, 2, VertexAttributeFormat> format3; | ||
| 1031 | BitField<14, 2, u64> size3; | ||
| 1032 | BitField<16, 2, VertexAttributeFormat> format4; | ||
| 1033 | BitField<18, 2, u64> size4; | ||
| 1034 | BitField<20, 2, VertexAttributeFormat> format5; | ||
| 1035 | BitField<22, 2, u64> size5; | ||
| 1036 | BitField<24, 2, VertexAttributeFormat> format6; | ||
| 1037 | BitField<26, 2, u64> size6; | ||
| 1038 | BitField<28, 2, VertexAttributeFormat> format7; | ||
| 1039 | BitField<30, 2, u64> size7; | ||
| 1040 | BitField<32, 2, VertexAttributeFormat> format8; | ||
| 1041 | BitField<34, 2, u64> size8; | ||
| 1042 | BitField<36, 2, VertexAttributeFormat> format9; | ||
| 1043 | BitField<38, 2, u64> size9; | ||
| 1044 | BitField<40, 2, VertexAttributeFormat> format10; | ||
| 1045 | BitField<42, 2, u64> size10; | ||
| 1046 | BitField<44, 2, VertexAttributeFormat> format11; | ||
| 1047 | BitField<46, 2, u64> size11; | ||
| 1048 | |||
| 1049 | BitField<48, 12, u64> attribute_mask; | ||
| 1050 | |||
| 1051 | // number of total attributes minus 1 | ||
| 1052 | BitField<60, 4, u64> max_attribute_index; | ||
| 1053 | }; | ||
| 1054 | |||
| 1055 | inline VertexAttributeFormat GetFormat(int n) const { | ||
| 1056 | VertexAttributeFormat formats[] = {format0, format1, format2, format3, | ||
| 1057 | format4, format5, format6, format7, | ||
| 1058 | format8, format9, format10, format11}; | ||
| 1059 | return formats[n]; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | inline int GetNumElements(int n) const { | ||
| 1063 | u64 sizes[] = {size0, size1, size2, size3, size4, size5, | ||
| 1064 | size6, size7, size8, size9, size10, size11}; | ||
| 1065 | return (int)sizes[n] + 1; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | inline int GetElementSizeInBytes(int n) const { | ||
| 1069 | return (GetFormat(n) == VertexAttributeFormat::FLOAT) | ||
| 1070 | ? 4 | ||
| 1071 | : (GetFormat(n) == VertexAttributeFormat::SHORT) ? 2 : 1; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | inline int GetStride(int n) const { | ||
| 1075 | return GetNumElements(n) * GetElementSizeInBytes(n); | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | inline bool IsDefaultAttribute(int id) const { | ||
| 1079 | return (id >= 12) || (attribute_mask & (1ULL << id)) != 0; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | inline int GetNumTotalAttributes() const { | ||
| 1083 | return (int)max_attribute_index + 1; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | // Attribute loaders map the source vertex data to input attributes | ||
| 1087 | // This e.g. allows to load different attributes from different memory locations | ||
| 1088 | struct { | ||
| 1089 | // Source attribute data offset from the base address | ||
| 1090 | u32 data_offset; | ||
| 1091 | |||
| 1092 | union { | ||
| 1093 | BitField<0, 4, u64> comp0; | ||
| 1094 | BitField<4, 4, u64> comp1; | ||
| 1095 | BitField<8, 4, u64> comp2; | ||
| 1096 | BitField<12, 4, u64> comp3; | ||
| 1097 | BitField<16, 4, u64> comp4; | ||
| 1098 | BitField<20, 4, u64> comp5; | ||
| 1099 | BitField<24, 4, u64> comp6; | ||
| 1100 | BitField<28, 4, u64> comp7; | ||
| 1101 | BitField<32, 4, u64> comp8; | ||
| 1102 | BitField<36, 4, u64> comp9; | ||
| 1103 | BitField<40, 4, u64> comp10; | ||
| 1104 | BitField<44, 4, u64> comp11; | ||
| 1105 | |||
| 1106 | // bytes for a single vertex in this loader | ||
| 1107 | BitField<48, 8, u64> byte_count; | ||
| 1108 | |||
| 1109 | BitField<60, 4, u64> component_count; | ||
| 1110 | }; | ||
| 1111 | |||
| 1112 | inline int GetComponent(int n) const { | ||
| 1113 | u64 components[] = {comp0, comp1, comp2, comp3, comp4, comp5, | ||
| 1114 | comp6, comp7, comp8, comp9, comp10, comp11}; | ||
| 1115 | return (int)components[n]; | ||
| 1116 | } | ||
| 1117 | } attribute_loaders[12]; | ||
| 1118 | } vertex_attributes; | ||
| 1119 | |||
| 1120 | struct { | ||
| 1121 | enum IndexFormat : u32 { | ||
| 1122 | BYTE = 0, | ||
| 1123 | SHORT = 1, | ||
| 1124 | }; | ||
| 1125 | |||
| 1126 | union { | ||
| 1127 | BitField<0, 31, u32> offset; // relative to base attribute address | ||
| 1128 | BitField<31, 1, IndexFormat> format; | ||
| 1129 | }; | ||
| 1130 | } index_array; | ||
| 1131 | |||
| 1132 | // Number of vertices to render | ||
| 1133 | u32 num_vertices; | ||
| 1134 | |||
| 1135 | INSERT_PADDING_WORDS(0x1); | ||
| 1136 | |||
| 1137 | // The index of the first vertex to render | ||
| 1138 | u32 vertex_offset; | ||
| 1139 | |||
| 1140 | INSERT_PADDING_WORDS(0x3); | ||
| 1141 | |||
| 1142 | // These two trigger rendering of triangles | ||
| 1143 | u32 trigger_draw; | ||
| 1144 | u32 trigger_draw_indexed; | ||
| 1145 | |||
| 1146 | INSERT_PADDING_WORDS(0x2); | ||
| 1147 | |||
| 1148 | // These registers are used to setup the default "fall-back" vertex shader attributes | ||
| 1149 | struct { | ||
| 1150 | // Index of the current default attribute | ||
| 1151 | u32 index; | ||
| 1152 | |||
| 1153 | // Writing to these registers sets the "current" default attribute. | ||
| 1154 | u32 set_value[3]; | ||
| 1155 | } vs_default_attributes_setup; | ||
| 1156 | |||
| 1157 | INSERT_PADDING_WORDS(0x2); | ||
| 1158 | |||
| 1159 | struct { | ||
| 1160 | // There are two channels that can be used to configure the next command buffer, which | ||
| 1161 | // can be then executed by writing to the "trigger" registers. There are two reasons why a | ||
| 1162 | // game might use this feature: | ||
| 1163 | // 1) With this, an arbitrary number of additional command buffers may be executed in | ||
| 1164 | // sequence without requiring any intervention of the CPU after the initial one is | ||
| 1165 | // kicked off. | ||
| 1166 | // 2) Games can configure these registers to provide a command list subroutine mechanism. | ||
| 1167 | |||
| 1168 | BitField<0, 20, u32> size[2]; ///< Size (in bytes / 8) of each channel's command buffer | ||
| 1169 | BitField<0, 28, u32> addr[2]; ///< Physical address / 8 of each channel's command buffer | ||
| 1170 | u32 trigger[2]; ///< Triggers execution of the channel's command buffer when written to | ||
| 1171 | |||
| 1172 | unsigned GetSize(unsigned index) const { | ||
| 1173 | ASSERT(index < 2); | ||
| 1174 | return 8 * size[index]; | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | PAddr GetPhysicalAddress(unsigned index) const { | ||
| 1178 | ASSERT(index < 2); | ||
| 1179 | return (PAddr)(8 * addr[index]); | ||
| 1180 | } | ||
| 1181 | } command_buffer; | ||
| 1182 | |||
| 1183 | INSERT_PADDING_WORDS(4); | ||
| 1184 | |||
| 1185 | /// Number of input attributes to the vertex shader minus 1 | ||
| 1186 | BitField<0, 4, u32> max_input_attrib_index; | ||
| 1187 | |||
| 1188 | INSERT_PADDING_WORDS(2); | ||
| 1189 | |||
| 1190 | enum class GPUMode : u32 { | ||
| 1191 | Drawing = 0, | ||
| 1192 | Configuring = 1, | ||
| 1193 | }; | ||
| 1194 | |||
| 1195 | GPUMode gpu_mode; | ||
| 1196 | |||
| 1197 | INSERT_PADDING_WORDS(0x18); | ||
| 1198 | |||
| 1199 | enum class TriangleTopology : u32 { | ||
| 1200 | List = 0, | ||
| 1201 | Strip = 1, | ||
| 1202 | Fan = 2, | ||
| 1203 | Shader = 3, // Programmable setup unit implemented in a geometry shader | ||
| 1204 | }; | ||
| 1205 | |||
| 1206 | BitField<8, 2, TriangleTopology> triangle_topology; | ||
| 1207 | |||
| 1208 | u32 restart_primitive; | ||
| 1209 | |||
| 1210 | INSERT_PADDING_WORDS(0x20); | ||
| 1211 | |||
| 1212 | struct ShaderConfig { | ||
| 1213 | BitField<0, 16, u32> bool_uniforms; | ||
| 1214 | |||
| 1215 | union { | ||
| 1216 | BitField<0, 8, u32> x; | ||
| 1217 | BitField<8, 8, u32> y; | ||
| 1218 | BitField<16, 8, u32> z; | ||
| 1219 | BitField<24, 8, u32> w; | ||
| 1220 | } int_uniforms[4]; | ||
| 1221 | |||
| 1222 | INSERT_PADDING_WORDS(0x4); | ||
| 1223 | |||
| 1224 | union { | ||
| 1225 | // Number of input attributes to shader unit - 1 | ||
| 1226 | BitField<0, 4, u32> max_input_attribute_index; | ||
| 1227 | }; | ||
| 1228 | |||
| 1229 | // Offset to shader program entry point (in words) | ||
| 1230 | BitField<0, 16, u32> main_offset; | ||
| 1231 | |||
| 1232 | /// Maps input attributes to registers. 4-bits per attribute, specifying a register index | ||
| 1233 | u32 input_attribute_to_register_map_low; | ||
| 1234 | u32 input_attribute_to_register_map_high; | ||
| 1235 | |||
| 1236 | unsigned int GetRegisterForAttribute(unsigned int attribute_index) const { | ||
| 1237 | u64 map = ((u64)input_attribute_to_register_map_high << 32) | | ||
| 1238 | (u64)input_attribute_to_register_map_low; | ||
| 1239 | return (map >> (attribute_index * 4)) & 0b1111; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | BitField<0, 16, u32> output_mask; | ||
| 1243 | |||
| 1244 | // 0x28E, CODETRANSFER_END | ||
| 1245 | INSERT_PADDING_WORDS(0x2); | ||
| 1246 | |||
| 1247 | struct { | ||
| 1248 | enum Format : u32 { | ||
| 1249 | FLOAT24 = 0, | ||
| 1250 | FLOAT32 = 1, | ||
| 1251 | }; | ||
| 1252 | |||
| 1253 | bool IsFloat32() const { | ||
| 1254 | return format == FLOAT32; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | union { | ||
| 1258 | // Index of the next uniform to write to | ||
| 1259 | // TODO: ctrulib uses 8 bits for this, however that seems to yield lots of invalid | ||
| 1260 | // indices | ||
| 1261 | // TODO: Maybe the uppermost index is for the geometry shader? Investigate! | ||
| 1262 | BitField<0, 7, u32> index; | ||
| 1263 | |||
| 1264 | BitField<31, 1, Format> format; | ||
| 1265 | }; | ||
| 1266 | |||
| 1267 | // Writing to these registers sets the current uniform. | ||
| 1268 | u32 set_value[8]; | ||
| 1269 | |||
| 1270 | } uniform_setup; | ||
| 1271 | |||
| 1272 | INSERT_PADDING_WORDS(0x2); | ||
| 1273 | |||
| 1274 | struct { | ||
| 1275 | // Offset of the next instruction to write code to. | ||
| 1276 | // Incremented with each instruction write. | ||
| 1277 | u32 offset; | ||
| 1278 | |||
| 1279 | // Writing to these registers sets the "current" word in the shader program. | ||
| 1280 | u32 set_word[8]; | ||
| 1281 | } program; | ||
| 1282 | |||
| 1283 | INSERT_PADDING_WORDS(0x1); | ||
| 1284 | |||
| 1285 | // This register group is used to load an internal table of swizzling patterns, | ||
| 1286 | // which are indexed by each shader instruction to specify vector component swizzling. | ||
| 1287 | struct { | ||
| 1288 | // Offset of the next swizzle pattern to write code to. | ||
| 1289 | // Incremented with each instruction write. | ||
| 1290 | u32 offset; | ||
| 1291 | |||
| 1292 | // Writing to these registers sets the current swizzle pattern in the table. | ||
| 1293 | u32 set_word[8]; | ||
| 1294 | } swizzle_patterns; | ||
| 1295 | |||
| 1296 | INSERT_PADDING_WORDS(0x2); | ||
| 1297 | }; | ||
| 1298 | |||
| 1299 | ShaderConfig gs; | ||
| 1300 | ShaderConfig vs; | ||
| 1301 | |||
| 1302 | INSERT_PADDING_WORDS(0x20); | ||
| 1303 | |||
| 1304 | // Map register indices to names readable by humans | ||
| 1305 | // Used for debugging purposes, so performance is not an issue here | ||
| 1306 | static std::string GetCommandName(int index); | ||
| 1307 | |||
| 1308 | static constexpr size_t NumIds() { | ||
| 1309 | return sizeof(Regs) / sizeof(u32); | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | const u32& operator[](int index) const { | ||
| 1313 | const u32* content = reinterpret_cast<const u32*>(this); | ||
| 1314 | return content[index]; | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | u32& operator[](int index) { | ||
| 1318 | u32* content = reinterpret_cast<u32*>(this); | ||
| 1319 | return content[index]; | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | private: | ||
| 1323 | /* | ||
| 1324 | * Most physical addresses which Pica registers refer to are 8-byte aligned. | ||
| 1325 | * This function should be used to get the address from a raw register value. | ||
| 1326 | */ | ||
| 1327 | static inline u32 DecodeAddressRegister(u32 register_value) { | ||
| 1328 | return register_value * 8; | ||
| 1329 | } | ||
| 1330 | }; | ||
| 1331 | |||
| 1332 | // TODO: MSVC does not support using offsetof() on non-static data members even though this | ||
| 1333 | // is technically allowed since C++11. This macro should be enabled once MSVC adds | ||
| 1334 | // support for that. | ||
| 1335 | #ifndef _MSC_VER | ||
| 1336 | #define ASSERT_REG_POSITION(field_name, position) \ | ||
| 1337 | static_assert(offsetof(Regs, field_name) == position * 4, \ | ||
| 1338 | "Field " #field_name " has invalid position") | ||
| 1339 | |||
| 1340 | ASSERT_REG_POSITION(trigger_irq, 0x10); | ||
| 1341 | ASSERT_REG_POSITION(cull_mode, 0x40); | ||
| 1342 | ASSERT_REG_POSITION(viewport_size_x, 0x41); | ||
| 1343 | ASSERT_REG_POSITION(viewport_size_y, 0x43); | ||
| 1344 | ASSERT_REG_POSITION(viewport_depth_range, 0x4d); | ||
| 1345 | ASSERT_REG_POSITION(viewport_depth_near_plane, 0x4e); | ||
| 1346 | ASSERT_REG_POSITION(vs_output_attributes[0], 0x50); | ||
| 1347 | ASSERT_REG_POSITION(vs_output_attributes[1], 0x51); | ||
| 1348 | ASSERT_REG_POSITION(scissor_test, 0x65); | ||
| 1349 | ASSERT_REG_POSITION(viewport_corner, 0x68); | ||
| 1350 | ASSERT_REG_POSITION(depthmap_enable, 0x6D); | ||
| 1351 | ASSERT_REG_POSITION(texture0_enable, 0x80); | ||
| 1352 | ASSERT_REG_POSITION(texture0, 0x81); | ||
| 1353 | ASSERT_REG_POSITION(texture0_format, 0x8e); | ||
| 1354 | ASSERT_REG_POSITION(fragment_lighting_enable, 0x8f); | ||
| 1355 | ASSERT_REG_POSITION(texture1, 0x91); | ||
| 1356 | ASSERT_REG_POSITION(texture1_format, 0x96); | ||
| 1357 | ASSERT_REG_POSITION(texture2, 0x99); | ||
| 1358 | ASSERT_REG_POSITION(texture2_format, 0x9e); | ||
| 1359 | ASSERT_REG_POSITION(tev_stage0, 0xc0); | ||
| 1360 | ASSERT_REG_POSITION(tev_stage1, 0xc8); | ||
| 1361 | ASSERT_REG_POSITION(tev_stage2, 0xd0); | ||
| 1362 | ASSERT_REG_POSITION(tev_stage3, 0xd8); | ||
| 1363 | ASSERT_REG_POSITION(tev_combiner_buffer_input, 0xe0); | ||
| 1364 | ASSERT_REG_POSITION(fog_mode, 0xe0); | ||
| 1365 | ASSERT_REG_POSITION(fog_color, 0xe1); | ||
| 1366 | ASSERT_REG_POSITION(fog_lut_offset, 0xe6); | ||
| 1367 | ASSERT_REG_POSITION(fog_lut_data, 0xe8); | ||
| 1368 | ASSERT_REG_POSITION(tev_stage4, 0xf0); | ||
| 1369 | ASSERT_REG_POSITION(tev_stage5, 0xf8); | ||
| 1370 | ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd); | ||
| 1371 | ASSERT_REG_POSITION(output_merger, 0x100); | ||
| 1372 | ASSERT_REG_POSITION(framebuffer, 0x110); | ||
| 1373 | ASSERT_REG_POSITION(lighting, 0x140); | ||
| 1374 | ASSERT_REG_POSITION(vertex_attributes, 0x200); | ||
| 1375 | ASSERT_REG_POSITION(index_array, 0x227); | ||
| 1376 | ASSERT_REG_POSITION(num_vertices, 0x228); | ||
| 1377 | ASSERT_REG_POSITION(vertex_offset, 0x22a); | ||
| 1378 | ASSERT_REG_POSITION(trigger_draw, 0x22e); | ||
| 1379 | ASSERT_REG_POSITION(trigger_draw_indexed, 0x22f); | ||
| 1380 | ASSERT_REG_POSITION(vs_default_attributes_setup, 0x232); | ||
| 1381 | ASSERT_REG_POSITION(command_buffer, 0x238); | ||
| 1382 | ASSERT_REG_POSITION(gpu_mode, 0x245); | ||
| 1383 | ASSERT_REG_POSITION(triangle_topology, 0x25e); | ||
| 1384 | ASSERT_REG_POSITION(restart_primitive, 0x25f); | ||
| 1385 | ASSERT_REG_POSITION(gs, 0x280); | ||
| 1386 | ASSERT_REG_POSITION(vs, 0x2b0); | ||
| 1387 | |||
| 1388 | #undef ASSERT_REG_POSITION | ||
| 1389 | #endif // !defined(_MSC_VER) | ||
| 1390 | |||
| 1391 | static_assert(sizeof(Regs::ShaderConfig) == 0x30 * sizeof(u32), | ||
| 1392 | "ShaderConfig structure has incorrect size"); | ||
| 1393 | |||
| 1394 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value | ||
| 1395 | // anyway. | ||
| 1396 | static_assert(sizeof(Regs) <= 0x300 * sizeof(u32), | ||
| 1397 | "Register set structure larger than it should be"); | ||
| 1398 | static_assert(sizeof(Regs) >= 0x300 * sizeof(u32), | ||
| 1399 | "Register set structure smaller than it should be"); | ||
| 1400 | |||
| 1401 | /// Initialize Pica state | 10 | /// Initialize Pica state |
| 1402 | void Init(); | 11 | void Init(); |
| 1403 | 12 | ||
diff --git a/src/video_core/pica_state.h b/src/video_core/pica_state.h index 785d05650..af7536d11 100644 --- a/src/video_core/pica_state.h +++ b/src/video_core/pica_state.h | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "video_core/pica.h" | ||
| 11 | #include "video_core/primitive_assembly.h" | 10 | #include "video_core/primitive_assembly.h" |
| 11 | #include "video_core/regs.h" | ||
| 12 | #include "video_core/shader/shader.h" | 12 | #include "video_core/shader/shader.h" |
| 13 | 13 | ||
| 14 | namespace Pica { | 14 | namespace Pica { |
diff --git a/src/video_core/primitive_assembly.cpp b/src/video_core/primitive_assembly.cpp index e71ff5719..acd2ac5e2 100644 --- a/src/video_core/primitive_assembly.cpp +++ b/src/video_core/primitive_assembly.cpp | |||
| @@ -3,14 +3,14 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "video_core/pica.h" | ||
| 7 | #include "video_core/primitive_assembly.h" | 6 | #include "video_core/primitive_assembly.h" |
| 7 | #include "video_core/regs_pipeline.h" | ||
| 8 | #include "video_core/shader/shader.h" | 8 | #include "video_core/shader/shader.h" |
| 9 | 9 | ||
| 10 | namespace Pica { | 10 | namespace Pica { |
| 11 | 11 | ||
| 12 | template <typename VertexType> | 12 | template <typename VertexType> |
| 13 | PrimitiveAssembler<VertexType>::PrimitiveAssembler(Regs::TriangleTopology topology) | 13 | PrimitiveAssembler<VertexType>::PrimitiveAssembler(PipelineRegs::TriangleTopology topology) |
| 14 | : topology(topology), buffer_index(0) {} | 14 | : topology(topology), buffer_index(0) {} |
| 15 | 15 | ||
| 16 | template <typename VertexType> | 16 | template <typename VertexType> |
| @@ -18,8 +18,8 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(const VertexType& vtx, | |||
| 18 | TriangleHandler triangle_handler) { | 18 | TriangleHandler triangle_handler) { |
| 19 | switch (topology) { | 19 | switch (topology) { |
| 20 | // TODO: Figure out what's different with TriangleTopology::Shader. | 20 | // TODO: Figure out what's different with TriangleTopology::Shader. |
| 21 | case Regs::TriangleTopology::List: | 21 | case PipelineRegs::TriangleTopology::List: |
| 22 | case Regs::TriangleTopology::Shader: | 22 | case PipelineRegs::TriangleTopology::Shader: |
| 23 | if (buffer_index < 2) { | 23 | if (buffer_index < 2) { |
| 24 | buffer[buffer_index++] = vtx; | 24 | buffer[buffer_index++] = vtx; |
| 25 | } else { | 25 | } else { |
| @@ -29,8 +29,8 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(const VertexType& vtx, | |||
| 29 | } | 29 | } |
| 30 | break; | 30 | break; |
| 31 | 31 | ||
| 32 | case Regs::TriangleTopology::Strip: | 32 | case PipelineRegs::TriangleTopology::Strip: |
| 33 | case Regs::TriangleTopology::Fan: | 33 | case PipelineRegs::TriangleTopology::Fan: |
| 34 | if (strip_ready) | 34 | if (strip_ready) |
| 35 | triangle_handler(buffer[0], buffer[1], vtx); | 35 | triangle_handler(buffer[0], buffer[1], vtx); |
| 36 | 36 | ||
| @@ -38,9 +38,9 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(const VertexType& vtx, | |||
| 38 | 38 | ||
| 39 | strip_ready |= (buffer_index == 1); | 39 | strip_ready |= (buffer_index == 1); |
| 40 | 40 | ||
| 41 | if (topology == Regs::TriangleTopology::Strip) | 41 | if (topology == PipelineRegs::TriangleTopology::Strip) |
| 42 | buffer_index = !buffer_index; | 42 | buffer_index = !buffer_index; |
| 43 | else if (topology == Regs::TriangleTopology::Fan) | 43 | else if (topology == PipelineRegs::TriangleTopology::Fan) |
| 44 | buffer_index = 1; | 44 | buffer_index = 1; |
| 45 | break; | 45 | break; |
| 46 | 46 | ||
| @@ -57,7 +57,7 @@ void PrimitiveAssembler<VertexType>::Reset() { | |||
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | template <typename VertexType> | 59 | template <typename VertexType> |
| 60 | void PrimitiveAssembler<VertexType>::Reconfigure(Regs::TriangleTopology topology) { | 60 | void PrimitiveAssembler<VertexType>::Reconfigure(PipelineRegs::TriangleTopology topology) { |
| 61 | Reset(); | 61 | Reset(); |
| 62 | this->topology = topology; | 62 | this->topology = topology; |
| 63 | } | 63 | } |
diff --git a/src/video_core/primitive_assembly.h b/src/video_core/primitive_assembly.h index 24da47382..e8eccdf27 100644 --- a/src/video_core/primitive_assembly.h +++ b/src/video_core/primitive_assembly.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <functional> | 7 | #include <functional> |
| 8 | #include "video_core/pica.h" | 8 | #include "video_core/regs_pipeline.h" |
| 9 | 9 | ||
| 10 | namespace Pica { | 10 | namespace Pica { |
| 11 | 11 | ||
| @@ -18,7 +18,8 @@ struct PrimitiveAssembler { | |||
| 18 | using TriangleHandler = | 18 | using TriangleHandler = |
| 19 | std::function<void(const VertexType& v0, const VertexType& v1, const VertexType& v2)>; | 19 | std::function<void(const VertexType& v0, const VertexType& v1, const VertexType& v2)>; |
| 20 | 20 | ||
| 21 | PrimitiveAssembler(Regs::TriangleTopology topology = Regs::TriangleTopology::List); | 21 | PrimitiveAssembler( |
| 22 | PipelineRegs::TriangleTopology topology = PipelineRegs::TriangleTopology::List); | ||
| 22 | 23 | ||
| 23 | /* | 24 | /* |
| 24 | * Queues a vertex, builds primitives from the vertex queue according to the given | 25 | * Queues a vertex, builds primitives from the vertex queue according to the given |
| @@ -36,10 +37,10 @@ struct PrimitiveAssembler { | |||
| 36 | /** | 37 | /** |
| 37 | * Reconfigures the PrimitiveAssembler to use a different triangle topology. | 38 | * Reconfigures the PrimitiveAssembler to use a different triangle topology. |
| 38 | */ | 39 | */ |
| 39 | void Reconfigure(Regs::TriangleTopology topology); | 40 | void Reconfigure(PipelineRegs::TriangleTopology topology); |
| 40 | 41 | ||
| 41 | private: | 42 | private: |
| 42 | Regs::TriangleTopology topology; | 43 | PipelineRegs::TriangleTopology topology; |
| 43 | 44 | ||
| 44 | int buffer_index; | 45 | int buffer_index; |
| 45 | VertexType buffer[2]; | 46 | VertexType buffer[2]; |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 287d732b5..ca09c9d0e 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -16,10 +16,10 @@ | |||
| 16 | #include "core/hw/gpu.h" | 16 | #include "core/hw/gpu.h" |
| 17 | #include "core/memory.h" | 17 | #include "core/memory.h" |
| 18 | #include "video_core/debug_utils/debug_utils.h" | 18 | #include "video_core/debug_utils/debug_utils.h" |
| 19 | #include "video_core/pica.h" | ||
| 20 | #include "video_core/pica_state.h" | 19 | #include "video_core/pica_state.h" |
| 21 | #include "video_core/pica_types.h" | 20 | #include "video_core/pica_types.h" |
| 22 | #include "video_core/rasterizer.h" | 21 | #include "video_core/rasterizer.h" |
| 22 | #include "video_core/regs.h" | ||
| 23 | #include "video_core/shader/shader.h" | 23 | #include "video_core/shader/shader.h" |
| 24 | #include "video_core/texture/texture_decode.h" | 24 | #include "video_core/texture/texture_decode.h" |
| 25 | #include "video_core/utils.h" | 25 | #include "video_core/utils.h" |
| @@ -29,7 +29,7 @@ namespace Pica { | |||
| 29 | namespace Rasterizer { | 29 | namespace Rasterizer { |
| 30 | 30 | ||
| 31 | static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | 31 | static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { |
| 32 | const auto& framebuffer = g_state.regs.framebuffer; | 32 | const auto& framebuffer = g_state.regs.framebuffer.framebuffer; |
| 33 | const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); | 33 | const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); |
| 34 | 34 | ||
| 35 | // Similarly to textures, the render framebuffer is laid out from bottom to top, too. | 35 | // Similarly to textures, the render framebuffer is laid out from bottom to top, too. |
| @@ -44,23 +44,23 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | |||
| 44 | u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset; | 44 | u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset; |
| 45 | 45 | ||
| 46 | switch (framebuffer.color_format) { | 46 | switch (framebuffer.color_format) { |
| 47 | case Regs::ColorFormat::RGBA8: | 47 | case FramebufferRegs::ColorFormat::RGBA8: |
| 48 | Color::EncodeRGBA8(color, dst_pixel); | 48 | Color::EncodeRGBA8(color, dst_pixel); |
| 49 | break; | 49 | break; |
| 50 | 50 | ||
| 51 | case Regs::ColorFormat::RGB8: | 51 | case FramebufferRegs::ColorFormat::RGB8: |
| 52 | Color::EncodeRGB8(color, dst_pixel); | 52 | Color::EncodeRGB8(color, dst_pixel); |
| 53 | break; | 53 | break; |
| 54 | 54 | ||
| 55 | case Regs::ColorFormat::RGB5A1: | 55 | case FramebufferRegs::ColorFormat::RGB5A1: |
| 56 | Color::EncodeRGB5A1(color, dst_pixel); | 56 | Color::EncodeRGB5A1(color, dst_pixel); |
| 57 | break; | 57 | break; |
| 58 | 58 | ||
| 59 | case Regs::ColorFormat::RGB565: | 59 | case FramebufferRegs::ColorFormat::RGB565: |
| 60 | Color::EncodeRGB565(color, dst_pixel); | 60 | Color::EncodeRGB565(color, dst_pixel); |
| 61 | break; | 61 | break; |
| 62 | 62 | ||
| 63 | case Regs::ColorFormat::RGBA4: | 63 | case FramebufferRegs::ColorFormat::RGBA4: |
| 64 | Color::EncodeRGBA4(color, dst_pixel); | 64 | Color::EncodeRGBA4(color, dst_pixel); |
| 65 | break; | 65 | break; |
| 66 | 66 | ||
| @@ -72,7 +72,7 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static const Math::Vec4<u8> GetPixel(int x, int y) { | 74 | static const Math::Vec4<u8> GetPixel(int x, int y) { |
| 75 | const auto& framebuffer = g_state.regs.framebuffer; | 75 | const auto& framebuffer = g_state.regs.framebuffer.framebuffer; |
| 76 | const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); | 76 | const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); |
| 77 | 77 | ||
| 78 | y = framebuffer.height - y; | 78 | y = framebuffer.height - y; |
| @@ -85,19 +85,19 @@ static const Math::Vec4<u8> GetPixel(int x, int y) { | |||
| 85 | u8* src_pixel = Memory::GetPhysicalPointer(addr) + src_offset; | 85 | u8* src_pixel = Memory::GetPhysicalPointer(addr) + src_offset; |
| 86 | 86 | ||
| 87 | switch (framebuffer.color_format) { | 87 | switch (framebuffer.color_format) { |
| 88 | case Regs::ColorFormat::RGBA8: | 88 | case FramebufferRegs::ColorFormat::RGBA8: |
| 89 | return Color::DecodeRGBA8(src_pixel); | 89 | return Color::DecodeRGBA8(src_pixel); |
| 90 | 90 | ||
| 91 | case Regs::ColorFormat::RGB8: | 91 | case FramebufferRegs::ColorFormat::RGB8: |
| 92 | return Color::DecodeRGB8(src_pixel); | 92 | return Color::DecodeRGB8(src_pixel); |
| 93 | 93 | ||
| 94 | case Regs::ColorFormat::RGB5A1: | 94 | case FramebufferRegs::ColorFormat::RGB5A1: |
| 95 | return Color::DecodeRGB5A1(src_pixel); | 95 | return Color::DecodeRGB5A1(src_pixel); |
| 96 | 96 | ||
| 97 | case Regs::ColorFormat::RGB565: | 97 | case FramebufferRegs::ColorFormat::RGB565: |
| 98 | return Color::DecodeRGB565(src_pixel); | 98 | return Color::DecodeRGB565(src_pixel); |
| 99 | 99 | ||
| 100 | case Regs::ColorFormat::RGBA4: | 100 | case FramebufferRegs::ColorFormat::RGBA4: |
| 101 | return Color::DecodeRGBA4(src_pixel); | 101 | return Color::DecodeRGBA4(src_pixel); |
| 102 | 102 | ||
| 103 | default: | 103 | default: |
| @@ -110,25 +110,25 @@ static const Math::Vec4<u8> GetPixel(int x, int y) { | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | static u32 GetDepth(int x, int y) { | 112 | static u32 GetDepth(int x, int y) { |
| 113 | const auto& framebuffer = g_state.regs.framebuffer; | 113 | const auto& framebuffer = g_state.regs.framebuffer.framebuffer; |
| 114 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | 114 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); |
| 115 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); | 115 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); |
| 116 | 116 | ||
| 117 | y = framebuffer.height - y; | 117 | y = framebuffer.height - y; |
| 118 | 118 | ||
| 119 | const u32 coarse_y = y & ~7; | 119 | const u32 coarse_y = y & ~7; |
| 120 | u32 bytes_per_pixel = Regs::BytesPerDepthPixel(framebuffer.depth_format); | 120 | u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); |
| 121 | u32 stride = framebuffer.width * bytes_per_pixel; | 121 | u32 stride = framebuffer.width * bytes_per_pixel; |
| 122 | 122 | ||
| 123 | u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | 123 | u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; |
| 124 | u8* src_pixel = depth_buffer + src_offset; | 124 | u8* src_pixel = depth_buffer + src_offset; |
| 125 | 125 | ||
| 126 | switch (framebuffer.depth_format) { | 126 | switch (framebuffer.depth_format) { |
| 127 | case Regs::DepthFormat::D16: | 127 | case FramebufferRegs::DepthFormat::D16: |
| 128 | return Color::DecodeD16(src_pixel); | 128 | return Color::DecodeD16(src_pixel); |
| 129 | case Regs::DepthFormat::D24: | 129 | case FramebufferRegs::DepthFormat::D24: |
| 130 | return Color::DecodeD24(src_pixel); | 130 | return Color::DecodeD24(src_pixel); |
| 131 | case Regs::DepthFormat::D24S8: | 131 | case FramebufferRegs::DepthFormat::D24S8: |
| 132 | return Color::DecodeD24S8(src_pixel).x; | 132 | return Color::DecodeD24S8(src_pixel).x; |
| 133 | default: | 133 | default: |
| 134 | LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); | 134 | LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); |
| @@ -138,21 +138,21 @@ static u32 GetDepth(int x, int y) { | |||
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static u8 GetStencil(int x, int y) { | 140 | static u8 GetStencil(int x, int y) { |
| 141 | const auto& framebuffer = g_state.regs.framebuffer; | 141 | const auto& framebuffer = g_state.regs.framebuffer.framebuffer; |
| 142 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | 142 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); |
| 143 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); | 143 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); |
| 144 | 144 | ||
| 145 | y = framebuffer.height - y; | 145 | y = framebuffer.height - y; |
| 146 | 146 | ||
| 147 | const u32 coarse_y = y & ~7; | 147 | const u32 coarse_y = y & ~7; |
| 148 | u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(framebuffer.depth_format); | 148 | u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); |
| 149 | u32 stride = framebuffer.width * bytes_per_pixel; | 149 | u32 stride = framebuffer.width * bytes_per_pixel; |
| 150 | 150 | ||
| 151 | u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | 151 | u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; |
| 152 | u8* src_pixel = depth_buffer + src_offset; | 152 | u8* src_pixel = depth_buffer + src_offset; |
| 153 | 153 | ||
| 154 | switch (framebuffer.depth_format) { | 154 | switch (framebuffer.depth_format) { |
| 155 | case Regs::DepthFormat::D24S8: | 155 | case FramebufferRegs::DepthFormat::D24S8: |
| 156 | return Color::DecodeD24S8(src_pixel).y; | 156 | return Color::DecodeD24S8(src_pixel).y; |
| 157 | 157 | ||
| 158 | default: | 158 | default: |
| @@ -165,29 +165,29 @@ static u8 GetStencil(int x, int y) { | |||
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | static void SetDepth(int x, int y, u32 value) { | 167 | static void SetDepth(int x, int y, u32 value) { |
| 168 | const auto& framebuffer = g_state.regs.framebuffer; | 168 | const auto& framebuffer = g_state.regs.framebuffer.framebuffer; |
| 169 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | 169 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); |
| 170 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); | 170 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); |
| 171 | 171 | ||
| 172 | y = framebuffer.height - y; | 172 | y = framebuffer.height - y; |
| 173 | 173 | ||
| 174 | const u32 coarse_y = y & ~7; | 174 | const u32 coarse_y = y & ~7; |
| 175 | u32 bytes_per_pixel = Regs::BytesPerDepthPixel(framebuffer.depth_format); | 175 | u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); |
| 176 | u32 stride = framebuffer.width * bytes_per_pixel; | 176 | u32 stride = framebuffer.width * bytes_per_pixel; |
| 177 | 177 | ||
| 178 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | 178 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; |
| 179 | u8* dst_pixel = depth_buffer + dst_offset; | 179 | u8* dst_pixel = depth_buffer + dst_offset; |
| 180 | 180 | ||
| 181 | switch (framebuffer.depth_format) { | 181 | switch (framebuffer.depth_format) { |
| 182 | case Regs::DepthFormat::D16: | 182 | case FramebufferRegs::DepthFormat::D16: |
| 183 | Color::EncodeD16(value, dst_pixel); | 183 | Color::EncodeD16(value, dst_pixel); |
| 184 | break; | 184 | break; |
| 185 | 185 | ||
| 186 | case Regs::DepthFormat::D24: | 186 | case FramebufferRegs::DepthFormat::D24: |
| 187 | Color::EncodeD24(value, dst_pixel); | 187 | Color::EncodeD24(value, dst_pixel); |
| 188 | break; | 188 | break; |
| 189 | 189 | ||
| 190 | case Regs::DepthFormat::D24S8: | 190 | case FramebufferRegs::DepthFormat::D24S8: |
| 191 | Color::EncodeD24X8(value, dst_pixel); | 191 | Color::EncodeD24X8(value, dst_pixel); |
| 192 | break; | 192 | break; |
| 193 | 193 | ||
| @@ -199,26 +199,26 @@ static void SetDepth(int x, int y, u32 value) { | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | static void SetStencil(int x, int y, u8 value) { | 201 | static void SetStencil(int x, int y, u8 value) { |
| 202 | const auto& framebuffer = g_state.regs.framebuffer; | 202 | const auto& framebuffer = g_state.regs.framebuffer.framebuffer; |
| 203 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | 203 | const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); |
| 204 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); | 204 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); |
| 205 | 205 | ||
| 206 | y = framebuffer.height - y; | 206 | y = framebuffer.height - y; |
| 207 | 207 | ||
| 208 | const u32 coarse_y = y & ~7; | 208 | const u32 coarse_y = y & ~7; |
| 209 | u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(framebuffer.depth_format); | 209 | u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); |
| 210 | u32 stride = framebuffer.width * bytes_per_pixel; | 210 | u32 stride = framebuffer.width * bytes_per_pixel; |
| 211 | 211 | ||
| 212 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | 212 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; |
| 213 | u8* dst_pixel = depth_buffer + dst_offset; | 213 | u8* dst_pixel = depth_buffer + dst_offset; |
| 214 | 214 | ||
| 215 | switch (framebuffer.depth_format) { | 215 | switch (framebuffer.depth_format) { |
| 216 | case Pica::Regs::DepthFormat::D16: | 216 | case Pica::FramebufferRegs::DepthFormat::D16: |
| 217 | case Pica::Regs::DepthFormat::D24: | 217 | case Pica::FramebufferRegs::DepthFormat::D24: |
| 218 | // Nothing to do | 218 | // Nothing to do |
| 219 | break; | 219 | break; |
| 220 | 220 | ||
| 221 | case Pica::Regs::DepthFormat::D24S8: | 221 | case Pica::FramebufferRegs::DepthFormat::D24S8: |
| 222 | Color::EncodeX24S8(value, dst_pixel); | 222 | Color::EncodeX24S8(value, dst_pixel); |
| 223 | break; | 223 | break; |
| 224 | 224 | ||
| @@ -229,32 +229,32 @@ static void SetStencil(int x, int y, u8 value) { | |||
| 229 | } | 229 | } |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | static u8 PerformStencilAction(Regs::StencilAction action, u8 old_stencil, u8 ref) { | 232 | static u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u8 ref) { |
| 233 | switch (action) { | 233 | switch (action) { |
| 234 | case Regs::StencilAction::Keep: | 234 | case FramebufferRegs::StencilAction::Keep: |
| 235 | return old_stencil; | 235 | return old_stencil; |
| 236 | 236 | ||
| 237 | case Regs::StencilAction::Zero: | 237 | case FramebufferRegs::StencilAction::Zero: |
| 238 | return 0; | 238 | return 0; |
| 239 | 239 | ||
| 240 | case Regs::StencilAction::Replace: | 240 | case FramebufferRegs::StencilAction::Replace: |
| 241 | return ref; | 241 | return ref; |
| 242 | 242 | ||
| 243 | case Regs::StencilAction::Increment: | 243 | case FramebufferRegs::StencilAction::Increment: |
| 244 | // Saturated increment | 244 | // Saturated increment |
| 245 | return std::min<u8>(old_stencil, 254) + 1; | 245 | return std::min<u8>(old_stencil, 254) + 1; |
| 246 | 246 | ||
| 247 | case Regs::StencilAction::Decrement: | 247 | case FramebufferRegs::StencilAction::Decrement: |
| 248 | // Saturated decrement | 248 | // Saturated decrement |
| 249 | return std::max<u8>(old_stencil, 1) - 1; | 249 | return std::max<u8>(old_stencil, 1) - 1; |
| 250 | 250 | ||
| 251 | case Regs::StencilAction::Invert: | 251 | case FramebufferRegs::StencilAction::Invert: |
| 252 | return ~old_stencil; | 252 | return ~old_stencil; |
| 253 | 253 | ||
| 254 | case Regs::StencilAction::IncrementWrap: | 254 | case FramebufferRegs::StencilAction::IncrementWrap: |
| 255 | return old_stencil + 1; | 255 | return old_stencil + 1; |
| 256 | 256 | ||
| 257 | case Regs::StencilAction::DecrementWrap: | 257 | case FramebufferRegs::StencilAction::DecrementWrap: |
| 258 | return old_stencil - 1; | 258 | return old_stencil - 1; |
| 259 | 259 | ||
| 260 | default: | 260 | default: |
| @@ -327,14 +327,14 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 327 | ScreenToRasterizerCoordinates(v1.screenpos), | 327 | ScreenToRasterizerCoordinates(v1.screenpos), |
| 328 | ScreenToRasterizerCoordinates(v2.screenpos)}; | 328 | ScreenToRasterizerCoordinates(v2.screenpos)}; |
| 329 | 329 | ||
| 330 | if (regs.cull_mode == Regs::CullMode::KeepAll) { | 330 | if (regs.rasterizer.cull_mode == RasterizerRegs::CullMode::KeepAll) { |
| 331 | // Make sure we always end up with a triangle wound counter-clockwise | 331 | // Make sure we always end up with a triangle wound counter-clockwise |
| 332 | if (!reversed && SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) { | 332 | if (!reversed && SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) { |
| 333 | ProcessTriangleInternal(v0, v2, v1, true); | 333 | ProcessTriangleInternal(v0, v2, v1, true); |
| 334 | return; | 334 | return; |
| 335 | } | 335 | } |
| 336 | } else { | 336 | } else { |
| 337 | if (!reversed && regs.cull_mode == Regs::CullMode::KeepClockWise) { | 337 | if (!reversed && regs.rasterizer.cull_mode == RasterizerRegs::CullMode::KeepClockWise) { |
| 338 | // Reverse vertex order and use the CCW code path. | 338 | // Reverse vertex order and use the CCW code path. |
| 339 | ProcessTriangleInternal(v0, v2, v1, true); | 339 | ProcessTriangleInternal(v0, v2, v1, true); |
| 340 | return; | 340 | return; |
| @@ -351,13 +351,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 351 | u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); | 351 | u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); |
| 352 | 352 | ||
| 353 | // Convert the scissor box coordinates to 12.4 fixed point | 353 | // Convert the scissor box coordinates to 12.4 fixed point |
| 354 | u16 scissor_x1 = (u16)(regs.scissor_test.x1 << 4); | 354 | u16 scissor_x1 = (u16)(regs.rasterizer.scissor_test.x1 << 4); |
| 355 | u16 scissor_y1 = (u16)(regs.scissor_test.y1 << 4); | 355 | u16 scissor_y1 = (u16)(regs.rasterizer.scissor_test.y1 << 4); |
| 356 | // x2,y2 have +1 added to cover the entire sub-pixel area | 356 | // x2,y2 have +1 added to cover the entire sub-pixel area |
| 357 | u16 scissor_x2 = (u16)((regs.scissor_test.x2 + 1) << 4); | 357 | u16 scissor_x2 = (u16)((regs.rasterizer.scissor_test.x2 + 1) << 4); |
| 358 | u16 scissor_y2 = (u16)((regs.scissor_test.y2 + 1) << 4); | 358 | u16 scissor_y2 = (u16)((regs.rasterizer.scissor_test.y2 + 1) << 4); |
| 359 | 359 | ||
| 360 | if (regs.scissor_test.mode == Regs::ScissorMode::Include) { | 360 | if (regs.rasterizer.scissor_test.mode == RasterizerRegs::ScissorMode::Include) { |
| 361 | // Calculate the new bounds | 361 | // Calculate the new bounds |
| 362 | min_x = std::max(min_x, scissor_x1); | 362 | min_x = std::max(min_x, scissor_x1); |
| 363 | min_y = std::max(min_y, scissor_y1); | 363 | min_y = std::max(min_y, scissor_y1); |
| @@ -397,12 +397,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 397 | 397 | ||
| 398 | auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); | 398 | auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); |
| 399 | 399 | ||
| 400 | auto textures = regs.GetTextures(); | 400 | auto textures = regs.texturing.GetTextures(); |
| 401 | auto tev_stages = regs.GetTevStages(); | 401 | auto tev_stages = regs.texturing.GetTevStages(); |
| 402 | 402 | ||
| 403 | bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable && | 403 | bool stencil_action_enable = |
| 404 | g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8; | 404 | g_state.regs.framebuffer.output_merger.stencil_test.enable && |
| 405 | const auto stencil_test = g_state.regs.output_merger.stencil_test; | 405 | g_state.regs.framebuffer.framebuffer.depth_format == FramebufferRegs::DepthFormat::D24S8; |
| 406 | const auto stencil_test = g_state.regs.framebuffer.output_merger.stencil_test; | ||
| 406 | 407 | ||
| 407 | // Enter rasterization loop, starting at the center of the topleft bounding box corner. | 408 | // Enter rasterization loop, starting at the center of the topleft bounding box corner. |
| 408 | // TODO: Not sure if looping through x first might be faster | 409 | // TODO: Not sure if looping through x first might be faster |
| @@ -411,7 +412,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 411 | 412 | ||
| 412 | // Do not process the pixel if it's inside the scissor box and the scissor mode is set | 413 | // Do not process the pixel if it's inside the scissor box and the scissor mode is set |
| 413 | // to Exclude | 414 | // to Exclude |
| 414 | if (regs.scissor_test.mode == Regs::ScissorMode::Exclude) { | 415 | if (regs.rasterizer.scissor_test.mode == RasterizerRegs::ScissorMode::Exclude) { |
| 415 | if (x >= scissor_x1 && x < scissor_x2 && y >= scissor_y1 && y < scissor_y2) | 416 | if (x >= scissor_x1 && x < scissor_x2 && y >= scissor_y1 && y < scissor_y2) |
| 416 | continue; | 417 | continue; |
| 417 | } | 418 | } |
| @@ -441,12 +442,14 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 441 | 442 | ||
| 442 | // Not fully accurate. About 3 bits in precision are missing. | 443 | // Not fully accurate. About 3 bits in precision are missing. |
| 443 | // Z-Buffer (z / w * scale + offset) | 444 | // Z-Buffer (z / w * scale + offset) |
| 444 | float depth_scale = float24::FromRaw(regs.viewport_depth_range).ToFloat32(); | 445 | float depth_scale = float24::FromRaw(regs.rasterizer.viewport_depth_range).ToFloat32(); |
| 445 | float depth_offset = float24::FromRaw(regs.viewport_depth_near_plane).ToFloat32(); | 446 | float depth_offset = |
| 447 | float24::FromRaw(regs.rasterizer.viewport_depth_near_plane).ToFloat32(); | ||
| 446 | float depth = interpolated_z_over_w * depth_scale + depth_offset; | 448 | float depth = interpolated_z_over_w * depth_scale + depth_offset; |
| 447 | 449 | ||
| 448 | // Potentially switch to W-Buffer | 450 | // Potentially switch to W-Buffer |
| 449 | if (regs.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) { | 451 | if (regs.rasterizer.depthmap_enable == |
| 452 | Pica::RasterizerRegs::DepthBuffering::WBuffering) { | ||
| 450 | // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w) | 453 | // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w) |
| 451 | depth *= interpolated_w_inverse.ToFloat32() * wsum; | 454 | depth *= interpolated_w_inverse.ToFloat32() * wsum; |
| 452 | } | 455 | } |
| @@ -513,9 +516,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 513 | // TODO: Refactor so cubemaps and shadowmaps can be handled | 516 | // TODO: Refactor so cubemaps and shadowmaps can be handled |
| 514 | if (i == 0) { | 517 | if (i == 0) { |
| 515 | switch (texture.config.type) { | 518 | switch (texture.config.type) { |
| 516 | case Regs::TextureConfig::Texture2D: | 519 | case TexturingRegs::TextureConfig::Texture2D: |
| 517 | break; | 520 | break; |
| 518 | case Regs::TextureConfig::Projection2D: { | 521 | case TexturingRegs::TextureConfig::Projection2D: { |
| 519 | auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); | 522 | auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); |
| 520 | u /= tc0_w; | 523 | u /= tc0_w; |
| 521 | v /= tc0_w; | 524 | v /= tc0_w; |
| @@ -534,21 +537,21 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 534 | int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height))) | 537 | int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height))) |
| 535 | .ToFloat32(); | 538 | .ToFloat32(); |
| 536 | 539 | ||
| 537 | static auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, | 540 | static auto GetWrappedTexCoord = [](TexturingRegs::TextureConfig::WrapMode mode, |
| 538 | unsigned size) { | 541 | int val, unsigned size) { |
| 539 | switch (mode) { | 542 | switch (mode) { |
| 540 | case Regs::TextureConfig::ClampToEdge: | 543 | case TexturingRegs::TextureConfig::ClampToEdge: |
| 541 | val = std::max(val, 0); | 544 | val = std::max(val, 0); |
| 542 | val = std::min(val, (int)size - 1); | 545 | val = std::min(val, (int)size - 1); |
| 543 | return val; | 546 | return val; |
| 544 | 547 | ||
| 545 | case Regs::TextureConfig::ClampToBorder: | 548 | case TexturingRegs::TextureConfig::ClampToBorder: |
| 546 | return val; | 549 | return val; |
| 547 | 550 | ||
| 548 | case Regs::TextureConfig::Repeat: | 551 | case TexturingRegs::TextureConfig::Repeat: |
| 549 | return (int)((unsigned)val % size); | 552 | return (int)((unsigned)val % size); |
| 550 | 553 | ||
| 551 | case Regs::TextureConfig::MirroredRepeat: { | 554 | case TexturingRegs::TextureConfig::MirroredRepeat: { |
| 552 | unsigned int coord = ((unsigned)val % (2 * size)); | 555 | unsigned int coord = ((unsigned)val % (2 * size)); |
| 553 | if (coord >= size) | 556 | if (coord >= size) |
| 554 | coord = 2 * size - 1 - coord; | 557 | coord = 2 * size - 1 - coord; |
| @@ -562,9 +565,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 562 | } | 565 | } |
| 563 | }; | 566 | }; |
| 564 | 567 | ||
| 565 | if ((texture.config.wrap_s == Regs::TextureConfig::ClampToBorder && | 568 | if ((texture.config.wrap_s == TexturingRegs::TextureConfig::ClampToBorder && |
| 566 | (s < 0 || static_cast<u32>(s) >= texture.config.width)) || | 569 | (s < 0 || static_cast<u32>(s) >= texture.config.width)) || |
| 567 | (texture.config.wrap_t == Regs::TextureConfig::ClampToBorder && | 570 | (texture.config.wrap_t == TexturingRegs::TextureConfig::ClampToBorder && |
| 568 | (t < 0 || static_cast<u32>(t) >= texture.config.height))) { | 571 | (t < 0 || static_cast<u32>(t) >= texture.config.height))) { |
| 569 | auto border_color = texture.config.border_color; | 572 | auto border_color = texture.config.border_color; |
| 570 | texture_color[i] = {border_color.r, border_color.g, border_color.b, | 573 | texture_color[i] = {border_color.r, border_color.g, border_color.b, |
| @@ -600,17 +603,19 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 600 | Math::Vec4<u8> combiner_output; | 603 | Math::Vec4<u8> combiner_output; |
| 601 | Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0}; | 604 | Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0}; |
| 602 | Math::Vec4<u8> next_combiner_buffer = { | 605 | Math::Vec4<u8> next_combiner_buffer = { |
| 603 | regs.tev_combiner_buffer_color.r, regs.tev_combiner_buffer_color.g, | 606 | regs.texturing.tev_combiner_buffer_color.r, |
| 604 | regs.tev_combiner_buffer_color.b, regs.tev_combiner_buffer_color.a, | 607 | regs.texturing.tev_combiner_buffer_color.g, |
| 608 | regs.texturing.tev_combiner_buffer_color.b, | ||
| 609 | regs.texturing.tev_combiner_buffer_color.a, | ||
| 605 | }; | 610 | }; |
| 606 | 611 | ||
| 607 | for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); | 612 | for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); |
| 608 | ++tev_stage_index) { | 613 | ++tev_stage_index) { |
| 609 | const auto& tev_stage = tev_stages[tev_stage_index]; | 614 | const auto& tev_stage = tev_stages[tev_stage_index]; |
| 610 | using Source = Regs::TevStageConfig::Source; | 615 | using Source = TexturingRegs::TevStageConfig::Source; |
| 611 | using ColorModifier = Regs::TevStageConfig::ColorModifier; | 616 | using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier; |
| 612 | using AlphaModifier = Regs::TevStageConfig::AlphaModifier; | 617 | using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier; |
| 613 | using Operation = Regs::TevStageConfig::Operation; | 618 | using Operation = TexturingRegs::TevStageConfig::Operation; |
| 614 | 619 | ||
| 615 | auto GetSource = [&](Source source) -> Math::Vec4<u8> { | 620 | auto GetSource = [&](Source source) -> Math::Vec4<u8> { |
| 616 | switch (source) { | 621 | switch (source) { |
| @@ -862,54 +867,54 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 862 | 867 | ||
| 863 | combiner_buffer = next_combiner_buffer; | 868 | combiner_buffer = next_combiner_buffer; |
| 864 | 869 | ||
| 865 | if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor( | 870 | if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor( |
| 866 | tev_stage_index)) { | 871 | tev_stage_index)) { |
| 867 | next_combiner_buffer.r() = combiner_output.r(); | 872 | next_combiner_buffer.r() = combiner_output.r(); |
| 868 | next_combiner_buffer.g() = combiner_output.g(); | 873 | next_combiner_buffer.g() = combiner_output.g(); |
| 869 | next_combiner_buffer.b() = combiner_output.b(); | 874 | next_combiner_buffer.b() = combiner_output.b(); |
| 870 | } | 875 | } |
| 871 | 876 | ||
| 872 | if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha( | 877 | if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha( |
| 873 | tev_stage_index)) { | 878 | tev_stage_index)) { |
| 874 | next_combiner_buffer.a() = combiner_output.a(); | 879 | next_combiner_buffer.a() = combiner_output.a(); |
| 875 | } | 880 | } |
| 876 | } | 881 | } |
| 877 | 882 | ||
| 878 | const auto& output_merger = regs.output_merger; | 883 | const auto& output_merger = regs.framebuffer.output_merger; |
| 879 | // TODO: Does alpha testing happen before or after stencil? | 884 | // TODO: Does alpha testing happen before or after stencil? |
| 880 | if (output_merger.alpha_test.enable) { | 885 | if (output_merger.alpha_test.enable) { |
| 881 | bool pass = false; | 886 | bool pass = false; |
| 882 | 887 | ||
| 883 | switch (output_merger.alpha_test.func) { | 888 | switch (output_merger.alpha_test.func) { |
| 884 | case Regs::CompareFunc::Never: | 889 | case FramebufferRegs::CompareFunc::Never: |
| 885 | pass = false; | 890 | pass = false; |
| 886 | break; | 891 | break; |
| 887 | 892 | ||
| 888 | case Regs::CompareFunc::Always: | 893 | case FramebufferRegs::CompareFunc::Always: |
| 889 | pass = true; | 894 | pass = true; |
| 890 | break; | 895 | break; |
| 891 | 896 | ||
| 892 | case Regs::CompareFunc::Equal: | 897 | case FramebufferRegs::CompareFunc::Equal: |
| 893 | pass = combiner_output.a() == output_merger.alpha_test.ref; | 898 | pass = combiner_output.a() == output_merger.alpha_test.ref; |
| 894 | break; | 899 | break; |
| 895 | 900 | ||
| 896 | case Regs::CompareFunc::NotEqual: | 901 | case FramebufferRegs::CompareFunc::NotEqual: |
| 897 | pass = combiner_output.a() != output_merger.alpha_test.ref; | 902 | pass = combiner_output.a() != output_merger.alpha_test.ref; |
| 898 | break; | 903 | break; |
| 899 | 904 | ||
| 900 | case Regs::CompareFunc::LessThan: | 905 | case FramebufferRegs::CompareFunc::LessThan: |
| 901 | pass = combiner_output.a() < output_merger.alpha_test.ref; | 906 | pass = combiner_output.a() < output_merger.alpha_test.ref; |
| 902 | break; | 907 | break; |
| 903 | 908 | ||
| 904 | case Regs::CompareFunc::LessThanOrEqual: | 909 | case FramebufferRegs::CompareFunc::LessThanOrEqual: |
| 905 | pass = combiner_output.a() <= output_merger.alpha_test.ref; | 910 | pass = combiner_output.a() <= output_merger.alpha_test.ref; |
| 906 | break; | 911 | break; |
| 907 | 912 | ||
| 908 | case Regs::CompareFunc::GreaterThan: | 913 | case FramebufferRegs::CompareFunc::GreaterThan: |
| 909 | pass = combiner_output.a() > output_merger.alpha_test.ref; | 914 | pass = combiner_output.a() > output_merger.alpha_test.ref; |
| 910 | break; | 915 | break; |
| 911 | 916 | ||
| 912 | case Regs::CompareFunc::GreaterThanOrEqual: | 917 | case FramebufferRegs::CompareFunc::GreaterThanOrEqual: |
| 913 | pass = combiner_output.a() >= output_merger.alpha_test.ref; | 918 | pass = combiner_output.a() >= output_merger.alpha_test.ref; |
| 914 | break; | 919 | break; |
| 915 | } | 920 | } |
| @@ -922,16 +927,16 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 922 | // Not fully accurate. We'd have to know what data type is used to | 927 | // Not fully accurate. We'd have to know what data type is used to |
| 923 | // store the depth etc. Using float for now until we know more | 928 | // store the depth etc. Using float for now until we know more |
| 924 | // about Pica datatypes | 929 | // about Pica datatypes |
| 925 | if (regs.fog_mode == Regs::FogMode::Fog) { | 930 | if (regs.texturing.fog_mode == TexturingRegs::FogMode::Fog) { |
| 926 | const Math::Vec3<u8> fog_color = { | 931 | const Math::Vec3<u8> fog_color = { |
| 927 | static_cast<u8>(regs.fog_color.r.Value()), | 932 | static_cast<u8>(regs.texturing.fog_color.r.Value()), |
| 928 | static_cast<u8>(regs.fog_color.g.Value()), | 933 | static_cast<u8>(regs.texturing.fog_color.g.Value()), |
| 929 | static_cast<u8>(regs.fog_color.b.Value()), | 934 | static_cast<u8>(regs.texturing.fog_color.b.Value()), |
| 930 | }; | 935 | }; |
| 931 | 936 | ||
| 932 | // Get index into fog LUT | 937 | // Get index into fog LUT |
| 933 | float fog_index; | 938 | float fog_index; |
| 934 | if (g_state.regs.fog_flip) { | 939 | if (g_state.regs.texturing.fog_flip) { |
| 935 | fog_index = (1.0f - depth) * 128.0f; | 940 | fog_index = (1.0f - depth) * 128.0f; |
| 936 | } else { | 941 | } else { |
| 937 | fog_index = depth * 128.0f; | 942 | fog_index = depth * 128.0f; |
| @@ -955,10 +960,10 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 955 | u8 old_stencil = 0; | 960 | u8 old_stencil = 0; |
| 956 | 961 | ||
| 957 | auto UpdateStencil = [stencil_test, x, y, | 962 | auto UpdateStencil = [stencil_test, x, y, |
| 958 | &old_stencil](Pica::Regs::StencilAction action) { | 963 | &old_stencil](Pica::FramebufferRegs::StencilAction action) { |
| 959 | u8 new_stencil = | 964 | u8 new_stencil = |
| 960 | PerformStencilAction(action, old_stencil, stencil_test.reference_value); | 965 | PerformStencilAction(action, old_stencil, stencil_test.reference_value); |
| 961 | if (g_state.regs.framebuffer.allow_depth_stencil_write != 0) | 966 | if (g_state.regs.framebuffer.framebuffer.allow_depth_stencil_write != 0) |
| 962 | SetStencil(x >> 4, y >> 4, (new_stencil & stencil_test.write_mask) | | 967 | SetStencil(x >> 4, y >> 4, (new_stencil & stencil_test.write_mask) | |
| 963 | (old_stencil & ~stencil_test.write_mask)); | 968 | (old_stencil & ~stencil_test.write_mask)); |
| 964 | }; | 969 | }; |
| @@ -970,35 +975,35 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 970 | 975 | ||
| 971 | bool pass = false; | 976 | bool pass = false; |
| 972 | switch (stencil_test.func) { | 977 | switch (stencil_test.func) { |
| 973 | case Regs::CompareFunc::Never: | 978 | case FramebufferRegs::CompareFunc::Never: |
| 974 | pass = false; | 979 | pass = false; |
| 975 | break; | 980 | break; |
| 976 | 981 | ||
| 977 | case Regs::CompareFunc::Always: | 982 | case FramebufferRegs::CompareFunc::Always: |
| 978 | pass = true; | 983 | pass = true; |
| 979 | break; | 984 | break; |
| 980 | 985 | ||
| 981 | case Regs::CompareFunc::Equal: | 986 | case FramebufferRegs::CompareFunc::Equal: |
| 982 | pass = (ref == dest); | 987 | pass = (ref == dest); |
| 983 | break; | 988 | break; |
| 984 | 989 | ||
| 985 | case Regs::CompareFunc::NotEqual: | 990 | case FramebufferRegs::CompareFunc::NotEqual: |
| 986 | pass = (ref != dest); | 991 | pass = (ref != dest); |
| 987 | break; | 992 | break; |
| 988 | 993 | ||
| 989 | case Regs::CompareFunc::LessThan: | 994 | case FramebufferRegs::CompareFunc::LessThan: |
| 990 | pass = (ref < dest); | 995 | pass = (ref < dest); |
| 991 | break; | 996 | break; |
| 992 | 997 | ||
| 993 | case Regs::CompareFunc::LessThanOrEqual: | 998 | case FramebufferRegs::CompareFunc::LessThanOrEqual: |
| 994 | pass = (ref <= dest); | 999 | pass = (ref <= dest); |
| 995 | break; | 1000 | break; |
| 996 | 1001 | ||
| 997 | case Regs::CompareFunc::GreaterThan: | 1002 | case FramebufferRegs::CompareFunc::GreaterThan: |
| 998 | pass = (ref > dest); | 1003 | pass = (ref > dest); |
| 999 | break; | 1004 | break; |
| 1000 | 1005 | ||
| 1001 | case Regs::CompareFunc::GreaterThanOrEqual: | 1006 | case FramebufferRegs::CompareFunc::GreaterThanOrEqual: |
| 1002 | pass = (ref >= dest); | 1007 | pass = (ref >= dest); |
| 1003 | break; | 1008 | break; |
| 1004 | } | 1009 | } |
| @@ -1010,7 +1015,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1010 | } | 1015 | } |
| 1011 | 1016 | ||
| 1012 | // Convert float to integer | 1017 | // Convert float to integer |
| 1013 | unsigned num_bits = Regs::DepthBitsPerPixel(regs.framebuffer.depth_format); | 1018 | unsigned num_bits = |
| 1019 | FramebufferRegs::DepthBitsPerPixel(regs.framebuffer.framebuffer.depth_format); | ||
| 1014 | u32 z = (u32)(depth * ((1 << num_bits) - 1)); | 1020 | u32 z = (u32)(depth * ((1 << num_bits) - 1)); |
| 1015 | 1021 | ||
| 1016 | if (output_merger.depth_test_enable) { | 1022 | if (output_merger.depth_test_enable) { |
| @@ -1019,35 +1025,35 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1019 | bool pass = false; | 1025 | bool pass = false; |
| 1020 | 1026 | ||
| 1021 | switch (output_merger.depth_test_func) { | 1027 | switch (output_merger.depth_test_func) { |
| 1022 | case Regs::CompareFunc::Never: | 1028 | case FramebufferRegs::CompareFunc::Never: |
| 1023 | pass = false; | 1029 | pass = false; |
| 1024 | break; | 1030 | break; |
| 1025 | 1031 | ||
| 1026 | case Regs::CompareFunc::Always: | 1032 | case FramebufferRegs::CompareFunc::Always: |
| 1027 | pass = true; | 1033 | pass = true; |
| 1028 | break; | 1034 | break; |
| 1029 | 1035 | ||
| 1030 | case Regs::CompareFunc::Equal: | 1036 | case FramebufferRegs::CompareFunc::Equal: |
| 1031 | pass = z == ref_z; | 1037 | pass = z == ref_z; |
| 1032 | break; | 1038 | break; |
| 1033 | 1039 | ||
| 1034 | case Regs::CompareFunc::NotEqual: | 1040 | case FramebufferRegs::CompareFunc::NotEqual: |
| 1035 | pass = z != ref_z; | 1041 | pass = z != ref_z; |
| 1036 | break; | 1042 | break; |
| 1037 | 1043 | ||
| 1038 | case Regs::CompareFunc::LessThan: | 1044 | case FramebufferRegs::CompareFunc::LessThan: |
| 1039 | pass = z < ref_z; | 1045 | pass = z < ref_z; |
| 1040 | break; | 1046 | break; |
| 1041 | 1047 | ||
| 1042 | case Regs::CompareFunc::LessThanOrEqual: | 1048 | case FramebufferRegs::CompareFunc::LessThanOrEqual: |
| 1043 | pass = z <= ref_z; | 1049 | pass = z <= ref_z; |
| 1044 | break; | 1050 | break; |
| 1045 | 1051 | ||
| 1046 | case Regs::CompareFunc::GreaterThan: | 1052 | case FramebufferRegs::CompareFunc::GreaterThan: |
| 1047 | pass = z > ref_z; | 1053 | pass = z > ref_z; |
| 1048 | break; | 1054 | break; |
| 1049 | 1055 | ||
| 1050 | case Regs::CompareFunc::GreaterThanOrEqual: | 1056 | case FramebufferRegs::CompareFunc::GreaterThanOrEqual: |
| 1051 | pass = z >= ref_z; | 1057 | pass = z >= ref_z; |
| 1052 | break; | 1058 | break; |
| 1053 | } | 1059 | } |
| @@ -1059,8 +1065,11 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1059 | } | 1065 | } |
| 1060 | } | 1066 | } |
| 1061 | 1067 | ||
| 1062 | if (regs.framebuffer.allow_depth_stencil_write != 0 && output_merger.depth_write_enable) | 1068 | if (regs.framebuffer.framebuffer.allow_depth_stencil_write != 0 && |
| 1069 | output_merger.depth_write_enable) { | ||
| 1070 | |||
| 1063 | SetDepth(x >> 4, y >> 4, z); | 1071 | SetDepth(x >> 4, y >> 4, z); |
| 1072 | } | ||
| 1064 | 1073 | ||
| 1065 | // The stencil depth_pass action is executed even if depth testing is disabled | 1074 | // The stencil depth_pass action is executed even if depth testing is disabled |
| 1066 | if (stencil_action_enable) | 1075 | if (stencil_action_enable) |
| @@ -1072,7 +1081,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1072 | if (output_merger.alphablend_enable) { | 1081 | if (output_merger.alphablend_enable) { |
| 1073 | auto params = output_merger.alpha_blending; | 1082 | auto params = output_merger.alpha_blending; |
| 1074 | 1083 | ||
| 1075 | auto LookupFactor = [&](unsigned channel, Regs::BlendFactor factor) -> u8 { | 1084 | auto LookupFactor = [&](unsigned channel, |
| 1085 | FramebufferRegs::BlendFactor factor) -> u8 { | ||
| 1076 | DEBUG_ASSERT(channel < 4); | 1086 | DEBUG_ASSERT(channel < 4); |
| 1077 | 1087 | ||
| 1078 | const Math::Vec4<u8> blend_const = { | 1088 | const Math::Vec4<u8> blend_const = { |
| @@ -1083,49 +1093,49 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1083 | }; | 1093 | }; |
| 1084 | 1094 | ||
| 1085 | switch (factor) { | 1095 | switch (factor) { |
| 1086 | case Regs::BlendFactor::Zero: | 1096 | case FramebufferRegs::BlendFactor::Zero: |
| 1087 | return 0; | 1097 | return 0; |
| 1088 | 1098 | ||
| 1089 | case Regs::BlendFactor::One: | 1099 | case FramebufferRegs::BlendFactor::One: |
| 1090 | return 255; | 1100 | return 255; |
| 1091 | 1101 | ||
| 1092 | case Regs::BlendFactor::SourceColor: | 1102 | case FramebufferRegs::BlendFactor::SourceColor: |
| 1093 | return combiner_output[channel]; | 1103 | return combiner_output[channel]; |
| 1094 | 1104 | ||
| 1095 | case Regs::BlendFactor::OneMinusSourceColor: | 1105 | case FramebufferRegs::BlendFactor::OneMinusSourceColor: |
| 1096 | return 255 - combiner_output[channel]; | 1106 | return 255 - combiner_output[channel]; |
| 1097 | 1107 | ||
| 1098 | case Regs::BlendFactor::DestColor: | 1108 | case FramebufferRegs::BlendFactor::DestColor: |
| 1099 | return dest[channel]; | 1109 | return dest[channel]; |
| 1100 | 1110 | ||
| 1101 | case Regs::BlendFactor::OneMinusDestColor: | 1111 | case FramebufferRegs::BlendFactor::OneMinusDestColor: |
| 1102 | return 255 - dest[channel]; | 1112 | return 255 - dest[channel]; |
| 1103 | 1113 | ||
| 1104 | case Regs::BlendFactor::SourceAlpha: | 1114 | case FramebufferRegs::BlendFactor::SourceAlpha: |
| 1105 | return combiner_output.a(); | 1115 | return combiner_output.a(); |
| 1106 | 1116 | ||
| 1107 | case Regs::BlendFactor::OneMinusSourceAlpha: | 1117 | case FramebufferRegs::BlendFactor::OneMinusSourceAlpha: |
| 1108 | return 255 - combiner_output.a(); | 1118 | return 255 - combiner_output.a(); |
| 1109 | 1119 | ||
| 1110 | case Regs::BlendFactor::DestAlpha: | 1120 | case FramebufferRegs::BlendFactor::DestAlpha: |
| 1111 | return dest.a(); | 1121 | return dest.a(); |
| 1112 | 1122 | ||
| 1113 | case Regs::BlendFactor::OneMinusDestAlpha: | 1123 | case FramebufferRegs::BlendFactor::OneMinusDestAlpha: |
| 1114 | return 255 - dest.a(); | 1124 | return 255 - dest.a(); |
| 1115 | 1125 | ||
| 1116 | case Regs::BlendFactor::ConstantColor: | 1126 | case FramebufferRegs::BlendFactor::ConstantColor: |
| 1117 | return blend_const[channel]; | 1127 | return blend_const[channel]; |
| 1118 | 1128 | ||
| 1119 | case Regs::BlendFactor::OneMinusConstantColor: | 1129 | case FramebufferRegs::BlendFactor::OneMinusConstantColor: |
| 1120 | return 255 - blend_const[channel]; | 1130 | return 255 - blend_const[channel]; |
| 1121 | 1131 | ||
| 1122 | case Regs::BlendFactor::ConstantAlpha: | 1132 | case FramebufferRegs::BlendFactor::ConstantAlpha: |
| 1123 | return blend_const.a(); | 1133 | return blend_const.a(); |
| 1124 | 1134 | ||
| 1125 | case Regs::BlendFactor::OneMinusConstantAlpha: | 1135 | case FramebufferRegs::BlendFactor::OneMinusConstantAlpha: |
| 1126 | return 255 - blend_const.a(); | 1136 | return 255 - blend_const.a(); |
| 1127 | 1137 | ||
| 1128 | case Regs::BlendFactor::SourceAlphaSaturate: | 1138 | case FramebufferRegs::BlendFactor::SourceAlphaSaturate: |
| 1129 | // Returns 1.0 for the alpha channel | 1139 | // Returns 1.0 for the alpha channel |
| 1130 | if (channel == 3) | 1140 | if (channel == 3) |
| 1131 | return 255; | 1141 | return 255; |
| @@ -1143,36 +1153,37 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1143 | static auto EvaluateBlendEquation = []( | 1153 | static auto EvaluateBlendEquation = []( |
| 1144 | const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor, | 1154 | const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor, |
| 1145 | const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor, | 1155 | const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor, |
| 1146 | Regs::BlendEquation equation) { | 1156 | FramebufferRegs::BlendEquation equation) { |
| 1157 | |||
| 1147 | Math::Vec4<int> result; | 1158 | Math::Vec4<int> result; |
| 1148 | 1159 | ||
| 1149 | auto src_result = (src * srcfactor).Cast<int>(); | 1160 | auto src_result = (src * srcfactor).Cast<int>(); |
| 1150 | auto dst_result = (dest * destfactor).Cast<int>(); | 1161 | auto dst_result = (dest * destfactor).Cast<int>(); |
| 1151 | 1162 | ||
| 1152 | switch (equation) { | 1163 | switch (equation) { |
| 1153 | case Regs::BlendEquation::Add: | 1164 | case FramebufferRegs::BlendEquation::Add: |
| 1154 | result = (src_result + dst_result) / 255; | 1165 | result = (src_result + dst_result) / 255; |
| 1155 | break; | 1166 | break; |
| 1156 | 1167 | ||
| 1157 | case Regs::BlendEquation::Subtract: | 1168 | case FramebufferRegs::BlendEquation::Subtract: |
| 1158 | result = (src_result - dst_result) / 255; | 1169 | result = (src_result - dst_result) / 255; |
| 1159 | break; | 1170 | break; |
| 1160 | 1171 | ||
| 1161 | case Regs::BlendEquation::ReverseSubtract: | 1172 | case FramebufferRegs::BlendEquation::ReverseSubtract: |
| 1162 | result = (dst_result - src_result) / 255; | 1173 | result = (dst_result - src_result) / 255; |
| 1163 | break; | 1174 | break; |
| 1164 | 1175 | ||
| 1165 | // TODO: How do these two actually work? | 1176 | // TODO: How do these two actually work? |
| 1166 | // OpenGL doesn't include the blend factors in the min/max computations, | 1177 | // OpenGL doesn't include the blend factors in the min/max computations, |
| 1167 | // but is this what the 3DS actually does? | 1178 | // but is this what the 3DS actually does? |
| 1168 | case Regs::BlendEquation::Min: | 1179 | case FramebufferRegs::BlendEquation::Min: |
| 1169 | result.r() = std::min(src.r(), dest.r()); | 1180 | result.r() = std::min(src.r(), dest.r()); |
| 1170 | result.g() = std::min(src.g(), dest.g()); | 1181 | result.g() = std::min(src.g(), dest.g()); |
| 1171 | result.b() = std::min(src.b(), dest.b()); | 1182 | result.b() = std::min(src.b(), dest.b()); |
| 1172 | result.a() = std::min(src.a(), dest.a()); | 1183 | result.a() = std::min(src.a(), dest.a()); |
| 1173 | break; | 1184 | break; |
| 1174 | 1185 | ||
| 1175 | case Regs::BlendEquation::Max: | 1186 | case FramebufferRegs::BlendEquation::Max: |
| 1176 | result.r() = std::max(src.r(), dest.r()); | 1187 | result.r() = std::max(src.r(), dest.r()); |
| 1177 | result.g() = std::max(src.g(), dest.g()); | 1188 | result.g() = std::max(src.g(), dest.g()); |
| 1178 | result.b() = std::max(src.b(), dest.b()); | 1189 | result.b() = std::max(src.b(), dest.b()); |
| @@ -1205,54 +1216,54 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1205 | dstfactor, params.blend_equation_a) | 1216 | dstfactor, params.blend_equation_a) |
| 1206 | .a(); | 1217 | .a(); |
| 1207 | } else { | 1218 | } else { |
| 1208 | static auto LogicOp = [](u8 src, u8 dest, Regs::LogicOp op) -> u8 { | 1219 | static auto LogicOp = [](u8 src, u8 dest, FramebufferRegs::LogicOp op) -> u8 { |
| 1209 | switch (op) { | 1220 | switch (op) { |
| 1210 | case Regs::LogicOp::Clear: | 1221 | case FramebufferRegs::LogicOp::Clear: |
| 1211 | return 0; | 1222 | return 0; |
| 1212 | 1223 | ||
| 1213 | case Regs::LogicOp::And: | 1224 | case FramebufferRegs::LogicOp::And: |
| 1214 | return src & dest; | 1225 | return src & dest; |
| 1215 | 1226 | ||
| 1216 | case Regs::LogicOp::AndReverse: | 1227 | case FramebufferRegs::LogicOp::AndReverse: |
| 1217 | return src & ~dest; | 1228 | return src & ~dest; |
| 1218 | 1229 | ||
| 1219 | case Regs::LogicOp::Copy: | 1230 | case FramebufferRegs::LogicOp::Copy: |
| 1220 | return src; | 1231 | return src; |
| 1221 | 1232 | ||
| 1222 | case Regs::LogicOp::Set: | 1233 | case FramebufferRegs::LogicOp::Set: |
| 1223 | return 255; | 1234 | return 255; |
| 1224 | 1235 | ||
| 1225 | case Regs::LogicOp::CopyInverted: | 1236 | case FramebufferRegs::LogicOp::CopyInverted: |
| 1226 | return ~src; | 1237 | return ~src; |
| 1227 | 1238 | ||
| 1228 | case Regs::LogicOp::NoOp: | 1239 | case FramebufferRegs::LogicOp::NoOp: |
| 1229 | return dest; | 1240 | return dest; |
| 1230 | 1241 | ||
| 1231 | case Regs::LogicOp::Invert: | 1242 | case FramebufferRegs::LogicOp::Invert: |
| 1232 | return ~dest; | 1243 | return ~dest; |
| 1233 | 1244 | ||
| 1234 | case Regs::LogicOp::Nand: | 1245 | case FramebufferRegs::LogicOp::Nand: |
| 1235 | return ~(src & dest); | 1246 | return ~(src & dest); |
| 1236 | 1247 | ||
| 1237 | case Regs::LogicOp::Or: | 1248 | case FramebufferRegs::LogicOp::Or: |
| 1238 | return src | dest; | 1249 | return src | dest; |
| 1239 | 1250 | ||
| 1240 | case Regs::LogicOp::Nor: | 1251 | case FramebufferRegs::LogicOp::Nor: |
| 1241 | return ~(src | dest); | 1252 | return ~(src | dest); |
| 1242 | 1253 | ||
| 1243 | case Regs::LogicOp::Xor: | 1254 | case FramebufferRegs::LogicOp::Xor: |
| 1244 | return src ^ dest; | 1255 | return src ^ dest; |
| 1245 | 1256 | ||
| 1246 | case Regs::LogicOp::Equiv: | 1257 | case FramebufferRegs::LogicOp::Equiv: |
| 1247 | return ~(src ^ dest); | 1258 | return ~(src ^ dest); |
| 1248 | 1259 | ||
| 1249 | case Regs::LogicOp::AndInverted: | 1260 | case FramebufferRegs::LogicOp::AndInverted: |
| 1250 | return ~src & dest; | 1261 | return ~src & dest; |
| 1251 | 1262 | ||
| 1252 | case Regs::LogicOp::OrReverse: | 1263 | case FramebufferRegs::LogicOp::OrReverse: |
| 1253 | return src | ~dest; | 1264 | return src | ~dest; |
| 1254 | 1265 | ||
| 1255 | case Regs::LogicOp::OrInverted: | 1266 | case FramebufferRegs::LogicOp::OrInverted: |
| 1256 | return ~src | dest; | 1267 | return ~src | dest; |
| 1257 | } | 1268 | } |
| 1258 | }; | 1269 | }; |
| @@ -1271,7 +1282,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | |||
| 1271 | output_merger.alpha_enable ? blend_output.a() : dest.a(), | 1282 | output_merger.alpha_enable ? blend_output.a() : dest.a(), |
| 1272 | }; | 1283 | }; |
| 1273 | 1284 | ||
| 1274 | if (regs.framebuffer.allow_color_write != 0) | 1285 | if (regs.framebuffer.framebuffer.allow_color_write != 0) |
| 1275 | DrawPixel(x >> 4, y >> 4, result); | 1286 | DrawPixel(x >> 4, y >> 4, result); |
| 1276 | } | 1287 | } |
| 1277 | } | 1288 | } |
diff --git a/src/video_core/regs.cpp b/src/video_core/regs.cpp new file mode 100644 index 000000000..f47e9e763 --- /dev/null +++ b/src/video_core/regs.cpp | |||
| @@ -0,0 +1,493 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <iterator> | ||
| 6 | #include <unordered_map> | ||
| 7 | #include <utility> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "video_core/regs.h" | ||
| 11 | |||
| 12 | namespace Pica { | ||
| 13 | |||
| 14 | static const std::pair<u16, const char*> register_names[] = { | ||
| 15 | {0x010, "GPUREG_FINALIZE"}, | ||
| 16 | |||
| 17 | {0x040, "GPUREG_FACECULLING_CONFIG"}, | ||
| 18 | {0x041, "GPUREG_VIEWPORT_WIDTH"}, | ||
| 19 | {0x042, "GPUREG_VIEWPORT_INVW"}, | ||
| 20 | {0x043, "GPUREG_VIEWPORT_HEIGHT"}, | ||
| 21 | {0x044, "GPUREG_VIEWPORT_INVH"}, | ||
| 22 | |||
| 23 | {0x047, "GPUREG_FRAGOP_CLIP"}, | ||
| 24 | {0x048, "GPUREG_FRAGOP_CLIP_DATA0"}, | ||
| 25 | {0x049, "GPUREG_FRAGOP_CLIP_DATA1"}, | ||
| 26 | {0x04A, "GPUREG_FRAGOP_CLIP_DATA2"}, | ||
| 27 | {0x04B, "GPUREG_FRAGOP_CLIP_DATA3"}, | ||
| 28 | |||
| 29 | {0x04D, "GPUREG_DEPTHMAP_SCALE"}, | ||
| 30 | {0x04E, "GPUREG_DEPTHMAP_OFFSET"}, | ||
| 31 | {0x04F, "GPUREG_SH_OUTMAP_TOTAL"}, | ||
| 32 | {0x050, "GPUREG_SH_OUTMAP_O0"}, | ||
| 33 | {0x051, "GPUREG_SH_OUTMAP_O1"}, | ||
| 34 | {0x052, "GPUREG_SH_OUTMAP_O2"}, | ||
| 35 | {0x053, "GPUREG_SH_OUTMAP_O3"}, | ||
| 36 | {0x054, "GPUREG_SH_OUTMAP_O4"}, | ||
| 37 | {0x055, "GPUREG_SH_OUTMAP_O5"}, | ||
| 38 | {0x056, "GPUREG_SH_OUTMAP_O6"}, | ||
| 39 | |||
| 40 | {0x061, "GPUREG_EARLYDEPTH_FUNC"}, | ||
| 41 | {0x062, "GPUREG_EARLYDEPTH_TEST1"}, | ||
| 42 | {0x063, "GPUREG_EARLYDEPTH_CLEAR"}, | ||
| 43 | {0x064, "GPUREG_SH_OUTATTR_MODE"}, | ||
| 44 | {0x065, "GPUREG_SCISSORTEST_MODE"}, | ||
| 45 | {0x066, "GPUREG_SCISSORTEST_POS"}, | ||
| 46 | {0x067, "GPUREG_SCISSORTEST_DIM"}, | ||
| 47 | {0x068, "GPUREG_VIEWPORT_XY"}, | ||
| 48 | |||
| 49 | {0x06A, "GPUREG_EARLYDEPTH_DATA"}, | ||
| 50 | |||
| 51 | {0x06D, "GPUREG_DEPTHMAP_ENABLE"}, | ||
| 52 | {0x06E, "GPUREG_RENDERBUF_DIM"}, | ||
| 53 | {0x06F, "GPUREG_SH_OUTATTR_CLOCK"}, | ||
| 54 | |||
| 55 | {0x080, "GPUREG_TEXUNIT_CONFIG"}, | ||
| 56 | {0x081, "GPUREG_TEXUNIT0_BORDER_COLOR"}, | ||
| 57 | {0x082, "GPUREG_TEXUNIT0_DIM"}, | ||
| 58 | {0x083, "GPUREG_TEXUNIT0_PARAM"}, | ||
| 59 | {0x084, "GPUREG_TEXUNIT0_LOD"}, | ||
| 60 | {0x085, "GPUREG_TEXUNIT0_ADDR1"}, | ||
| 61 | {0x086, "GPUREG_TEXUNIT0_ADDR2"}, | ||
| 62 | {0x087, "GPUREG_TEXUNIT0_ADDR3"}, | ||
| 63 | {0x088, "GPUREG_TEXUNIT0_ADDR4"}, | ||
| 64 | {0x089, "GPUREG_TEXUNIT0_ADDR5"}, | ||
| 65 | {0x08A, "GPUREG_TEXUNIT0_ADDR6"}, | ||
| 66 | {0x08B, "GPUREG_TEXUNIT0_SHADOW"}, | ||
| 67 | |||
| 68 | {0x08E, "GPUREG_TEXUNIT0_TYPE"}, | ||
| 69 | {0x08F, "GPUREG_LIGHTING_ENABLE0"}, | ||
| 70 | |||
| 71 | {0x091, "GPUREG_TEXUNIT1_BORDER_COLOR"}, | ||
| 72 | {0x092, "GPUREG_TEXUNIT1_DIM"}, | ||
| 73 | {0x093, "GPUREG_TEXUNIT1_PARAM"}, | ||
| 74 | {0x094, "GPUREG_TEXUNIT1_LOD"}, | ||
| 75 | {0x095, "GPUREG_TEXUNIT1_ADDR"}, | ||
| 76 | {0x096, "GPUREG_TEXUNIT1_TYPE"}, | ||
| 77 | |||
| 78 | {0x099, "GPUREG_TEXUNIT2_BORDER_COLOR"}, | ||
| 79 | {0x09A, "GPUREG_TEXUNIT2_DIM"}, | ||
| 80 | {0x09B, "GPUREG_TEXUNIT2_PARAM"}, | ||
| 81 | {0x09C, "GPUREG_TEXUNIT2_LOD"}, | ||
| 82 | {0x09D, "GPUREG_TEXUNIT2_ADDR"}, | ||
| 83 | {0x09E, "GPUREG_TEXUNIT2_TYPE"}, | ||
| 84 | |||
| 85 | {0x0A8, "GPUREG_TEXUNIT3_PROCTEX0"}, | ||
| 86 | {0x0A9, "GPUREG_TEXUNIT3_PROCTEX1"}, | ||
| 87 | {0x0AA, "GPUREG_TEXUNIT3_PROCTEX2"}, | ||
| 88 | {0x0AB, "GPUREG_TEXUNIT3_PROCTEX3"}, | ||
| 89 | {0x0AC, "GPUREG_TEXUNIT3_PROCTEX4"}, | ||
| 90 | {0x0AD, "GPUREG_TEXUNIT3_PROCTEX5"}, | ||
| 91 | |||
| 92 | {0x0AF, "GPUREG_PROCTEX_LUT"}, | ||
| 93 | {0x0B0, "GPUREG_PROCTEX_LUT_DATA0"}, | ||
| 94 | {0x0B1, "GPUREG_PROCTEX_LUT_DATA1"}, | ||
| 95 | {0x0B2, "GPUREG_PROCTEX_LUT_DATA2"}, | ||
| 96 | {0x0B3, "GPUREG_PROCTEX_LUT_DATA3"}, | ||
| 97 | {0x0B4, "GPUREG_PROCTEX_LUT_DATA4"}, | ||
| 98 | {0x0B5, "GPUREG_PROCTEX_LUT_DATA5"}, | ||
| 99 | {0x0B6, "GPUREG_PROCTEX_LUT_DATA6"}, | ||
| 100 | {0x0B7, "GPUREG_PROCTEX_LUT_DATA7"}, | ||
| 101 | |||
| 102 | {0x0C0, "GPUREG_TEXENV0_SOURCE"}, | ||
| 103 | {0x0C1, "GPUREG_TEXENV0_OPERAND"}, | ||
| 104 | {0x0C2, "GPUREG_TEXENV0_COMBINER"}, | ||
| 105 | {0x0C3, "GPUREG_TEXENV0_COLOR"}, | ||
| 106 | {0x0C4, "GPUREG_TEXENV0_SCALE"}, | ||
| 107 | |||
| 108 | {0x0C8, "GPUREG_TEXENV1_SOURCE"}, | ||
| 109 | {0x0C9, "GPUREG_TEXENV1_OPERAND"}, | ||
| 110 | {0x0CA, "GPUREG_TEXENV1_COMBINER"}, | ||
| 111 | {0x0CB, "GPUREG_TEXENV1_COLOR"}, | ||
| 112 | {0x0CC, "GPUREG_TEXENV1_SCALE"}, | ||
| 113 | |||
| 114 | {0x0D0, "GPUREG_TEXENV2_SOURCE"}, | ||
| 115 | {0x0D1, "GPUREG_TEXENV2_OPERAND"}, | ||
| 116 | {0x0D2, "GPUREG_TEXENV2_COMBINER"}, | ||
| 117 | {0x0D3, "GPUREG_TEXENV2_COLOR"}, | ||
| 118 | {0x0D4, "GPUREG_TEXENV2_SCALE"}, | ||
| 119 | |||
| 120 | {0x0D8, "GPUREG_TEXENV3_SOURCE"}, | ||
| 121 | {0x0D9, "GPUREG_TEXENV3_OPERAND"}, | ||
| 122 | {0x0DA, "GPUREG_TEXENV3_COMBINER"}, | ||
| 123 | {0x0DB, "GPUREG_TEXENV3_COLOR"}, | ||
| 124 | {0x0DC, "GPUREG_TEXENV3_SCALE"}, | ||
| 125 | |||
| 126 | {0x0E0, "GPUREG_TEXENV_UPDATE_BUFFER"}, | ||
| 127 | {0x0E1, "GPUREG_FOG_COLOR"}, | ||
| 128 | |||
| 129 | {0x0E4, "GPUREG_GAS_ATTENUATION"}, | ||
| 130 | {0x0E5, "GPUREG_GAS_ACCMAX"}, | ||
| 131 | {0x0E6, "GPUREG_FOG_LUT_INDEX"}, | ||
| 132 | |||
| 133 | {0x0E8, "GPUREG_FOG_LUT_DATA0"}, | ||
| 134 | {0x0E9, "GPUREG_FOG_LUT_DATA1"}, | ||
| 135 | {0x0EA, "GPUREG_FOG_LUT_DATA2"}, | ||
| 136 | {0x0EB, "GPUREG_FOG_LUT_DATA3"}, | ||
| 137 | {0x0EC, "GPUREG_FOG_LUT_DATA4"}, | ||
| 138 | {0x0ED, "GPUREG_FOG_LUT_DATA5"}, | ||
| 139 | {0x0EE, "GPUREG_FOG_LUT_DATA6"}, | ||
| 140 | {0x0EF, "GPUREG_FOG_LUT_DATA7"}, | ||
| 141 | {0x0F0, "GPUREG_TEXENV4_SOURCE"}, | ||
| 142 | {0x0F1, "GPUREG_TEXENV4_OPERAND"}, | ||
| 143 | {0x0F2, "GPUREG_TEXENV4_COMBINER"}, | ||
| 144 | {0x0F3, "GPUREG_TEXENV4_COLOR"}, | ||
| 145 | {0x0F4, "GPUREG_TEXENV4_SCALE"}, | ||
| 146 | |||
| 147 | {0x0F8, "GPUREG_TEXENV5_SOURCE"}, | ||
| 148 | {0x0F9, "GPUREG_TEXENV5_OPERAND"}, | ||
| 149 | {0x0FA, "GPUREG_TEXENV5_COMBINER"}, | ||
| 150 | {0x0FB, "GPUREG_TEXENV5_COLOR"}, | ||
| 151 | {0x0FC, "GPUREG_TEXENV5_SCALE"}, | ||
| 152 | {0x0FD, "GPUREG_TEXENV_BUFFER_COLOR"}, | ||
| 153 | |||
| 154 | {0x100, "GPUREG_COLOR_OPERATION"}, | ||
| 155 | {0x101, "GPUREG_BLEND_FUNC"}, | ||
| 156 | {0x102, "GPUREG_LOGIC_OP"}, | ||
| 157 | {0x103, "GPUREG_BLEND_COLOR"}, | ||
| 158 | {0x104, "GPUREG_FRAGOP_ALPHA_TEST"}, | ||
| 159 | {0x105, "GPUREG_STENCIL_TEST"}, | ||
| 160 | {0x106, "GPUREG_STENCIL_OP"}, | ||
| 161 | {0x107, "GPUREG_DEPTH_COLOR_MASK"}, | ||
| 162 | |||
| 163 | {0x110, "GPUREG_FRAMEBUFFER_INVALIDATE"}, | ||
| 164 | {0x111, "GPUREG_FRAMEBUFFER_FLUSH"}, | ||
| 165 | {0x112, "GPUREG_COLORBUFFER_READ"}, | ||
| 166 | {0x113, "GPUREG_COLORBUFFER_WRITE"}, | ||
| 167 | {0x114, "GPUREG_DEPTHBUFFER_READ"}, | ||
| 168 | {0x115, "GPUREG_DEPTHBUFFER_WRITE"}, | ||
| 169 | {0x116, "GPUREG_DEPTHBUFFER_FORMAT"}, | ||
| 170 | {0x117, "GPUREG_COLORBUFFER_FORMAT"}, | ||
| 171 | {0x118, "GPUREG_EARLYDEPTH_TEST2"}, | ||
| 172 | |||
| 173 | {0x11B, "GPUREG_FRAMEBUFFER_BLOCK32"}, | ||
| 174 | {0x11C, "GPUREG_DEPTHBUFFER_LOC"}, | ||
| 175 | {0x11D, "GPUREG_COLORBUFFER_LOC"}, | ||
| 176 | {0x11E, "GPUREG_FRAMEBUFFER_DIM"}, | ||
| 177 | |||
| 178 | {0x120, "GPUREG_GAS_LIGHT_XY"}, | ||
| 179 | {0x121, "GPUREG_GAS_LIGHT_Z"}, | ||
| 180 | {0x122, "GPUREG_GAS_LIGHT_Z_COLOR"}, | ||
| 181 | {0x123, "GPUREG_GAS_LUT_INDEX"}, | ||
| 182 | {0x124, "GPUREG_GAS_LUT_DATA"}, | ||
| 183 | |||
| 184 | {0x126, "GPUREG_GAS_DELTAZ_DEPTH"}, | ||
| 185 | |||
| 186 | {0x130, "GPUREG_FRAGOP_SHADOW"}, | ||
| 187 | |||
| 188 | {0x140, "GPUREG_LIGHT0_SPECULAR0"}, | ||
| 189 | {0x141, "GPUREG_LIGHT0_SPECULAR1"}, | ||
| 190 | {0x142, "GPUREG_LIGHT0_DIFFUSE"}, | ||
| 191 | {0x143, "GPUREG_LIGHT0_AMBIENT"}, | ||
| 192 | {0x144, "GPUREG_LIGHT0_XY"}, | ||
| 193 | {0x145, "GPUREG_LIGHT0_Z"}, | ||
| 194 | {0x146, "GPUREG_LIGHT0_SPOTDIR_XY"}, | ||
| 195 | {0x147, "GPUREG_LIGHT0_SPOTDIR_Z"}, | ||
| 196 | |||
| 197 | {0x149, "GPUREG_LIGHT0_CONFIG"}, | ||
| 198 | {0x14A, "GPUREG_LIGHT0_ATTENUATION_BIAS"}, | ||
| 199 | {0x14B, "GPUREG_LIGHT0_ATTENUATION_SCALE"}, | ||
| 200 | |||
| 201 | {0x150, "GPUREG_LIGHT1_SPECULAR0"}, | ||
| 202 | {0x151, "GPUREG_LIGHT1_SPECULAR1"}, | ||
| 203 | {0x152, "GPUREG_LIGHT1_DIFFUSE"}, | ||
| 204 | {0x153, "GPUREG_LIGHT1_AMBIENT"}, | ||
| 205 | {0x154, "GPUREG_LIGHT1_XY"}, | ||
| 206 | {0x155, "GPUREG_LIGHT1_Z"}, | ||
| 207 | {0x156, "GPUREG_LIGHT1_SPOTDIR_XY"}, | ||
| 208 | {0x157, "GPUREG_LIGHT1_SPOTDIR_Z"}, | ||
| 209 | |||
| 210 | {0x159, "GPUREG_LIGHT1_CONFIG"}, | ||
| 211 | {0x15A, "GPUREG_LIGHT1_ATTENUATION_BIAS"}, | ||
| 212 | {0x15B, "GPUREG_LIGHT1_ATTENUATION_SCALE"}, | ||
| 213 | |||
| 214 | {0x160, "GPUREG_LIGHT2_SPECULAR0"}, | ||
| 215 | {0x161, "GPUREG_LIGHT2_SPECULAR1"}, | ||
| 216 | {0x162, "GPUREG_LIGHT2_DIFFUSE"}, | ||
| 217 | {0x163, "GPUREG_LIGHT2_AMBIENT"}, | ||
| 218 | {0x164, "GPUREG_LIGHT2_XY"}, | ||
| 219 | {0x165, "GPUREG_LIGHT2_Z"}, | ||
| 220 | {0x166, "GPUREG_LIGHT2_SPOTDIR_XY"}, | ||
| 221 | {0x167, "GPUREG_LIGHT2_SPOTDIR_Z"}, | ||
| 222 | |||
| 223 | {0x169, "GPUREG_LIGHT2_CONFIG"}, | ||
| 224 | {0x16A, "GPUREG_LIGHT2_ATTENUATION_BIAS"}, | ||
| 225 | {0x16B, "GPUREG_LIGHT2_ATTENUATION_SCALE"}, | ||
| 226 | |||
| 227 | {0x170, "GPUREG_LIGHT3_SPECULAR0"}, | ||
| 228 | {0x171, "GPUREG_LIGHT3_SPECULAR1"}, | ||
| 229 | {0x172, "GPUREG_LIGHT3_DIFFUSE"}, | ||
| 230 | {0x173, "GPUREG_LIGHT3_AMBIENT"}, | ||
| 231 | {0x174, "GPUREG_LIGHT3_XY"}, | ||
| 232 | {0x175, "GPUREG_LIGHT3_Z"}, | ||
| 233 | {0x176, "GPUREG_LIGHT3_SPOTDIR_XY"}, | ||
| 234 | {0x177, "GPUREG_LIGHT3_SPOTDIR_Z"}, | ||
| 235 | |||
| 236 | {0x179, "GPUREG_LIGHT3_CONFIG"}, | ||
| 237 | {0x17A, "GPUREG_LIGHT3_ATTENUATION_BIAS"}, | ||
| 238 | {0x17B, "GPUREG_LIGHT3_ATTENUATION_SCALE"}, | ||
| 239 | |||
| 240 | {0x180, "GPUREG_LIGHT4_SPECULAR0"}, | ||
| 241 | {0x181, "GPUREG_LIGHT4_SPECULAR1"}, | ||
| 242 | {0x182, "GPUREG_LIGHT4_DIFFUSE"}, | ||
| 243 | {0x183, "GPUREG_LIGHT4_AMBIENT"}, | ||
| 244 | {0x184, "GPUREG_LIGHT4_XY"}, | ||
| 245 | {0x185, "GPUREG_LIGHT4_Z"}, | ||
| 246 | {0x186, "GPUREG_LIGHT4_SPOTDIR_XY"}, | ||
| 247 | {0x187, "GPUREG_LIGHT4_SPOTDIR_Z"}, | ||
| 248 | |||
| 249 | {0x189, "GPUREG_LIGHT4_CONFIG"}, | ||
| 250 | {0x18A, "GPUREG_LIGHT4_ATTENUATION_BIAS"}, | ||
| 251 | {0x18B, "GPUREG_LIGHT4_ATTENUATION_SCALE"}, | ||
| 252 | |||
| 253 | {0x190, "GPUREG_LIGHT5_SPECULAR0"}, | ||
| 254 | {0x191, "GPUREG_LIGHT5_SPECULAR1"}, | ||
| 255 | {0x192, "GPUREG_LIGHT5_DIFFUSE"}, | ||
| 256 | {0x193, "GPUREG_LIGHT5_AMBIENT"}, | ||
| 257 | {0x194, "GPUREG_LIGHT5_XY"}, | ||
| 258 | {0x195, "GPUREG_LIGHT5_Z"}, | ||
| 259 | {0x196, "GPUREG_LIGHT5_SPOTDIR_XY"}, | ||
| 260 | {0x197, "GPUREG_LIGHT5_SPOTDIR_Z"}, | ||
| 261 | |||
| 262 | {0x199, "GPUREG_LIGHT5_CONFIG"}, | ||
| 263 | {0x19A, "GPUREG_LIGHT5_ATTENUATION_BIAS"}, | ||
| 264 | {0x19B, "GPUREG_LIGHT5_ATTENUATION_SCALE"}, | ||
| 265 | |||
| 266 | {0x1A0, "GPUREG_LIGHT6_SPECULAR0"}, | ||
| 267 | {0x1A1, "GPUREG_LIGHT6_SPECULAR1"}, | ||
| 268 | {0x1A2, "GPUREG_LIGHT6_DIFFUSE"}, | ||
| 269 | {0x1A3, "GPUREG_LIGHT6_AMBIENT"}, | ||
| 270 | {0x1A4, "GPUREG_LIGHT6_XY"}, | ||
| 271 | {0x1A5, "GPUREG_LIGHT6_Z"}, | ||
| 272 | {0x1A6, "GPUREG_LIGHT6_SPOTDIR_XY"}, | ||
| 273 | {0x1A7, "GPUREG_LIGHT6_SPOTDIR_Z"}, | ||
| 274 | |||
| 275 | {0x1A9, "GPUREG_LIGHT6_CONFIG"}, | ||
| 276 | {0x1AA, "GPUREG_LIGHT6_ATTENUATION_BIAS"}, | ||
| 277 | {0x1AB, "GPUREG_LIGHT6_ATTENUATION_SCALE"}, | ||
| 278 | |||
| 279 | {0x1B0, "GPUREG_LIGHT7_SPECULAR0"}, | ||
| 280 | {0x1B1, "GPUREG_LIGHT7_SPECULAR1"}, | ||
| 281 | {0x1B2, "GPUREG_LIGHT7_DIFFUSE"}, | ||
| 282 | {0x1B3, "GPUREG_LIGHT7_AMBIENT"}, | ||
| 283 | {0x1B4, "GPUREG_LIGHT7_XY"}, | ||
| 284 | {0x1B5, "GPUREG_LIGHT7_Z"}, | ||
| 285 | {0x1B6, "GPUREG_LIGHT7_SPOTDIR_XY"}, | ||
| 286 | {0x1B7, "GPUREG_LIGHT7_SPOTDIR_Z"}, | ||
| 287 | |||
| 288 | {0x1B9, "GPUREG_LIGHT7_CONFIG"}, | ||
| 289 | {0x1BA, "GPUREG_LIGHT7_ATTENUATION_BIAS"}, | ||
| 290 | {0x1BB, "GPUREG_LIGHT7_ATTENUATION_SCALE"}, | ||
| 291 | |||
| 292 | {0x1C0, "GPUREG_LIGHTING_AMBIENT"}, | ||
| 293 | |||
| 294 | {0x1C2, "GPUREG_LIGHTING_NUM_LIGHTS"}, | ||
| 295 | {0x1C3, "GPUREG_LIGHTING_CONFIG0"}, | ||
| 296 | {0x1C4, "GPUREG_LIGHTING_CONFIG1"}, | ||
| 297 | {0x1C5, "GPUREG_LIGHTING_LUT_INDEX"}, | ||
| 298 | {0x1C6, "GPUREG_LIGHTING_ENABLE1"}, | ||
| 299 | |||
| 300 | {0x1C8, "GPUREG_LIGHTING_LUT_DATA0"}, | ||
| 301 | {0x1C9, "GPUREG_LIGHTING_LUT_DATA1"}, | ||
| 302 | {0x1CA, "GPUREG_LIGHTING_LUT_DATA2"}, | ||
| 303 | {0x1CB, "GPUREG_LIGHTING_LUT_DATA3"}, | ||
| 304 | {0x1CC, "GPUREG_LIGHTING_LUT_DATA4"}, | ||
| 305 | {0x1CD, "GPUREG_LIGHTING_LUT_DATA5"}, | ||
| 306 | {0x1CE, "GPUREG_LIGHTING_LUT_DATA6"}, | ||
| 307 | {0x1CF, "GPUREG_LIGHTING_LUT_DATA7"}, | ||
| 308 | {0x1D0, "GPUREG_LIGHTING_LUTINPUT_ABS"}, | ||
| 309 | {0x1D1, "GPUREG_LIGHTING_LUTINPUT_SELECT"}, | ||
| 310 | {0x1D2, "GPUREG_LIGHTING_LUTINPUT_SCALE"}, | ||
| 311 | |||
| 312 | {0x1D9, "GPUREG_LIGHTING_LIGHT_PERMUTATION"}, | ||
| 313 | |||
| 314 | {0x200, "GPUREG_ATTRIBBUFFERS_LOC"}, | ||
| 315 | {0x201, "GPUREG_ATTRIBBUFFERS_FORMAT_LOW"}, | ||
| 316 | {0x202, "GPUREG_ATTRIBBUFFERS_FORMAT_HIGH"}, | ||
| 317 | {0x203, "GPUREG_ATTRIBBUFFER0_OFFSET"}, | ||
| 318 | {0x204, "GPUREG_ATTRIBBUFFER0_CONFIG1"}, | ||
| 319 | {0x205, "GPUREG_ATTRIBBUFFER0_CONFIG2"}, | ||
| 320 | {0x206, "GPUREG_ATTRIBBUFFER1_OFFSET"}, | ||
| 321 | {0x207, "GPUREG_ATTRIBBUFFER1_CONFIG1"}, | ||
| 322 | {0x208, "GPUREG_ATTRIBBUFFER1_CONFIG2"}, | ||
| 323 | {0x209, "GPUREG_ATTRIBBUFFER2_OFFSET"}, | ||
| 324 | {0x20A, "GPUREG_ATTRIBBUFFER2_CONFIG1"}, | ||
| 325 | {0x20B, "GPUREG_ATTRIBBUFFER2_CONFIG2"}, | ||
| 326 | {0x20C, "GPUREG_ATTRIBBUFFER3_OFFSET"}, | ||
| 327 | {0x20D, "GPUREG_ATTRIBBUFFER3_CONFIG1"}, | ||
| 328 | {0x20E, "GPUREG_ATTRIBBUFFER3_CONFIG2"}, | ||
| 329 | {0x20F, "GPUREG_ATTRIBBUFFER4_OFFSET"}, | ||
| 330 | {0x210, "GPUREG_ATTRIBBUFFER4_CONFIG1"}, | ||
| 331 | {0x211, "GPUREG_ATTRIBBUFFER4_CONFIG2"}, | ||
| 332 | {0x212, "GPUREG_ATTRIBBUFFER5_OFFSET"}, | ||
| 333 | {0x213, "GPUREG_ATTRIBBUFFER5_CONFIG1"}, | ||
| 334 | {0x214, "GPUREG_ATTRIBBUFFER5_CONFIG2"}, | ||
| 335 | {0x215, "GPUREG_ATTRIBBUFFER6_OFFSET"}, | ||
| 336 | {0x216, "GPUREG_ATTRIBBUFFER6_CONFIG1"}, | ||
| 337 | {0x217, "GPUREG_ATTRIBBUFFER6_CONFIG2"}, | ||
| 338 | {0x218, "GPUREG_ATTRIBBUFFER7_OFFSET"}, | ||
| 339 | {0x219, "GPUREG_ATTRIBBUFFER7_CONFIG1"}, | ||
| 340 | {0x21A, "GPUREG_ATTRIBBUFFER7_CONFIG2"}, | ||
| 341 | {0x21B, "GPUREG_ATTRIBBUFFER8_OFFSET"}, | ||
| 342 | {0x21C, "GPUREG_ATTRIBBUFFER8_CONFIG1"}, | ||
| 343 | {0x21D, "GPUREG_ATTRIBBUFFER8_CONFIG2"}, | ||
| 344 | {0x21E, "GPUREG_ATTRIBBUFFER9_OFFSET"}, | ||
| 345 | {0x21F, "GPUREG_ATTRIBBUFFER9_CONFIG1"}, | ||
| 346 | {0x220, "GPUREG_ATTRIBBUFFER9_CONFIG2"}, | ||
| 347 | {0x221, "GPUREG_ATTRIBBUFFER10_OFFSET"}, | ||
| 348 | {0x222, "GPUREG_ATTRIBBUFFER10_CONFIG1"}, | ||
| 349 | {0x223, "GPUREG_ATTRIBBUFFER10_CONFIG2"}, | ||
| 350 | {0x224, "GPUREG_ATTRIBBUFFER11_OFFSET"}, | ||
| 351 | {0x225, "GPUREG_ATTRIBBUFFER11_CONFIG1"}, | ||
| 352 | {0x226, "GPUREG_ATTRIBBUFFER11_CONFIG2"}, | ||
| 353 | {0x227, "GPUREG_INDEXBUFFER_CONFIG"}, | ||
| 354 | {0x228, "GPUREG_NUMVERTICES"}, | ||
| 355 | {0x229, "GPUREG_GEOSTAGE_CONFIG"}, | ||
| 356 | {0x22A, "GPUREG_VERTEX_OFFSET"}, | ||
| 357 | |||
| 358 | {0x22D, "GPUREG_POST_VERTEX_CACHE_NUM"}, | ||
| 359 | {0x22E, "GPUREG_DRAWARRAYS"}, | ||
| 360 | {0x22F, "GPUREG_DRAWELEMENTS"}, | ||
| 361 | |||
| 362 | {0x231, "GPUREG_VTX_FUNC"}, | ||
| 363 | {0x232, "GPUREG_FIXEDATTRIB_INDEX"}, | ||
| 364 | {0x233, "GPUREG_FIXEDATTRIB_DATA0"}, | ||
| 365 | {0x234, "GPUREG_FIXEDATTRIB_DATA1"}, | ||
| 366 | {0x235, "GPUREG_FIXEDATTRIB_DATA2"}, | ||
| 367 | |||
| 368 | {0x238, "GPUREG_CMDBUF_SIZE0"}, | ||
| 369 | {0x239, "GPUREG_CMDBUF_SIZE1"}, | ||
| 370 | {0x23A, "GPUREG_CMDBUF_ADDR0"}, | ||
| 371 | {0x23B, "GPUREG_CMDBUF_ADDR1"}, | ||
| 372 | {0x23C, "GPUREG_CMDBUF_JUMP0"}, | ||
| 373 | {0x23D, "GPUREG_CMDBUF_JUMP1"}, | ||
| 374 | |||
| 375 | {0x242, "GPUREG_VSH_NUM_ATTR"}, | ||
| 376 | |||
| 377 | {0x244, "GPUREG_VSH_COM_MODE"}, | ||
| 378 | {0x245, "GPUREG_START_DRAW_FUNC0"}, | ||
| 379 | |||
| 380 | {0x24A, "GPUREG_VSH_OUTMAP_TOTAL1"}, | ||
| 381 | |||
| 382 | {0x251, "GPUREG_VSH_OUTMAP_TOTAL2"}, | ||
| 383 | {0x252, "GPUREG_GSH_MISC0"}, | ||
| 384 | {0x253, "GPUREG_GEOSTAGE_CONFIG2"}, | ||
| 385 | {0x254, "GPUREG_GSH_MISC1"}, | ||
| 386 | |||
| 387 | {0x25E, "GPUREG_PRIMITIVE_CONFIG"}, | ||
| 388 | {0x25F, "GPUREG_RESTART_PRIMITIVE"}, | ||
| 389 | |||
| 390 | {0x280, "GPUREG_GSH_BOOLUNIFORM"}, | ||
| 391 | {0x281, "GPUREG_GSH_INTUNIFORM_I0"}, | ||
| 392 | {0x282, "GPUREG_GSH_INTUNIFORM_I1"}, | ||
| 393 | {0x283, "GPUREG_GSH_INTUNIFORM_I2"}, | ||
| 394 | {0x284, "GPUREG_GSH_INTUNIFORM_I3"}, | ||
| 395 | |||
| 396 | {0x289, "GPUREG_GSH_INPUTBUFFER_CONFIG"}, | ||
| 397 | {0x28A, "GPUREG_GSH_ENTRYPOINT"}, | ||
| 398 | {0x28B, "GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW"}, | ||
| 399 | {0x28C, "GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH"}, | ||
| 400 | {0x28D, "GPUREG_GSH_OUTMAP_MASK"}, | ||
| 401 | |||
| 402 | {0x28F, "GPUREG_GSH_CODETRANSFER_END"}, | ||
| 403 | {0x290, "GPUREG_GSH_FLOATUNIFORM_INDEX"}, | ||
| 404 | {0x291, "GPUREG_GSH_FLOATUNIFORM_DATA0"}, | ||
| 405 | {0x292, "GPUREG_GSH_FLOATUNIFORM_DATA1"}, | ||
| 406 | {0x293, "GPUREG_GSH_FLOATUNIFORM_DATA2"}, | ||
| 407 | {0x294, "GPUREG_GSH_FLOATUNIFORM_DATA3"}, | ||
| 408 | {0x295, "GPUREG_GSH_FLOATUNIFORM_DATA4"}, | ||
| 409 | {0x296, "GPUREG_GSH_FLOATUNIFORM_DATA5"}, | ||
| 410 | {0x297, "GPUREG_GSH_FLOATUNIFORM_DATA6"}, | ||
| 411 | {0x298, "GPUREG_GSH_FLOATUNIFORM_DATA7"}, | ||
| 412 | |||
| 413 | {0x29B, "GPUREG_GSH_CODETRANSFER_INDEX"}, | ||
| 414 | {0x29C, "GPUREG_GSH_CODETRANSFER_DATA0"}, | ||
| 415 | {0x29D, "GPUREG_GSH_CODETRANSFER_DATA1"}, | ||
| 416 | {0x29E, "GPUREG_GSH_CODETRANSFER_DATA2"}, | ||
| 417 | {0x29F, "GPUREG_GSH_CODETRANSFER_DATA3"}, | ||
| 418 | {0x2A0, "GPUREG_GSH_CODETRANSFER_DATA4"}, | ||
| 419 | {0x2A1, "GPUREG_GSH_CODETRANSFER_DATA5"}, | ||
| 420 | {0x2A2, "GPUREG_GSH_CODETRANSFER_DATA6"}, | ||
| 421 | {0x2A3, "GPUREG_GSH_CODETRANSFER_DATA7"}, | ||
| 422 | |||
| 423 | {0x2A5, "GPUREG_GSH_OPDESCS_INDEX"}, | ||
| 424 | {0x2A6, "GPUREG_GSH_OPDESCS_DATA0"}, | ||
| 425 | {0x2A7, "GPUREG_GSH_OPDESCS_DATA1"}, | ||
| 426 | {0x2A8, "GPUREG_GSH_OPDESCS_DATA2"}, | ||
| 427 | {0x2A9, "GPUREG_GSH_OPDESCS_DATA3"}, | ||
| 428 | {0x2AA, "GPUREG_GSH_OPDESCS_DATA4"}, | ||
| 429 | {0x2AB, "GPUREG_GSH_OPDESCS_DATA5"}, | ||
| 430 | {0x2AC, "GPUREG_GSH_OPDESCS_DATA6"}, | ||
| 431 | {0x2AD, "GPUREG_GSH_OPDESCS_DATA7"}, | ||
| 432 | |||
| 433 | {0x2B0, "GPUREG_VSH_BOOLUNIFORM"}, | ||
| 434 | {0x2B1, "GPUREG_VSH_INTUNIFORM_I0"}, | ||
| 435 | {0x2B2, "GPUREG_VSH_INTUNIFORM_I1"}, | ||
| 436 | {0x2B3, "GPUREG_VSH_INTUNIFORM_I2"}, | ||
| 437 | {0x2B4, "GPUREG_VSH_INTUNIFORM_I3"}, | ||
| 438 | |||
| 439 | {0x2B9, "GPUREG_VSH_INPUTBUFFER_CONFIG"}, | ||
| 440 | {0x2BA, "GPUREG_VSH_ENTRYPOINT"}, | ||
| 441 | {0x2BB, "GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW"}, | ||
| 442 | {0x2BC, "GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH"}, | ||
| 443 | {0x2BD, "GPUREG_VSH_OUTMAP_MASK"}, | ||
| 444 | |||
| 445 | {0x2BF, "GPUREG_VSH_CODETRANSFER_END"}, | ||
| 446 | {0x2C0, "GPUREG_VSH_FLOATUNIFORM_INDEX"}, | ||
| 447 | {0x2C1, "GPUREG_VSH_FLOATUNIFORM_DATA0"}, | ||
| 448 | {0x2C2, "GPUREG_VSH_FLOATUNIFORM_DATA1"}, | ||
| 449 | {0x2C3, "GPUREG_VSH_FLOATUNIFORM_DATA2"}, | ||
| 450 | {0x2C4, "GPUREG_VSH_FLOATUNIFORM_DATA3"}, | ||
| 451 | {0x2C5, "GPUREG_VSH_FLOATUNIFORM_DATA4"}, | ||
| 452 | {0x2C6, "GPUREG_VSH_FLOATUNIFORM_DATA5"}, | ||
| 453 | {0x2C7, "GPUREG_VSH_FLOATUNIFORM_DATA6"}, | ||
| 454 | {0x2C8, "GPUREG_VSH_FLOATUNIFORM_DATA7"}, | ||
| 455 | |||
| 456 | {0x2CB, "GPUREG_VSH_CODETRANSFER_INDEX"}, | ||
| 457 | {0x2CC, "GPUREG_VSH_CODETRANSFER_DATA0"}, | ||
| 458 | {0x2CD, "GPUREG_VSH_CODETRANSFER_DATA1"}, | ||
| 459 | {0x2CE, "GPUREG_VSH_CODETRANSFER_DATA2"}, | ||
| 460 | {0x2CF, "GPUREG_VSH_CODETRANSFER_DATA3"}, | ||
| 461 | {0x2D0, "GPUREG_VSH_CODETRANSFER_DATA4"}, | ||
| 462 | {0x2D1, "GPUREG_VSH_CODETRANSFER_DATA5"}, | ||
| 463 | {0x2D2, "GPUREG_VSH_CODETRANSFER_DATA6"}, | ||
| 464 | {0x2D3, "GPUREG_VSH_CODETRANSFER_DATA7"}, | ||
| 465 | |||
| 466 | {0x2D5, "GPUREG_VSH_OPDESCS_INDEX"}, | ||
| 467 | {0x2D6, "GPUREG_VSH_OPDESCS_DATA0"}, | ||
| 468 | {0x2D7, "GPUREG_VSH_OPDESCS_DATA1"}, | ||
| 469 | {0x2D8, "GPUREG_VSH_OPDESCS_DATA2"}, | ||
| 470 | {0x2D9, "GPUREG_VSH_OPDESCS_DATA3"}, | ||
| 471 | {0x2DA, "GPUREG_VSH_OPDESCS_DATA4"}, | ||
| 472 | {0x2DB, "GPUREG_VSH_OPDESCS_DATA5"}, | ||
| 473 | {0x2DC, "GPUREG_VSH_OPDESCS_DATA6"}, | ||
| 474 | {0x2DD, "GPUREG_VSH_OPDESCS_DATA7"}, | ||
| 475 | }; | ||
| 476 | |||
| 477 | std::string Regs::GetCommandName(int index) { | ||
| 478 | static std::unordered_map<u32, const char*> map; | ||
| 479 | |||
| 480 | if (map.empty()) { | ||
| 481 | map.insert(std::begin(register_names), std::end(register_names)); | ||
| 482 | } | ||
| 483 | |||
| 484 | // Return empty string if no match is found | ||
| 485 | auto it = map.find(index); | ||
| 486 | if (it != map.end()) { | ||
| 487 | return it->second; | ||
| 488 | } else { | ||
| 489 | return std::string(); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | } // namespace Pica | ||
diff --git a/src/video_core/regs.h b/src/video_core/regs.h new file mode 100644 index 000000000..f25edde27 --- /dev/null +++ b/src/video_core/regs.h | |||
| @@ -0,0 +1,164 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | ||
| 9 | #include <string> | ||
| 10 | #ifndef _MSC_VER | ||
| 11 | #include <type_traits> // for std::enable_if | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #include "common/common_funcs.h" | ||
| 15 | #include "common/common_types.h" | ||
| 16 | #include "video_core/regs_framebuffer.h" | ||
| 17 | #include "video_core/regs_lighting.h" | ||
| 18 | #include "video_core/regs_pipeline.h" | ||
| 19 | #include "video_core/regs_rasterizer.h" | ||
| 20 | #include "video_core/regs_shader.h" | ||
| 21 | #include "video_core/regs_texturing.h" | ||
| 22 | |||
| 23 | namespace Pica { | ||
| 24 | |||
| 25 | // Returns index corresponding to the Regs member labeled by field_name | ||
| 26 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions | ||
| 27 | // when used with array elements (e.g. PICA_REG_INDEX(vs_uniform_setup.set_value[1])). | ||
| 28 | // For details cf. | ||
| 29 | // https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | ||
| 30 | // Hopefully, this will be fixed sometime in the future. | ||
| 31 | // For lack of better alternatives, we currently hardcode the offsets when constant | ||
| 32 | // expressions are needed via PICA_REG_INDEX_WORKAROUND (on sane compilers, static_asserts | ||
| 33 | // will then make sure the offsets indeed match the automatically calculated ones). | ||
| 34 | #define PICA_REG_INDEX(field_name) (offsetof(Pica::Regs, field_name) / sizeof(u32)) | ||
| 35 | #if defined(_MSC_VER) | ||
| 36 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) (backup_workaround_index) | ||
| 37 | #else | ||
| 38 | // NOTE: Yeah, hacking in a static_assert here just to workaround the lacking MSVC compiler | ||
| 39 | // really is this annoying. This macro just forwards its first argument to PICA_REG_INDEX | ||
| 40 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected | ||
| 41 | // field offset. Otherwise, the compiler will fail to compile this code. | ||
| 42 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ | ||
| 43 | ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \ | ||
| 44 | size_t>::type)PICA_REG_INDEX(field_name)) | ||
| 45 | #endif // _MSC_VER | ||
| 46 | |||
| 47 | struct Regs { | ||
| 48 | INSERT_PADDING_WORDS(0x10); | ||
| 49 | u32 trigger_irq; | ||
| 50 | INSERT_PADDING_WORDS(0x2f); | ||
| 51 | RasterizerRegs rasterizer; | ||
| 52 | TexturingRegs texturing; | ||
| 53 | FramebufferRegs framebuffer; | ||
| 54 | LightingRegs lighting; | ||
| 55 | PipelineRegs pipeline; | ||
| 56 | ShaderRegs gs; | ||
| 57 | ShaderRegs vs; | ||
| 58 | INSERT_PADDING_WORDS(0x20); | ||
| 59 | |||
| 60 | // Map register indices to names readable by humans | ||
| 61 | // Used for debugging purposes, so performance is not an issue here | ||
| 62 | static std::string GetCommandName(int index); | ||
| 63 | |||
| 64 | static constexpr size_t NumIds() { | ||
| 65 | return sizeof(Regs) / sizeof(u32); | ||
| 66 | } | ||
| 67 | |||
| 68 | const u32& operator[](int index) const { | ||
| 69 | const u32* content = reinterpret_cast<const u32*>(this); | ||
| 70 | return content[index]; | ||
| 71 | } | ||
| 72 | |||
| 73 | u32& operator[](int index) { | ||
| 74 | u32* content = reinterpret_cast<u32*>(this); | ||
| 75 | return content[index]; | ||
| 76 | } | ||
| 77 | |||
| 78 | private: | ||
| 79 | /* | ||
| 80 | * Most physical addresses which Pica registers refer to are 8-byte aligned. | ||
| 81 | * This function should be used to get the address from a raw register value. | ||
| 82 | */ | ||
| 83 | static inline u32 DecodeAddressRegister(u32 register_value) { | ||
| 84 | return register_value * 8; | ||
| 85 | } | ||
| 86 | }; | ||
| 87 | |||
| 88 | // TODO: MSVC does not support using offsetof() on non-static data members even though this | ||
| 89 | // is technically allowed since C++11. This macro should be enabled once MSVC adds | ||
| 90 | // support for that. | ||
| 91 | #ifndef _MSC_VER | ||
| 92 | #define ASSERT_REG_POSITION(field_name, position) \ | ||
| 93 | static_assert(offsetof(Regs, field_name) == position * 4, \ | ||
| 94 | "Field " #field_name " has invalid position") | ||
| 95 | |||
| 96 | ASSERT_REG_POSITION(trigger_irq, 0x10); | ||
| 97 | |||
| 98 | ASSERT_REG_POSITION(rasterizer, 0x40); | ||
| 99 | ASSERT_REG_POSITION(rasterizer.cull_mode, 0x40); | ||
| 100 | ASSERT_REG_POSITION(rasterizer.viewport_size_x, 0x41); | ||
| 101 | ASSERT_REG_POSITION(rasterizer.viewport_size_y, 0x43); | ||
| 102 | ASSERT_REG_POSITION(rasterizer.viewport_depth_range, 0x4d); | ||
| 103 | ASSERT_REG_POSITION(rasterizer.viewport_depth_near_plane, 0x4e); | ||
| 104 | ASSERT_REG_POSITION(rasterizer.vs_output_attributes[0], 0x50); | ||
| 105 | ASSERT_REG_POSITION(rasterizer.vs_output_attributes[1], 0x51); | ||
| 106 | ASSERT_REG_POSITION(rasterizer.scissor_test, 0x65); | ||
| 107 | ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68); | ||
| 108 | ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D); | ||
| 109 | |||
| 110 | ASSERT_REG_POSITION(texturing, 0x80); | ||
| 111 | ASSERT_REG_POSITION(texturing.texture0_enable, 0x80); | ||
| 112 | ASSERT_REG_POSITION(texturing.texture0, 0x81); | ||
| 113 | ASSERT_REG_POSITION(texturing.texture0_format, 0x8e); | ||
| 114 | ASSERT_REG_POSITION(texturing.fragment_lighting_enable, 0x8f); | ||
| 115 | ASSERT_REG_POSITION(texturing.texture1, 0x91); | ||
| 116 | ASSERT_REG_POSITION(texturing.texture1_format, 0x96); | ||
| 117 | ASSERT_REG_POSITION(texturing.texture2, 0x99); | ||
| 118 | ASSERT_REG_POSITION(texturing.texture2_format, 0x9e); | ||
| 119 | ASSERT_REG_POSITION(texturing.tev_stage0, 0xc0); | ||
| 120 | ASSERT_REG_POSITION(texturing.tev_stage1, 0xc8); | ||
| 121 | ASSERT_REG_POSITION(texturing.tev_stage2, 0xd0); | ||
| 122 | ASSERT_REG_POSITION(texturing.tev_stage3, 0xd8); | ||
| 123 | ASSERT_REG_POSITION(texturing.tev_combiner_buffer_input, 0xe0); | ||
| 124 | ASSERT_REG_POSITION(texturing.fog_mode, 0xe0); | ||
| 125 | ASSERT_REG_POSITION(texturing.fog_color, 0xe1); | ||
| 126 | ASSERT_REG_POSITION(texturing.fog_lut_offset, 0xe6); | ||
| 127 | ASSERT_REG_POSITION(texturing.fog_lut_data, 0xe8); | ||
| 128 | ASSERT_REG_POSITION(texturing.tev_stage4, 0xf0); | ||
| 129 | ASSERT_REG_POSITION(texturing.tev_stage5, 0xf8); | ||
| 130 | ASSERT_REG_POSITION(texturing.tev_combiner_buffer_color, 0xfd); | ||
| 131 | |||
| 132 | ASSERT_REG_POSITION(framebuffer, 0x100); | ||
| 133 | ASSERT_REG_POSITION(framebuffer.output_merger, 0x100); | ||
| 134 | ASSERT_REG_POSITION(framebuffer.framebuffer, 0x110); | ||
| 135 | |||
| 136 | ASSERT_REG_POSITION(lighting, 0x140); | ||
| 137 | |||
| 138 | ASSERT_REG_POSITION(pipeline, 0x200); | ||
| 139 | ASSERT_REG_POSITION(pipeline.vertex_attributes, 0x200); | ||
| 140 | ASSERT_REG_POSITION(pipeline.index_array, 0x227); | ||
| 141 | ASSERT_REG_POSITION(pipeline.num_vertices, 0x228); | ||
| 142 | ASSERT_REG_POSITION(pipeline.vertex_offset, 0x22a); | ||
| 143 | ASSERT_REG_POSITION(pipeline.trigger_draw, 0x22e); | ||
| 144 | ASSERT_REG_POSITION(pipeline.trigger_draw_indexed, 0x22f); | ||
| 145 | ASSERT_REG_POSITION(pipeline.vs_default_attributes_setup, 0x232); | ||
| 146 | ASSERT_REG_POSITION(pipeline.command_buffer, 0x238); | ||
| 147 | ASSERT_REG_POSITION(pipeline.gpu_mode, 0x245); | ||
| 148 | ASSERT_REG_POSITION(pipeline.triangle_topology, 0x25e); | ||
| 149 | ASSERT_REG_POSITION(pipeline.restart_primitive, 0x25f); | ||
| 150 | |||
| 151 | ASSERT_REG_POSITION(gs, 0x280); | ||
| 152 | ASSERT_REG_POSITION(vs, 0x2b0); | ||
| 153 | |||
| 154 | #undef ASSERT_REG_POSITION | ||
| 155 | #endif // !defined(_MSC_VER) | ||
| 156 | |||
| 157 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value | ||
| 158 | // anyway. | ||
| 159 | static_assert(sizeof(Regs) <= 0x300 * sizeof(u32), | ||
| 160 | "Register set structure larger than it should be"); | ||
| 161 | static_assert(sizeof(Regs) >= 0x300 * sizeof(u32), | ||
| 162 | "Register set structure smaller than it should be"); | ||
| 163 | |||
| 164 | } // namespace Pica | ||
diff --git a/src/video_core/regs_framebuffer.h b/src/video_core/regs_framebuffer.h new file mode 100644 index 000000000..366782080 --- /dev/null +++ b/src/video_core/regs_framebuffer.h | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_funcs.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "common/logging/log.h" | ||
| 14 | |||
| 15 | namespace Pica { | ||
| 16 | |||
| 17 | struct FramebufferRegs { | ||
| 18 | enum class LogicOp : u32 { | ||
| 19 | Clear = 0, | ||
| 20 | And = 1, | ||
| 21 | AndReverse = 2, | ||
| 22 | Copy = 3, | ||
| 23 | Set = 4, | ||
| 24 | CopyInverted = 5, | ||
| 25 | NoOp = 6, | ||
| 26 | Invert = 7, | ||
| 27 | Nand = 8, | ||
| 28 | Or = 9, | ||
| 29 | Nor = 10, | ||
| 30 | Xor = 11, | ||
| 31 | Equiv = 12, | ||
| 32 | AndInverted = 13, | ||
| 33 | OrReverse = 14, | ||
| 34 | OrInverted = 15, | ||
| 35 | }; | ||
| 36 | |||
| 37 | enum class BlendEquation : u32 { | ||
| 38 | Add = 0, | ||
| 39 | Subtract = 1, | ||
| 40 | ReverseSubtract = 2, | ||
| 41 | Min = 3, | ||
| 42 | Max = 4, | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum class BlendFactor : u32 { | ||
| 46 | Zero = 0, | ||
| 47 | One = 1, | ||
| 48 | SourceColor = 2, | ||
| 49 | OneMinusSourceColor = 3, | ||
| 50 | DestColor = 4, | ||
| 51 | OneMinusDestColor = 5, | ||
| 52 | SourceAlpha = 6, | ||
| 53 | OneMinusSourceAlpha = 7, | ||
| 54 | DestAlpha = 8, | ||
| 55 | OneMinusDestAlpha = 9, | ||
| 56 | ConstantColor = 10, | ||
| 57 | OneMinusConstantColor = 11, | ||
| 58 | ConstantAlpha = 12, | ||
| 59 | OneMinusConstantAlpha = 13, | ||
| 60 | SourceAlphaSaturate = 14, | ||
| 61 | }; | ||
| 62 | |||
| 63 | enum class CompareFunc : u32 { | ||
| 64 | Never = 0, | ||
| 65 | Always = 1, | ||
| 66 | Equal = 2, | ||
| 67 | NotEqual = 3, | ||
| 68 | LessThan = 4, | ||
| 69 | LessThanOrEqual = 5, | ||
| 70 | GreaterThan = 6, | ||
| 71 | GreaterThanOrEqual = 7, | ||
| 72 | }; | ||
| 73 | |||
| 74 | enum class StencilAction : u32 { | ||
| 75 | Keep = 0, | ||
| 76 | Zero = 1, | ||
| 77 | Replace = 2, | ||
| 78 | Increment = 3, | ||
| 79 | Decrement = 4, | ||
| 80 | Invert = 5, | ||
| 81 | IncrementWrap = 6, | ||
| 82 | DecrementWrap = 7, | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct { | ||
| 86 | union { | ||
| 87 | // If false, logic blending is used | ||
| 88 | BitField<8, 1, u32> alphablend_enable; | ||
| 89 | }; | ||
| 90 | |||
| 91 | union { | ||
| 92 | BitField<0, 8, BlendEquation> blend_equation_rgb; | ||
| 93 | BitField<8, 8, BlendEquation> blend_equation_a; | ||
| 94 | |||
| 95 | BitField<16, 4, BlendFactor> factor_source_rgb; | ||
| 96 | BitField<20, 4, BlendFactor> factor_dest_rgb; | ||
| 97 | |||
| 98 | BitField<24, 4, BlendFactor> factor_source_a; | ||
| 99 | BitField<28, 4, BlendFactor> factor_dest_a; | ||
| 100 | } alpha_blending; | ||
| 101 | |||
| 102 | union { | ||
| 103 | BitField<0, 4, LogicOp> logic_op; | ||
| 104 | }; | ||
| 105 | |||
| 106 | union { | ||
| 107 | u32 raw; | ||
| 108 | BitField<0, 8, u32> r; | ||
| 109 | BitField<8, 8, u32> g; | ||
| 110 | BitField<16, 8, u32> b; | ||
| 111 | BitField<24, 8, u32> a; | ||
| 112 | } blend_const; | ||
| 113 | |||
| 114 | union { | ||
| 115 | BitField<0, 1, u32> enable; | ||
| 116 | BitField<4, 3, CompareFunc> func; | ||
| 117 | BitField<8, 8, u32> ref; | ||
| 118 | } alpha_test; | ||
| 119 | |||
| 120 | struct { | ||
| 121 | union { | ||
| 122 | // Raw value of this register | ||
| 123 | u32 raw_func; | ||
| 124 | |||
| 125 | // If true, enable stencil testing | ||
| 126 | BitField<0, 1, u32> enable; | ||
| 127 | |||
| 128 | // Comparison operation for stencil testing | ||
| 129 | BitField<4, 3, CompareFunc> func; | ||
| 130 | |||
| 131 | // Mask used to control writing to the stencil buffer | ||
| 132 | BitField<8, 8, u32> write_mask; | ||
| 133 | |||
| 134 | // Value to compare against for stencil testing | ||
| 135 | BitField<16, 8, u32> reference_value; | ||
| 136 | |||
| 137 | // Mask to apply on stencil test inputs | ||
| 138 | BitField<24, 8, u32> input_mask; | ||
| 139 | }; | ||
| 140 | |||
| 141 | union { | ||
| 142 | // Raw value of this register | ||
| 143 | u32 raw_op; | ||
| 144 | |||
| 145 | // Action to perform when the stencil test fails | ||
| 146 | BitField<0, 3, StencilAction> action_stencil_fail; | ||
| 147 | |||
| 148 | // Action to perform when stencil testing passed but depth testing fails | ||
| 149 | BitField<4, 3, StencilAction> action_depth_fail; | ||
| 150 | |||
| 151 | // Action to perform when both stencil and depth testing pass | ||
| 152 | BitField<8, 3, StencilAction> action_depth_pass; | ||
| 153 | }; | ||
| 154 | } stencil_test; | ||
| 155 | |||
| 156 | union { | ||
| 157 | BitField<0, 1, u32> depth_test_enable; | ||
| 158 | BitField<4, 3, CompareFunc> depth_test_func; | ||
| 159 | BitField<8, 1, u32> red_enable; | ||
| 160 | BitField<9, 1, u32> green_enable; | ||
| 161 | BitField<10, 1, u32> blue_enable; | ||
| 162 | BitField<11, 1, u32> alpha_enable; | ||
| 163 | BitField<12, 1, u32> depth_write_enable; | ||
| 164 | }; | ||
| 165 | |||
| 166 | INSERT_PADDING_WORDS(0x8); | ||
| 167 | } output_merger; | ||
| 168 | |||
| 169 | // Components are laid out in reverse byte order, most significant bits first. | ||
| 170 | enum class ColorFormat : u32 { | ||
| 171 | RGBA8 = 0, | ||
| 172 | RGB8 = 1, | ||
| 173 | RGB5A1 = 2, | ||
| 174 | RGB565 = 3, | ||
| 175 | RGBA4 = 4, | ||
| 176 | }; | ||
| 177 | |||
| 178 | enum class DepthFormat : u32 { | ||
| 179 | D16 = 0, | ||
| 180 | D24 = 2, | ||
| 181 | D24S8 = 3, | ||
| 182 | }; | ||
| 183 | |||
| 184 | // Returns the number of bytes in the specified color format | ||
| 185 | static unsigned BytesPerColorPixel(ColorFormat format) { | ||
| 186 | switch (format) { | ||
| 187 | case ColorFormat::RGBA8: | ||
| 188 | return 4; | ||
| 189 | case ColorFormat::RGB8: | ||
| 190 | return 3; | ||
| 191 | case ColorFormat::RGB5A1: | ||
| 192 | case ColorFormat::RGB565: | ||
| 193 | case ColorFormat::RGBA4: | ||
| 194 | return 2; | ||
| 195 | default: | ||
| 196 | LOG_CRITICAL(HW_GPU, "Unknown color format %u", format); | ||
| 197 | UNIMPLEMENTED(); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | struct FramebufferConfig { | ||
| 202 | INSERT_PADDING_WORDS(0x3); | ||
| 203 | |||
| 204 | union { | ||
| 205 | BitField<0, 4, u32> allow_color_write; // 0 = disable, else enable | ||
| 206 | }; | ||
| 207 | |||
| 208 | INSERT_PADDING_WORDS(0x1); | ||
| 209 | |||
| 210 | union { | ||
| 211 | BitField<0, 2, u32> allow_depth_stencil_write; // 0 = disable, else enable | ||
| 212 | }; | ||
| 213 | |||
| 214 | DepthFormat depth_format; // TODO: Should be a BitField! | ||
| 215 | BitField<16, 3, ColorFormat> color_format; | ||
| 216 | |||
| 217 | INSERT_PADDING_WORDS(0x4); | ||
| 218 | |||
| 219 | u32 depth_buffer_address; | ||
| 220 | u32 color_buffer_address; | ||
| 221 | |||
| 222 | union { | ||
| 223 | // Apparently, the framebuffer width is stored as expected, | ||
| 224 | // while the height is stored as the actual height minus one. | ||
| 225 | // Hence, don't access these fields directly but use the accessors | ||
| 226 | // GetWidth() and GetHeight() instead. | ||
| 227 | BitField<0, 11, u32> width; | ||
| 228 | BitField<12, 10, u32> height; | ||
| 229 | }; | ||
| 230 | |||
| 231 | INSERT_PADDING_WORDS(0x1); | ||
| 232 | |||
| 233 | inline PAddr GetColorBufferPhysicalAddress() const { | ||
| 234 | return color_buffer_address * 8; | ||
| 235 | } | ||
| 236 | inline PAddr GetDepthBufferPhysicalAddress() const { | ||
| 237 | return depth_buffer_address * 8; | ||
| 238 | } | ||
| 239 | |||
| 240 | inline u32 GetWidth() const { | ||
| 241 | return width; | ||
| 242 | } | ||
| 243 | |||
| 244 | inline u32 GetHeight() const { | ||
| 245 | return height + 1; | ||
| 246 | } | ||
| 247 | } framebuffer; | ||
| 248 | |||
| 249 | // Returns the number of bytes in the specified depth format | ||
| 250 | static u32 BytesPerDepthPixel(DepthFormat format) { | ||
| 251 | switch (format) { | ||
| 252 | case DepthFormat::D16: | ||
| 253 | return 2; | ||
| 254 | case DepthFormat::D24: | ||
| 255 | return 3; | ||
| 256 | case DepthFormat::D24S8: | ||
| 257 | return 4; | ||
| 258 | default: | ||
| 259 | LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); | ||
| 260 | UNIMPLEMENTED(); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | // Returns the number of bits per depth component of the specified depth format | ||
| 265 | static u32 DepthBitsPerPixel(DepthFormat format) { | ||
| 266 | switch (format) { | ||
| 267 | case DepthFormat::D16: | ||
| 268 | return 16; | ||
| 269 | case DepthFormat::D24: | ||
| 270 | case DepthFormat::D24S8: | ||
| 271 | return 24; | ||
| 272 | default: | ||
| 273 | LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); | ||
| 274 | UNIMPLEMENTED(); | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | INSERT_PADDING_WORDS(0x20); | ||
| 279 | }; | ||
| 280 | |||
| 281 | static_assert(sizeof(FramebufferRegs) == 0x40 * sizeof(u32), | ||
| 282 | "FramebufferRegs struct has incorrect size"); | ||
| 283 | |||
| 284 | } // namespace Pica | ||
diff --git a/src/video_core/regs_lighting.h b/src/video_core/regs_lighting.h new file mode 100644 index 000000000..548a6c4d5 --- /dev/null +++ b/src/video_core/regs_lighting.h | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_funcs.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "common/vector_math.h" | ||
| 14 | |||
| 15 | namespace Pica { | ||
| 16 | |||
| 17 | struct LightingRegs { | ||
| 18 | enum class LightingSampler { | ||
| 19 | Distribution0 = 0, | ||
| 20 | Distribution1 = 1, | ||
| 21 | Fresnel = 3, | ||
| 22 | ReflectBlue = 4, | ||
| 23 | ReflectGreen = 5, | ||
| 24 | ReflectRed = 6, | ||
| 25 | SpotlightAttenuation = 8, | ||
| 26 | DistanceAttenuation = 16, | ||
| 27 | }; | ||
| 28 | |||
| 29 | /** | ||
| 30 | * Pica fragment lighting supports using different LUTs for each lighting component: Reflectance | ||
| 31 | * R, G, and B channels, distribution function for specular components 0 and 1, fresnel factor, | ||
| 32 | * and spotlight attenuation. Furthermore, which LUTs are used for each channel (or whether a | ||
| 33 | * channel is enabled at all) is specified by various pre-defined lighting configurations. With | ||
| 34 | * configurations that require more LUTs, more cycles are required on HW to perform lighting | ||
| 35 | * computations. | ||
| 36 | */ | ||
| 37 | enum class LightingConfig { | ||
| 38 | Config0 = 0, ///< Reflect Red, Distribution 0, Spotlight | ||
| 39 | Config1 = 1, ///< Reflect Red, Fresnel, Spotlight | ||
| 40 | Config2 = 2, ///< Reflect Red, Distribution 0/1 | ||
| 41 | Config3 = 3, ///< Distribution 0/1, Fresnel | ||
| 42 | Config4 = 4, ///< Reflect Red/Green/Blue, Distribution 0/1, Spotlight | ||
| 43 | Config5 = 5, ///< Reflect Red/Green/Blue, Distribution 0, Fresnel, Spotlight | ||
| 44 | Config6 = 6, ///< Reflect Red, Distribution 0/1, Fresnel, Spotlight | ||
| 45 | |||
| 46 | Config7 = 8, ///< Reflect Red/Green/Blue, Distribution 0/1, Fresnel, Spotlight | ||
| 47 | ///< NOTE: '8' is intentional, '7' does not appear to be a valid configuration | ||
| 48 | }; | ||
| 49 | |||
| 50 | /// Selects which lighting components are affected by fresnel | ||
| 51 | enum class LightingFresnelSelector { | ||
| 52 | None = 0, ///< Fresnel is disabled | ||
| 53 | PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel | ||
| 54 | SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel | ||
| 55 | Both = | ||
| 56 | PrimaryAlpha | | ||
| 57 | SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel | ||
| 58 | }; | ||
| 59 | |||
| 60 | /// Factor used to scale the output of a lighting LUT | ||
| 61 | enum class LightingScale { | ||
| 62 | Scale1 = 0, ///< Scale is 1x | ||
| 63 | Scale2 = 1, ///< Scale is 2x | ||
| 64 | Scale4 = 2, ///< Scale is 4x | ||
| 65 | Scale8 = 3, ///< Scale is 8x | ||
| 66 | |||
| 67 | Scale1_4 = 6, ///< Scale is 0.25x | ||
| 68 | Scale1_2 = 7, ///< Scale is 0.5x | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum class LightingLutInput { | ||
| 72 | NH = 0, // Cosine of the angle between the normal and half-angle vectors | ||
| 73 | VH = 1, // Cosine of the angle between the view and half-angle vectors | ||
| 74 | NV = 2, // Cosine of the angle between the normal and the view vector | ||
| 75 | LN = 3, // Cosine of the angle between the light and the normal vectors | ||
| 76 | }; | ||
| 77 | |||
| 78 | enum class LightingBumpMode : u32 { | ||
| 79 | None = 0, | ||
| 80 | NormalMap = 1, | ||
| 81 | TangentMap = 2, | ||
| 82 | }; | ||
| 83 | |||
| 84 | union LightColor { | ||
| 85 | BitField<0, 10, u32> b; | ||
| 86 | BitField<10, 10, u32> g; | ||
| 87 | BitField<20, 10, u32> r; | ||
| 88 | |||
| 89 | Math::Vec3f ToVec3f() const { | ||
| 90 | // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color | ||
| 91 | // component | ||
| 92 | return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); | ||
| 93 | } | ||
| 94 | }; | ||
| 95 | |||
| 96 | /// Returns true if the specified lighting sampler is supported by the current Pica lighting | ||
| 97 | /// configuration | ||
| 98 | static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) { | ||
| 99 | switch (sampler) { | ||
| 100 | case LightingSampler::Distribution0: | ||
| 101 | return (config != LightingConfig::Config1); | ||
| 102 | |||
| 103 | case LightingSampler::Distribution1: | ||
| 104 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && | ||
| 105 | (config != LightingConfig::Config5); | ||
| 106 | |||
| 107 | case LightingSampler::Fresnel: | ||
| 108 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && | ||
| 109 | (config != LightingConfig::Config4); | ||
| 110 | |||
| 111 | case LightingSampler::ReflectRed: | ||
| 112 | return (config != LightingConfig::Config3); | ||
| 113 | |||
| 114 | case LightingSampler::ReflectGreen: | ||
| 115 | case LightingSampler::ReflectBlue: | ||
| 116 | return (config == LightingConfig::Config4) || (config == LightingConfig::Config5) || | ||
| 117 | (config == LightingConfig::Config7); | ||
| 118 | default: | ||
| 119 | UNREACHABLE_MSG("Regs::IsLightingSamplerSupported: Reached " | ||
| 120 | "unreachable section, sampler should be one " | ||
| 121 | "of Distribution0, Distribution1, Fresnel, " | ||
| 122 | "ReflectRed, ReflectGreen or ReflectBlue, instead " | ||
| 123 | "got %i", | ||
| 124 | static_cast<int>(config)); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | struct LightSrc { | ||
| 129 | LightColor specular_0; // material.specular_0 * light.specular_0 | ||
| 130 | LightColor specular_1; // material.specular_1 * light.specular_1 | ||
| 131 | LightColor diffuse; // material.diffuse * light.diffuse | ||
| 132 | LightColor ambient; // material.ambient * light.ambient | ||
| 133 | |||
| 134 | // Encoded as 16-bit floating point | ||
| 135 | union { | ||
| 136 | BitField<0, 16, u32> x; | ||
| 137 | BitField<16, 16, u32> y; | ||
| 138 | }; | ||
| 139 | union { | ||
| 140 | BitField<0, 16, u32> z; | ||
| 141 | }; | ||
| 142 | |||
| 143 | INSERT_PADDING_WORDS(0x3); | ||
| 144 | |||
| 145 | union { | ||
| 146 | BitField<0, 1, u32> directional; | ||
| 147 | BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0 | ||
| 148 | } config; | ||
| 149 | |||
| 150 | BitField<0, 20, u32> dist_atten_bias; | ||
| 151 | BitField<0, 20, u32> dist_atten_scale; | ||
| 152 | |||
| 153 | INSERT_PADDING_WORDS(0x4); | ||
| 154 | }; | ||
| 155 | static_assert(sizeof(LightSrc) == 0x10 * sizeof(u32), "LightSrc structure must be 0x10 words"); | ||
| 156 | |||
| 157 | LightSrc light[8]; | ||
| 158 | LightColor global_ambient; // Emission + (material.ambient * lighting.ambient) | ||
| 159 | INSERT_PADDING_WORDS(0x1); | ||
| 160 | BitField<0, 3, u32> max_light_index; // Number of enabled lights - 1 | ||
| 161 | |||
| 162 | union { | ||
| 163 | BitField<2, 2, LightingFresnelSelector> fresnel_selector; | ||
| 164 | BitField<4, 4, LightingConfig> config; | ||
| 165 | BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2 | ||
| 166 | BitField<27, 1, u32> clamp_highlights; | ||
| 167 | BitField<28, 2, LightingBumpMode> bump_mode; | ||
| 168 | BitField<30, 1, u32> disable_bump_renorm; | ||
| 169 | } config0; | ||
| 170 | |||
| 171 | union { | ||
| 172 | BitField<16, 1, u32> disable_lut_d0; | ||
| 173 | BitField<17, 1, u32> disable_lut_d1; | ||
| 174 | BitField<19, 1, u32> disable_lut_fr; | ||
| 175 | BitField<20, 1, u32> disable_lut_rr; | ||
| 176 | BitField<21, 1, u32> disable_lut_rg; | ||
| 177 | BitField<22, 1, u32> disable_lut_rb; | ||
| 178 | |||
| 179 | // Each bit specifies whether distance attenuation should be applied for the corresponding | ||
| 180 | // light. | ||
| 181 | BitField<24, 1, u32> disable_dist_atten_light_0; | ||
| 182 | BitField<25, 1, u32> disable_dist_atten_light_1; | ||
| 183 | BitField<26, 1, u32> disable_dist_atten_light_2; | ||
| 184 | BitField<27, 1, u32> disable_dist_atten_light_3; | ||
| 185 | BitField<28, 1, u32> disable_dist_atten_light_4; | ||
| 186 | BitField<29, 1, u32> disable_dist_atten_light_5; | ||
| 187 | BitField<30, 1, u32> disable_dist_atten_light_6; | ||
| 188 | BitField<31, 1, u32> disable_dist_atten_light_7; | ||
| 189 | } config1; | ||
| 190 | |||
| 191 | bool IsDistAttenDisabled(unsigned index) const { | ||
| 192 | const unsigned disable[] = { | ||
| 193 | config1.disable_dist_atten_light_0, config1.disable_dist_atten_light_1, | ||
| 194 | config1.disable_dist_atten_light_2, config1.disable_dist_atten_light_3, | ||
| 195 | config1.disable_dist_atten_light_4, config1.disable_dist_atten_light_5, | ||
| 196 | config1.disable_dist_atten_light_6, config1.disable_dist_atten_light_7}; | ||
| 197 | return disable[index] != 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | union { | ||
| 201 | BitField<0, 8, u32> index; ///< Index at which to set data in the LUT | ||
| 202 | BitField<8, 5, u32> type; ///< Type of LUT for which to set data | ||
| 203 | } lut_config; | ||
| 204 | |||
| 205 | BitField<0, 1, u32> disable; | ||
| 206 | INSERT_PADDING_WORDS(0x1); | ||
| 207 | |||
| 208 | // When data is written to any of these registers, it gets written to the lookup table of the | ||
| 209 | // selected type at the selected index, specified above in the `lut_config` register. With each | ||
| 210 | // write, `lut_config.index` is incremented. It does not matter which of these registers is | ||
| 211 | // written to, the behavior will be the same. | ||
| 212 | u32 lut_data[8]; | ||
| 213 | |||
| 214 | // These are used to specify if absolute (abs) value should be used for each LUT index. When | ||
| 215 | // abs mode is disabled, LUT indexes are in the range of (-1.0, 1.0). Otherwise, they are in | ||
| 216 | // the range of (0.0, 1.0). | ||
| 217 | union { | ||
| 218 | BitField<1, 1, u32> disable_d0; | ||
| 219 | BitField<5, 1, u32> disable_d1; | ||
| 220 | BitField<9, 1, u32> disable_sp; | ||
| 221 | BitField<13, 1, u32> disable_fr; | ||
| 222 | BitField<17, 1, u32> disable_rb; | ||
| 223 | BitField<21, 1, u32> disable_rg; | ||
| 224 | BitField<25, 1, u32> disable_rr; | ||
| 225 | } abs_lut_input; | ||
| 226 | |||
| 227 | union { | ||
| 228 | BitField<0, 3, LightingLutInput> d0; | ||
| 229 | BitField<4, 3, LightingLutInput> d1; | ||
| 230 | BitField<8, 3, LightingLutInput> sp; | ||
| 231 | BitField<12, 3, LightingLutInput> fr; | ||
| 232 | BitField<16, 3, LightingLutInput> rb; | ||
| 233 | BitField<20, 3, LightingLutInput> rg; | ||
| 234 | BitField<24, 3, LightingLutInput> rr; | ||
| 235 | } lut_input; | ||
| 236 | |||
| 237 | union { | ||
| 238 | BitField<0, 3, LightingScale> d0; | ||
| 239 | BitField<4, 3, LightingScale> d1; | ||
| 240 | BitField<8, 3, LightingScale> sp; | ||
| 241 | BitField<12, 3, LightingScale> fr; | ||
| 242 | BitField<16, 3, LightingScale> rb; | ||
| 243 | BitField<20, 3, LightingScale> rg; | ||
| 244 | BitField<24, 3, LightingScale> rr; | ||
| 245 | |||
| 246 | static float GetScale(LightingScale scale) { | ||
| 247 | switch (scale) { | ||
| 248 | case LightingScale::Scale1: | ||
| 249 | return 1.0f; | ||
| 250 | case LightingScale::Scale2: | ||
| 251 | return 2.0f; | ||
| 252 | case LightingScale::Scale4: | ||
| 253 | return 4.0f; | ||
| 254 | case LightingScale::Scale8: | ||
| 255 | return 8.0f; | ||
| 256 | case LightingScale::Scale1_4: | ||
| 257 | return 0.25f; | ||
| 258 | case LightingScale::Scale1_2: | ||
| 259 | return 0.5f; | ||
| 260 | } | ||
| 261 | return 0.0f; | ||
| 262 | } | ||
| 263 | } lut_scale; | ||
| 264 | |||
| 265 | INSERT_PADDING_WORDS(0x6); | ||
| 266 | |||
| 267 | union { | ||
| 268 | // There are 8 light enable "slots", corresponding to the total number of lights supported | ||
| 269 | // by Pica. For N enabled lights (specified by register 0x1c2, or 'src_num' above), the | ||
| 270 | // first N slots below will be set to integers within the range of 0-7, corresponding to the | ||
| 271 | // actual light that is enabled for each slot. | ||
| 272 | |||
| 273 | BitField<0, 3, u32> slot_0; | ||
| 274 | BitField<4, 3, u32> slot_1; | ||
| 275 | BitField<8, 3, u32> slot_2; | ||
| 276 | BitField<12, 3, u32> slot_3; | ||
| 277 | BitField<16, 3, u32> slot_4; | ||
| 278 | BitField<20, 3, u32> slot_5; | ||
| 279 | BitField<24, 3, u32> slot_6; | ||
| 280 | BitField<28, 3, u32> slot_7; | ||
| 281 | |||
| 282 | unsigned GetNum(unsigned index) const { | ||
| 283 | const unsigned enable_slots[] = {slot_0, slot_1, slot_2, slot_3, | ||
| 284 | slot_4, slot_5, slot_6, slot_7}; | ||
| 285 | return enable_slots[index]; | ||
| 286 | } | ||
| 287 | } light_enable; | ||
| 288 | |||
| 289 | INSERT_PADDING_WORDS(0x26); | ||
| 290 | }; | ||
| 291 | |||
| 292 | static_assert(sizeof(LightingRegs) == 0xC0 * sizeof(u32), "LightingRegs struct has incorrect size"); | ||
| 293 | |||
| 294 | } // namespace Pica | ||
diff --git a/src/video_core/regs_pipeline.h b/src/video_core/regs_pipeline.h new file mode 100644 index 000000000..5844a66ee --- /dev/null +++ b/src/video_core/regs_pipeline.h | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_funcs.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | |||
| 14 | namespace Pica { | ||
| 15 | |||
| 16 | struct PipelineRegs { | ||
| 17 | enum class VertexAttributeFormat : u64 { | ||
| 18 | BYTE = 0, | ||
| 19 | UBYTE = 1, | ||
| 20 | SHORT = 2, | ||
| 21 | FLOAT = 3, | ||
| 22 | }; | ||
| 23 | |||
| 24 | struct { | ||
| 25 | BitField<0, 29, u32> base_address; | ||
| 26 | |||
| 27 | PAddr GetPhysicalBaseAddress() const { | ||
| 28 | return base_address * 8; | ||
| 29 | } | ||
| 30 | |||
| 31 | // Descriptor for internal vertex attributes | ||
| 32 | union { | ||
| 33 | BitField<0, 2, VertexAttributeFormat> format0; // size of one element | ||
| 34 | BitField<2, 2, u64> size0; // number of elements minus 1 | ||
| 35 | BitField<4, 2, VertexAttributeFormat> format1; | ||
| 36 | BitField<6, 2, u64> size1; | ||
| 37 | BitField<8, 2, VertexAttributeFormat> format2; | ||
| 38 | BitField<10, 2, u64> size2; | ||
| 39 | BitField<12, 2, VertexAttributeFormat> format3; | ||
| 40 | BitField<14, 2, u64> size3; | ||
| 41 | BitField<16, 2, VertexAttributeFormat> format4; | ||
| 42 | BitField<18, 2, u64> size4; | ||
| 43 | BitField<20, 2, VertexAttributeFormat> format5; | ||
| 44 | BitField<22, 2, u64> size5; | ||
| 45 | BitField<24, 2, VertexAttributeFormat> format6; | ||
| 46 | BitField<26, 2, u64> size6; | ||
| 47 | BitField<28, 2, VertexAttributeFormat> format7; | ||
| 48 | BitField<30, 2, u64> size7; | ||
| 49 | BitField<32, 2, VertexAttributeFormat> format8; | ||
| 50 | BitField<34, 2, u64> size8; | ||
| 51 | BitField<36, 2, VertexAttributeFormat> format9; | ||
| 52 | BitField<38, 2, u64> size9; | ||
| 53 | BitField<40, 2, VertexAttributeFormat> format10; | ||
| 54 | BitField<42, 2, u64> size10; | ||
| 55 | BitField<44, 2, VertexAttributeFormat> format11; | ||
| 56 | BitField<46, 2, u64> size11; | ||
| 57 | |||
| 58 | BitField<48, 12, u64> attribute_mask; | ||
| 59 | |||
| 60 | // number of total attributes minus 1 | ||
| 61 | BitField<60, 4, u64> max_attribute_index; | ||
| 62 | }; | ||
| 63 | |||
| 64 | inline VertexAttributeFormat GetFormat(int n) const { | ||
| 65 | VertexAttributeFormat formats[] = {format0, format1, format2, format3, | ||
| 66 | format4, format5, format6, format7, | ||
| 67 | format8, format9, format10, format11}; | ||
| 68 | return formats[n]; | ||
| 69 | } | ||
| 70 | |||
| 71 | inline int GetNumElements(int n) const { | ||
| 72 | u64 sizes[] = {size0, size1, size2, size3, size4, size5, | ||
| 73 | size6, size7, size8, size9, size10, size11}; | ||
| 74 | return (int)sizes[n] + 1; | ||
| 75 | } | ||
| 76 | |||
| 77 | inline int GetElementSizeInBytes(int n) const { | ||
| 78 | return (GetFormat(n) == VertexAttributeFormat::FLOAT) | ||
| 79 | ? 4 | ||
| 80 | : (GetFormat(n) == VertexAttributeFormat::SHORT) ? 2 : 1; | ||
| 81 | } | ||
| 82 | |||
| 83 | inline int GetStride(int n) const { | ||
| 84 | return GetNumElements(n) * GetElementSizeInBytes(n); | ||
| 85 | } | ||
| 86 | |||
| 87 | inline bool IsDefaultAttribute(int id) const { | ||
| 88 | return (id >= 12) || (attribute_mask & (1ULL << id)) != 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | inline int GetNumTotalAttributes() const { | ||
| 92 | return (int)max_attribute_index + 1; | ||
| 93 | } | ||
| 94 | |||
| 95 | // Attribute loaders map the source vertex data to input attributes | ||
| 96 | // This e.g. allows to load different attributes from different memory locations | ||
| 97 | struct { | ||
| 98 | // Source attribute data offset from the base address | ||
| 99 | u32 data_offset; | ||
| 100 | |||
| 101 | union { | ||
| 102 | BitField<0, 4, u64> comp0; | ||
| 103 | BitField<4, 4, u64> comp1; | ||
| 104 | BitField<8, 4, u64> comp2; | ||
| 105 | BitField<12, 4, u64> comp3; | ||
| 106 | BitField<16, 4, u64> comp4; | ||
| 107 | BitField<20, 4, u64> comp5; | ||
| 108 | BitField<24, 4, u64> comp6; | ||
| 109 | BitField<28, 4, u64> comp7; | ||
| 110 | BitField<32, 4, u64> comp8; | ||
| 111 | BitField<36, 4, u64> comp9; | ||
| 112 | BitField<40, 4, u64> comp10; | ||
| 113 | BitField<44, 4, u64> comp11; | ||
| 114 | |||
| 115 | // bytes for a single vertex in this loader | ||
| 116 | BitField<48, 8, u64> byte_count; | ||
| 117 | |||
| 118 | BitField<60, 4, u64> component_count; | ||
| 119 | }; | ||
| 120 | |||
| 121 | inline int GetComponent(int n) const { | ||
| 122 | u64 components[] = {comp0, comp1, comp2, comp3, comp4, comp5, | ||
| 123 | comp6, comp7, comp8, comp9, comp10, comp11}; | ||
| 124 | return (int)components[n]; | ||
| 125 | } | ||
| 126 | } attribute_loaders[12]; | ||
| 127 | } vertex_attributes; | ||
| 128 | |||
| 129 | struct { | ||
| 130 | enum IndexFormat : u32 { | ||
| 131 | BYTE = 0, | ||
| 132 | SHORT = 1, | ||
| 133 | }; | ||
| 134 | |||
| 135 | union { | ||
| 136 | BitField<0, 31, u32> offset; // relative to base attribute address | ||
| 137 | BitField<31, 1, IndexFormat> format; | ||
| 138 | }; | ||
| 139 | } index_array; | ||
| 140 | |||
| 141 | // Number of vertices to render | ||
| 142 | u32 num_vertices; | ||
| 143 | |||
| 144 | INSERT_PADDING_WORDS(0x1); | ||
| 145 | |||
| 146 | // The index of the first vertex to render | ||
| 147 | u32 vertex_offset; | ||
| 148 | |||
| 149 | INSERT_PADDING_WORDS(0x3); | ||
| 150 | |||
| 151 | // These two trigger rendering of triangles | ||
| 152 | u32 trigger_draw; | ||
| 153 | u32 trigger_draw_indexed; | ||
| 154 | |||
| 155 | INSERT_PADDING_WORDS(0x2); | ||
| 156 | |||
| 157 | // These registers are used to setup the default "fall-back" vertex shader attributes | ||
| 158 | struct { | ||
| 159 | // Index of the current default attribute | ||
| 160 | u32 index; | ||
| 161 | |||
| 162 | // Writing to these registers sets the "current" default attribute. | ||
| 163 | u32 set_value[3]; | ||
| 164 | } vs_default_attributes_setup; | ||
| 165 | |||
| 166 | INSERT_PADDING_WORDS(0x2); | ||
| 167 | |||
| 168 | struct { | ||
| 169 | // There are two channels that can be used to configure the next command buffer, which can | ||
| 170 | // be then executed by writing to the "trigger" registers. There are two reasons why a game | ||
| 171 | // might use this feature: | ||
| 172 | // 1) With this, an arbitrary number of additional command buffers may be executed in | ||
| 173 | // sequence without requiring any intervention of the CPU after the initial one is | ||
| 174 | // kicked off. | ||
| 175 | // 2) Games can configure these registers to provide a command list subroutine mechanism. | ||
| 176 | |||
| 177 | BitField<0, 20, u32> size[2]; ///< Size (in bytes / 8) of each channel's command buffer | ||
| 178 | BitField<0, 28, u32> addr[2]; ///< Physical address / 8 of each channel's command buffer | ||
| 179 | u32 trigger[2]; ///< Triggers execution of the channel's command buffer when written to | ||
| 180 | |||
| 181 | unsigned GetSize(unsigned index) const { | ||
| 182 | ASSERT(index < 2); | ||
| 183 | return 8 * size[index]; | ||
| 184 | } | ||
| 185 | |||
| 186 | PAddr GetPhysicalAddress(unsigned index) const { | ||
| 187 | ASSERT(index < 2); | ||
| 188 | return (PAddr)(8 * addr[index]); | ||
| 189 | } | ||
| 190 | } command_buffer; | ||
| 191 | |||
| 192 | INSERT_PADDING_WORDS(4); | ||
| 193 | |||
| 194 | /// Number of input attributes to the vertex shader minus 1 | ||
| 195 | BitField<0, 4, u32> max_input_attrib_index; | ||
| 196 | |||
| 197 | INSERT_PADDING_WORDS(2); | ||
| 198 | |||
| 199 | enum class GPUMode : u32 { | ||
| 200 | Drawing = 0, | ||
| 201 | Configuring = 1, | ||
| 202 | }; | ||
| 203 | |||
| 204 | GPUMode gpu_mode; | ||
| 205 | |||
| 206 | INSERT_PADDING_WORDS(0x18); | ||
| 207 | |||
| 208 | enum class TriangleTopology : u32 { | ||
| 209 | List = 0, | ||
| 210 | Strip = 1, | ||
| 211 | Fan = 2, | ||
| 212 | Shader = 3, // Programmable setup unit implemented in a geometry shader | ||
| 213 | }; | ||
| 214 | |||
| 215 | BitField<8, 2, TriangleTopology> triangle_topology; | ||
| 216 | |||
| 217 | u32 restart_primitive; | ||
| 218 | |||
| 219 | INSERT_PADDING_WORDS(0x20); | ||
| 220 | }; | ||
| 221 | |||
| 222 | static_assert(sizeof(PipelineRegs) == 0x80 * sizeof(u32), "PipelineRegs struct has incorrect size"); | ||
| 223 | |||
| 224 | } // namespace Pica | ||
diff --git a/src/video_core/regs_rasterizer.h b/src/video_core/regs_rasterizer.h new file mode 100644 index 000000000..a471a3b38 --- /dev/null +++ b/src/video_core/regs_rasterizer.h | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | |||
| 13 | namespace Pica { | ||
| 14 | |||
| 15 | struct RasterizerRegs { | ||
| 16 | enum class CullMode : u32 { | ||
| 17 | // Select which polygons are considered to be "frontfacing". | ||
| 18 | KeepAll = 0, | ||
| 19 | KeepClockWise = 1, | ||
| 20 | KeepCounterClockWise = 2, | ||
| 21 | // TODO: What does the third value imply? | ||
| 22 | }; | ||
| 23 | |||
| 24 | union { | ||
| 25 | BitField<0, 2, CullMode> cull_mode; | ||
| 26 | }; | ||
| 27 | |||
| 28 | BitField<0, 24, u32> viewport_size_x; | ||
| 29 | |||
| 30 | INSERT_PADDING_WORDS(0x1); | ||
| 31 | |||
| 32 | BitField<0, 24, u32> viewport_size_y; | ||
| 33 | |||
| 34 | INSERT_PADDING_WORDS(0x9); | ||
| 35 | |||
| 36 | BitField<0, 24, u32> viewport_depth_range; // float24 | ||
| 37 | BitField<0, 24, u32> viewport_depth_near_plane; // float24 | ||
| 38 | |||
| 39 | BitField<0, 3, u32> vs_output_total; | ||
| 40 | |||
| 41 | union VSOutputAttributes { | ||
| 42 | // Maps components of output vertex attributes to semantics | ||
| 43 | enum Semantic : u32 { | ||
| 44 | POSITION_X = 0, | ||
| 45 | POSITION_Y = 1, | ||
| 46 | POSITION_Z = 2, | ||
| 47 | POSITION_W = 3, | ||
| 48 | |||
| 49 | QUATERNION_X = 4, | ||
| 50 | QUATERNION_Y = 5, | ||
| 51 | QUATERNION_Z = 6, | ||
| 52 | QUATERNION_W = 7, | ||
| 53 | |||
| 54 | COLOR_R = 8, | ||
| 55 | COLOR_G = 9, | ||
| 56 | COLOR_B = 10, | ||
| 57 | COLOR_A = 11, | ||
| 58 | |||
| 59 | TEXCOORD0_U = 12, | ||
| 60 | TEXCOORD0_V = 13, | ||
| 61 | TEXCOORD1_U = 14, | ||
| 62 | TEXCOORD1_V = 15, | ||
| 63 | |||
| 64 | TEXCOORD0_W = 16, | ||
| 65 | |||
| 66 | VIEW_X = 18, | ||
| 67 | VIEW_Y = 19, | ||
| 68 | VIEW_Z = 20, | ||
| 69 | |||
| 70 | TEXCOORD2_U = 22, | ||
| 71 | TEXCOORD2_V = 23, | ||
| 72 | |||
| 73 | INVALID = 31, | ||
| 74 | }; | ||
| 75 | |||
| 76 | BitField<0, 5, Semantic> map_x; | ||
| 77 | BitField<8, 5, Semantic> map_y; | ||
| 78 | BitField<16, 5, Semantic> map_z; | ||
| 79 | BitField<24, 5, Semantic> map_w; | ||
| 80 | } vs_output_attributes[7]; | ||
| 81 | |||
| 82 | INSERT_PADDING_WORDS(0xe); | ||
| 83 | |||
| 84 | enum class ScissorMode : u32 { | ||
| 85 | Disabled = 0, | ||
| 86 | Exclude = 1, // Exclude pixels inside the scissor box | ||
| 87 | |||
| 88 | Include = 3 // Exclude pixels outside the scissor box | ||
| 89 | }; | ||
| 90 | |||
| 91 | struct { | ||
| 92 | BitField<0, 2, ScissorMode> mode; | ||
| 93 | |||
| 94 | union { | ||
| 95 | BitField<0, 16, u32> x1; | ||
| 96 | BitField<16, 16, u32> y1; | ||
| 97 | }; | ||
| 98 | |||
| 99 | union { | ||
| 100 | BitField<0, 16, u32> x2; | ||
| 101 | BitField<16, 16, u32> y2; | ||
| 102 | }; | ||
| 103 | } scissor_test; | ||
| 104 | |||
| 105 | union { | ||
| 106 | BitField<0, 10, s32> x; | ||
| 107 | BitField<16, 10, s32> y; | ||
| 108 | } viewport_corner; | ||
| 109 | |||
| 110 | INSERT_PADDING_WORDS(0x1); | ||
| 111 | |||
| 112 | // TODO: early depth | ||
| 113 | INSERT_PADDING_WORDS(0x1); | ||
| 114 | |||
| 115 | INSERT_PADDING_WORDS(0x2); | ||
| 116 | |||
| 117 | enum DepthBuffering : u32 { | ||
| 118 | WBuffering = 0, | ||
| 119 | ZBuffering = 1, | ||
| 120 | }; | ||
| 121 | BitField<0, 1, DepthBuffering> depthmap_enable; | ||
| 122 | |||
| 123 | INSERT_PADDING_WORDS(0x12); | ||
| 124 | }; | ||
| 125 | |||
| 126 | static_assert(sizeof(RasterizerRegs) == 0x40 * sizeof(u32), | ||
| 127 | "RasterizerRegs struct has incorrect size"); | ||
| 128 | |||
| 129 | } // namespace Pica | ||
diff --git a/src/video_core/regs_shader.h b/src/video_core/regs_shader.h new file mode 100644 index 000000000..ddb1ee451 --- /dev/null +++ b/src/video_core/regs_shader.h | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | |||
| 13 | namespace Pica { | ||
| 14 | |||
| 15 | struct ShaderRegs { | ||
| 16 | BitField<0, 16, u32> bool_uniforms; | ||
| 17 | |||
| 18 | union { | ||
| 19 | BitField<0, 8, u32> x; | ||
| 20 | BitField<8, 8, u32> y; | ||
| 21 | BitField<16, 8, u32> z; | ||
| 22 | BitField<24, 8, u32> w; | ||
| 23 | } int_uniforms[4]; | ||
| 24 | |||
| 25 | INSERT_PADDING_WORDS(0x4); | ||
| 26 | |||
| 27 | union { | ||
| 28 | // Number of input attributes to shader unit - 1 | ||
| 29 | BitField<0, 4, u32> max_input_attribute_index; | ||
| 30 | }; | ||
| 31 | |||
| 32 | // Offset to shader program entry point (in words) | ||
| 33 | BitField<0, 16, u32> main_offset; | ||
| 34 | |||
| 35 | /// Maps input attributes to registers. 4-bits per attribute, specifying a register index | ||
| 36 | u32 input_attribute_to_register_map_low; | ||
| 37 | u32 input_attribute_to_register_map_high; | ||
| 38 | |||
| 39 | unsigned int GetRegisterForAttribute(unsigned int attribute_index) const { | ||
| 40 | u64 map = ((u64)input_attribute_to_register_map_high << 32) | | ||
| 41 | (u64)input_attribute_to_register_map_low; | ||
| 42 | return (map >> (attribute_index * 4)) & 0b1111; | ||
| 43 | } | ||
| 44 | |||
| 45 | BitField<0, 16, u32> output_mask; | ||
| 46 | |||
| 47 | // 0x28E, CODETRANSFER_END | ||
| 48 | INSERT_PADDING_WORDS(0x2); | ||
| 49 | |||
| 50 | struct { | ||
| 51 | enum Format : u32 { | ||
| 52 | FLOAT24 = 0, | ||
| 53 | FLOAT32 = 1, | ||
| 54 | }; | ||
| 55 | |||
| 56 | bool IsFloat32() const { | ||
| 57 | return format == FLOAT32; | ||
| 58 | } | ||
| 59 | |||
| 60 | union { | ||
| 61 | // Index of the next uniform to write to | ||
| 62 | // TODO: ctrulib uses 8 bits for this, however that seems to yield lots of invalid | ||
| 63 | // indices | ||
| 64 | // TODO: Maybe the uppermost index is for the geometry shader? Investigate! | ||
| 65 | BitField<0, 7, u32> index; | ||
| 66 | |||
| 67 | BitField<31, 1, Format> format; | ||
| 68 | }; | ||
| 69 | |||
| 70 | // Writing to these registers sets the current uniform. | ||
| 71 | u32 set_value[8]; | ||
| 72 | |||
| 73 | } uniform_setup; | ||
| 74 | |||
| 75 | INSERT_PADDING_WORDS(0x2); | ||
| 76 | |||
| 77 | struct { | ||
| 78 | // Offset of the next instruction to write code to. | ||
| 79 | // Incremented with each instruction write. | ||
| 80 | u32 offset; | ||
| 81 | |||
| 82 | // Writing to these registers sets the "current" word in the shader program. | ||
| 83 | u32 set_word[8]; | ||
| 84 | } program; | ||
| 85 | |||
| 86 | INSERT_PADDING_WORDS(0x1); | ||
| 87 | |||
| 88 | // This register group is used to load an internal table of swizzling patterns, | ||
| 89 | // which are indexed by each shader instruction to specify vector component swizzling. | ||
| 90 | struct { | ||
| 91 | // Offset of the next swizzle pattern to write code to. | ||
| 92 | // Incremented with each instruction write. | ||
| 93 | u32 offset; | ||
| 94 | |||
| 95 | // Writing to these registers sets the current swizzle pattern in the table. | ||
| 96 | u32 set_word[8]; | ||
| 97 | } swizzle_patterns; | ||
| 98 | |||
| 99 | INSERT_PADDING_WORDS(0x2); | ||
| 100 | }; | ||
| 101 | |||
| 102 | static_assert(sizeof(ShaderRegs) == 0x30 * sizeof(u32), "ShaderRegs struct has incorrect size"); | ||
| 103 | |||
| 104 | } // namespace Pica | ||
diff --git a/src/video_core/regs_texturing.h b/src/video_core/regs_texturing.h new file mode 100644 index 000000000..be8bc6826 --- /dev/null +++ b/src/video_core/regs_texturing.h | |||
| @@ -0,0 +1,328 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_funcs.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | |||
| 14 | namespace Pica { | ||
| 15 | |||
| 16 | struct TexturingRegs { | ||
| 17 | struct TextureConfig { | ||
| 18 | enum TextureType : u32 { | ||
| 19 | Texture2D = 0, | ||
| 20 | TextureCube = 1, | ||
| 21 | Shadow2D = 2, | ||
| 22 | Projection2D = 3, | ||
| 23 | ShadowCube = 4, | ||
| 24 | Disabled = 5, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum WrapMode : u32 { | ||
| 28 | ClampToEdge = 0, | ||
| 29 | ClampToBorder = 1, | ||
| 30 | Repeat = 2, | ||
| 31 | MirroredRepeat = 3, | ||
| 32 | }; | ||
| 33 | |||
| 34 | enum TextureFilter : u32 { | ||
| 35 | Nearest = 0, | ||
| 36 | Linear = 1, | ||
| 37 | }; | ||
| 38 | |||
| 39 | union { | ||
| 40 | u32 raw; | ||
| 41 | BitField<0, 8, u32> r; | ||
| 42 | BitField<8, 8, u32> g; | ||
| 43 | BitField<16, 8, u32> b; | ||
| 44 | BitField<24, 8, u32> a; | ||
| 45 | } border_color; | ||
| 46 | |||
| 47 | union { | ||
| 48 | BitField<0, 16, u32> height; | ||
| 49 | BitField<16, 16, u32> width; | ||
| 50 | }; | ||
| 51 | |||
| 52 | union { | ||
| 53 | BitField<1, 1, TextureFilter> mag_filter; | ||
| 54 | BitField<2, 1, TextureFilter> min_filter; | ||
| 55 | BitField<8, 2, WrapMode> wrap_t; | ||
| 56 | BitField<12, 2, WrapMode> wrap_s; | ||
| 57 | BitField<28, 2, TextureType> | ||
| 58 | type; ///< @note Only valid for texture 0 according to 3DBrew. | ||
| 59 | }; | ||
| 60 | |||
| 61 | INSERT_PADDING_WORDS(0x1); | ||
| 62 | |||
| 63 | u32 address; | ||
| 64 | |||
| 65 | PAddr GetPhysicalAddress() const { | ||
| 66 | return address * 8; | ||
| 67 | } | ||
| 68 | |||
| 69 | // texture1 and texture2 store the texture format directly after the address | ||
| 70 | // whereas texture0 inserts some additional flags inbetween. | ||
| 71 | // Hence, we store the format separately so that all other parameters can be described | ||
| 72 | // in a single structure. | ||
| 73 | }; | ||
| 74 | |||
| 75 | enum class TextureFormat : u32 { | ||
| 76 | RGBA8 = 0, | ||
| 77 | RGB8 = 1, | ||
| 78 | RGB5A1 = 2, | ||
| 79 | RGB565 = 3, | ||
| 80 | RGBA4 = 4, | ||
| 81 | IA8 = 5, | ||
| 82 | RG8 = 6, ///< @note Also called HILO8 in 3DBrew. | ||
| 83 | I8 = 7, | ||
| 84 | A8 = 8, | ||
| 85 | IA4 = 9, | ||
| 86 | I4 = 10, | ||
| 87 | A4 = 11, | ||
| 88 | ETC1 = 12, // compressed | ||
| 89 | ETC1A4 = 13, // compressed | ||
| 90 | }; | ||
| 91 | |||
| 92 | static unsigned NibblesPerPixel(TextureFormat format) { | ||
| 93 | switch (format) { | ||
| 94 | case TextureFormat::RGBA8: | ||
| 95 | return 8; | ||
| 96 | |||
| 97 | case TextureFormat::RGB8: | ||
| 98 | return 6; | ||
| 99 | |||
| 100 | case TextureFormat::RGB5A1: | ||
| 101 | case TextureFormat::RGB565: | ||
| 102 | case TextureFormat::RGBA4: | ||
| 103 | case TextureFormat::IA8: | ||
| 104 | case TextureFormat::RG8: | ||
| 105 | return 4; | ||
| 106 | |||
| 107 | case TextureFormat::I4: | ||
| 108 | case TextureFormat::A4: | ||
| 109 | return 1; | ||
| 110 | |||
| 111 | case TextureFormat::I8: | ||
| 112 | case TextureFormat::A8: | ||
| 113 | case TextureFormat::IA4: | ||
| 114 | |||
| 115 | default: // placeholder for yet unknown formats | ||
| 116 | UNIMPLEMENTED(); | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | union { | ||
| 122 | BitField<0, 1, u32> texture0_enable; | ||
| 123 | BitField<1, 1, u32> texture1_enable; | ||
| 124 | BitField<2, 1, u32> texture2_enable; | ||
| 125 | }; | ||
| 126 | TextureConfig texture0; | ||
| 127 | INSERT_PADDING_WORDS(0x8); | ||
| 128 | BitField<0, 4, TextureFormat> texture0_format; | ||
| 129 | BitField<0, 1, u32> fragment_lighting_enable; | ||
| 130 | INSERT_PADDING_WORDS(0x1); | ||
| 131 | TextureConfig texture1; | ||
| 132 | BitField<0, 4, TextureFormat> texture1_format; | ||
| 133 | INSERT_PADDING_WORDS(0x2); | ||
| 134 | TextureConfig texture2; | ||
| 135 | BitField<0, 4, TextureFormat> texture2_format; | ||
| 136 | INSERT_PADDING_WORDS(0x21); | ||
| 137 | |||
| 138 | struct FullTextureConfig { | ||
| 139 | const bool enabled; | ||
| 140 | const TextureConfig config; | ||
| 141 | const TextureFormat format; | ||
| 142 | }; | ||
| 143 | const std::array<FullTextureConfig, 3> GetTextures() const { | ||
| 144 | return {{ | ||
| 145 | {texture0_enable.ToBool(), texture0, texture0_format}, | ||
| 146 | {texture1_enable.ToBool(), texture1, texture1_format}, | ||
| 147 | {texture2_enable.ToBool(), texture2, texture2_format}, | ||
| 148 | }}; | ||
| 149 | } | ||
| 150 | |||
| 151 | // 0xc0-0xff: Texture Combiner (akin to glTexEnv) | ||
| 152 | struct TevStageConfig { | ||
| 153 | enum class Source : u32 { | ||
| 154 | PrimaryColor = 0x0, | ||
| 155 | PrimaryFragmentColor = 0x1, | ||
| 156 | SecondaryFragmentColor = 0x2, | ||
| 157 | |||
| 158 | Texture0 = 0x3, | ||
| 159 | Texture1 = 0x4, | ||
| 160 | Texture2 = 0x5, | ||
| 161 | Texture3 = 0x6, | ||
| 162 | |||
| 163 | PreviousBuffer = 0xd, | ||
| 164 | Constant = 0xe, | ||
| 165 | Previous = 0xf, | ||
| 166 | }; | ||
| 167 | |||
| 168 | enum class ColorModifier : u32 { | ||
| 169 | SourceColor = 0x0, | ||
| 170 | OneMinusSourceColor = 0x1, | ||
| 171 | SourceAlpha = 0x2, | ||
| 172 | OneMinusSourceAlpha = 0x3, | ||
| 173 | SourceRed = 0x4, | ||
| 174 | OneMinusSourceRed = 0x5, | ||
| 175 | |||
| 176 | SourceGreen = 0x8, | ||
| 177 | OneMinusSourceGreen = 0x9, | ||
| 178 | |||
| 179 | SourceBlue = 0xc, | ||
| 180 | OneMinusSourceBlue = 0xd, | ||
| 181 | }; | ||
| 182 | |||
| 183 | enum class AlphaModifier : u32 { | ||
| 184 | SourceAlpha = 0x0, | ||
| 185 | OneMinusSourceAlpha = 0x1, | ||
| 186 | SourceRed = 0x2, | ||
| 187 | OneMinusSourceRed = 0x3, | ||
| 188 | SourceGreen = 0x4, | ||
| 189 | OneMinusSourceGreen = 0x5, | ||
| 190 | SourceBlue = 0x6, | ||
| 191 | OneMinusSourceBlue = 0x7, | ||
| 192 | }; | ||
| 193 | |||
| 194 | enum class Operation : u32 { | ||
| 195 | Replace = 0, | ||
| 196 | Modulate = 1, | ||
| 197 | Add = 2, | ||
| 198 | AddSigned = 3, | ||
| 199 | Lerp = 4, | ||
| 200 | Subtract = 5, | ||
| 201 | Dot3_RGB = 6, | ||
| 202 | |||
| 203 | MultiplyThenAdd = 8, | ||
| 204 | AddThenMultiply = 9, | ||
| 205 | }; | ||
| 206 | |||
| 207 | union { | ||
| 208 | u32 sources_raw; | ||
| 209 | BitField<0, 4, Source> color_source1; | ||
| 210 | BitField<4, 4, Source> color_source2; | ||
| 211 | BitField<8, 4, Source> color_source3; | ||
| 212 | BitField<16, 4, Source> alpha_source1; | ||
| 213 | BitField<20, 4, Source> alpha_source2; | ||
| 214 | BitField<24, 4, Source> alpha_source3; | ||
| 215 | }; | ||
| 216 | |||
| 217 | union { | ||
| 218 | u32 modifiers_raw; | ||
| 219 | BitField<0, 4, ColorModifier> color_modifier1; | ||
| 220 | BitField<4, 4, ColorModifier> color_modifier2; | ||
| 221 | BitField<8, 4, ColorModifier> color_modifier3; | ||
| 222 | BitField<12, 3, AlphaModifier> alpha_modifier1; | ||
| 223 | BitField<16, 3, AlphaModifier> alpha_modifier2; | ||
| 224 | BitField<20, 3, AlphaModifier> alpha_modifier3; | ||
| 225 | }; | ||
| 226 | |||
| 227 | union { | ||
| 228 | u32 ops_raw; | ||
| 229 | BitField<0, 4, Operation> color_op; | ||
| 230 | BitField<16, 4, Operation> alpha_op; | ||
| 231 | }; | ||
| 232 | |||
| 233 | union { | ||
| 234 | u32 const_color; | ||
| 235 | BitField<0, 8, u32> const_r; | ||
| 236 | BitField<8, 8, u32> const_g; | ||
| 237 | BitField<16, 8, u32> const_b; | ||
| 238 | BitField<24, 8, u32> const_a; | ||
| 239 | }; | ||
| 240 | |||
| 241 | union { | ||
| 242 | u32 scales_raw; | ||
| 243 | BitField<0, 2, u32> color_scale; | ||
| 244 | BitField<16, 2, u32> alpha_scale; | ||
| 245 | }; | ||
| 246 | |||
| 247 | inline unsigned GetColorMultiplier() const { | ||
| 248 | return (color_scale < 3) ? (1 << color_scale) : 1; | ||
| 249 | } | ||
| 250 | |||
| 251 | inline unsigned GetAlphaMultiplier() const { | ||
| 252 | return (alpha_scale < 3) ? (1 << alpha_scale) : 1; | ||
| 253 | } | ||
| 254 | }; | ||
| 255 | |||
| 256 | TevStageConfig tev_stage0; | ||
| 257 | INSERT_PADDING_WORDS(0x3); | ||
| 258 | TevStageConfig tev_stage1; | ||
| 259 | INSERT_PADDING_WORDS(0x3); | ||
| 260 | TevStageConfig tev_stage2; | ||
| 261 | INSERT_PADDING_WORDS(0x3); | ||
| 262 | TevStageConfig tev_stage3; | ||
| 263 | INSERT_PADDING_WORDS(0x3); | ||
| 264 | |||
| 265 | enum class FogMode : u32 { | ||
| 266 | None = 0, | ||
| 267 | Fog = 5, | ||
| 268 | Gas = 7, | ||
| 269 | }; | ||
| 270 | |||
| 271 | union { | ||
| 272 | BitField<0, 3, FogMode> fog_mode; | ||
| 273 | BitField<16, 1, u32> fog_flip; | ||
| 274 | |||
| 275 | union { | ||
| 276 | // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in | ||
| 277 | // these masks are set | ||
| 278 | BitField<8, 4, u32> update_mask_rgb; | ||
| 279 | BitField<12, 4, u32> update_mask_a; | ||
| 280 | |||
| 281 | bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { | ||
| 282 | return (stage_index < 4) && (update_mask_rgb & (1 << stage_index)); | ||
| 283 | } | ||
| 284 | |||
| 285 | bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const { | ||
| 286 | return (stage_index < 4) && (update_mask_a & (1 << stage_index)); | ||
| 287 | } | ||
| 288 | } tev_combiner_buffer_input; | ||
| 289 | }; | ||
| 290 | |||
| 291 | union { | ||
| 292 | u32 raw; | ||
| 293 | BitField<0, 8, u32> r; | ||
| 294 | BitField<8, 8, u32> g; | ||
| 295 | BitField<16, 8, u32> b; | ||
| 296 | } fog_color; | ||
| 297 | |||
| 298 | INSERT_PADDING_WORDS(0x4); | ||
| 299 | |||
| 300 | BitField<0, 16, u32> fog_lut_offset; | ||
| 301 | |||
| 302 | INSERT_PADDING_WORDS(0x1); | ||
| 303 | |||
| 304 | u32 fog_lut_data[8]; | ||
| 305 | |||
| 306 | TevStageConfig tev_stage4; | ||
| 307 | INSERT_PADDING_WORDS(0x3); | ||
| 308 | TevStageConfig tev_stage5; | ||
| 309 | |||
| 310 | union { | ||
| 311 | u32 raw; | ||
| 312 | BitField<0, 8, u32> r; | ||
| 313 | BitField<8, 8, u32> g; | ||
| 314 | BitField<16, 8, u32> b; | ||
| 315 | BitField<24, 8, u32> a; | ||
| 316 | } tev_combiner_buffer_color; | ||
| 317 | |||
| 318 | INSERT_PADDING_WORDS(0x2); | ||
| 319 | |||
| 320 | const std::array<TevStageConfig, 6> GetTevStages() const { | ||
| 321 | return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}}; | ||
| 322 | }; | ||
| 323 | }; | ||
| 324 | |||
| 325 | static_assert(sizeof(TexturingRegs) == 0x80 * sizeof(u32), | ||
| 326 | "TexturingRegs struct has incorrect size"); | ||
| 327 | |||
| 328 | } // namespace Pica | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 071e4ace0..75736c99f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -14,8 +14,8 @@ | |||
| 14 | #include "common/microprofile.h" | 14 | #include "common/microprofile.h" |
| 15 | #include "common/vector_math.h" | 15 | #include "common/vector_math.h" |
| 16 | #include "core/hw/gpu.h" | 16 | #include "core/hw/gpu.h" |
| 17 | #include "video_core/pica.h" | ||
| 18 | #include "video_core/pica_state.h" | 17 | #include "video_core/pica_state.h" |
| 18 | #include "video_core/regs.h" | ||
| 19 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 19 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 20 | #include "video_core/renderer_opengl/gl_shader_gen.h" | 20 | #include "video_core/renderer_opengl/gl_shader_gen.h" |
| 21 | #include "video_core/renderer_opengl/gl_shader_util.h" | 21 | #include "video_core/renderer_opengl/gl_shader_util.h" |
| @@ -26,13 +26,15 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192)); | |||
| 26 | MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); | 26 | MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); |
| 27 | MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); | 27 | MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); |
| 28 | 28 | ||
| 29 | static bool IsPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) { | 29 | static bool IsPassThroughTevStage(const Pica::TexturingRegs::TevStageConfig& stage) { |
| 30 | return (stage.color_op == Pica::Regs::TevStageConfig::Operation::Replace && | 30 | using TevStageConfig = Pica::TexturingRegs::TevStageConfig; |
| 31 | stage.alpha_op == Pica::Regs::TevStageConfig::Operation::Replace && | 31 | |
| 32 | stage.color_source1 == Pica::Regs::TevStageConfig::Source::Previous && | 32 | return (stage.color_op == TevStageConfig::Operation::Replace && |
| 33 | stage.alpha_source1 == Pica::Regs::TevStageConfig::Source::Previous && | 33 | stage.alpha_op == TevStageConfig::Operation::Replace && |
| 34 | stage.color_modifier1 == Pica::Regs::TevStageConfig::ColorModifier::SourceColor && | 34 | stage.color_source1 == TevStageConfig::Source::Previous && |
| 35 | stage.alpha_modifier1 == Pica::Regs::TevStageConfig::AlphaModifier::SourceAlpha && | 35 | stage.alpha_source1 == TevStageConfig::Source::Previous && |
| 36 | stage.color_modifier1 == TevStageConfig::ColorModifier::SourceColor && | ||
| 37 | stage.alpha_modifier1 == TevStageConfig::AlphaModifier::SourceAlpha && | ||
| 36 | stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1); | 38 | stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1); |
| 37 | } | 39 | } |
| 38 | 40 | ||
| @@ -181,7 +183,7 @@ void RasterizerOpenGL::DrawTriangles() { | |||
| 181 | CachedSurface* depth_surface; | 183 | CachedSurface* depth_surface; |
| 182 | MathUtil::Rectangle<int> rect; | 184 | MathUtil::Rectangle<int> rect; |
| 183 | std::tie(color_surface, depth_surface, rect) = | 185 | std::tie(color_surface, depth_surface, rect) = |
| 184 | res_cache.GetFramebufferSurfaces(regs.framebuffer); | 186 | res_cache.GetFramebufferSurfaces(regs.framebuffer.framebuffer); |
| 185 | 187 | ||
| 186 | state.draw.draw_framebuffer = framebuffer.handle; | 188 | state.draw.draw_framebuffer = framebuffer.handle; |
| 187 | state.Apply(); | 189 | state.Apply(); |
| @@ -190,20 +192,24 @@ void RasterizerOpenGL::DrawTriangles() { | |||
| 190 | color_surface != nullptr ? color_surface->texture.handle : 0, 0); | 192 | color_surface != nullptr ? color_surface->texture.handle : 0, 0); |
| 191 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, | 193 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, |
| 192 | depth_surface != nullptr ? depth_surface->texture.handle : 0, 0); | 194 | depth_surface != nullptr ? depth_surface->texture.handle : 0, 0); |
| 193 | bool has_stencil = regs.framebuffer.depth_format == Pica::Regs::DepthFormat::D24S8; | 195 | bool has_stencil = |
| 196 | regs.framebuffer.framebuffer.depth_format == Pica::FramebufferRegs::DepthFormat::D24S8; | ||
| 194 | glFramebufferTexture2D( | 197 | glFramebufferTexture2D( |
| 195 | GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | 198 | GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, |
| 196 | (has_stencil && depth_surface != nullptr) ? depth_surface->texture.handle : 0, 0); | 199 | (has_stencil && depth_surface != nullptr) ? depth_surface->texture.handle : 0, 0); |
| 197 | 200 | ||
| 198 | // Sync the viewport | 201 | // Sync the viewport |
| 199 | // These registers hold half-width and half-height, so must be multiplied by 2 | 202 | // These registers hold half-width and half-height, so must be multiplied by 2 |
| 200 | GLsizei viewport_width = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_x).ToFloat32() * 2; | 203 | GLsizei viewport_width = |
| 201 | GLsizei viewport_height = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_y).ToFloat32() * 2; | 204 | (GLsizei)Pica::float24::FromRaw(regs.rasterizer.viewport_size_x).ToFloat32() * 2; |
| 205 | GLsizei viewport_height = | ||
| 206 | (GLsizei)Pica::float24::FromRaw(regs.rasterizer.viewport_size_y).ToFloat32() * 2; | ||
| 202 | 207 | ||
| 203 | glViewport((GLint)(rect.left + regs.viewport_corner.x * color_surface->res_scale_width), | 208 | glViewport( |
| 204 | (GLint)(rect.bottom + regs.viewport_corner.y * color_surface->res_scale_height), | 209 | (GLint)(rect.left + regs.rasterizer.viewport_corner.x * color_surface->res_scale_width), |
| 205 | (GLsizei)(viewport_width * color_surface->res_scale_width), | 210 | (GLint)(rect.bottom + regs.rasterizer.viewport_corner.y * color_surface->res_scale_height), |
| 206 | (GLsizei)(viewport_height * color_surface->res_scale_height)); | 211 | (GLsizei)(viewport_width * color_surface->res_scale_width), |
| 212 | (GLsizei)(viewport_height * color_surface->res_scale_height)); | ||
| 207 | 213 | ||
| 208 | if (uniform_block_data.data.framebuffer_scale[0] != color_surface->res_scale_width || | 214 | if (uniform_block_data.data.framebuffer_scale[0] != color_surface->res_scale_width || |
| 209 | uniform_block_data.data.framebuffer_scale[1] != color_surface->res_scale_height) { | 215 | uniform_block_data.data.framebuffer_scale[1] != color_surface->res_scale_height) { |
| @@ -215,16 +221,16 @@ void RasterizerOpenGL::DrawTriangles() { | |||
| 215 | 221 | ||
| 216 | // Scissor checks are window-, not viewport-relative, which means that if the cached texture | 222 | // Scissor checks are window-, not viewport-relative, which means that if the cached texture |
| 217 | // sub-rect changes, the scissor bounds also need to be updated. | 223 | // sub-rect changes, the scissor bounds also need to be updated. |
| 218 | GLint scissor_x1 = | 224 | GLint scissor_x1 = static_cast<GLint>( |
| 219 | static_cast<GLint>(rect.left + regs.scissor_test.x1 * color_surface->res_scale_width); | 225 | rect.left + regs.rasterizer.scissor_test.x1 * color_surface->res_scale_width); |
| 220 | GLint scissor_y1 = | 226 | GLint scissor_y1 = static_cast<GLint>( |
| 221 | static_cast<GLint>(rect.bottom + regs.scissor_test.y1 * color_surface->res_scale_height); | 227 | rect.bottom + regs.rasterizer.scissor_test.y1 * color_surface->res_scale_height); |
| 222 | // x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when | 228 | // x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when |
| 223 | // scaling or doing multisampling. | 229 | // scaling or doing multisampling. |
| 224 | GLint scissor_x2 = | 230 | GLint scissor_x2 = static_cast<GLint>( |
| 225 | static_cast<GLint>(rect.left + (regs.scissor_test.x2 + 1) * color_surface->res_scale_width); | 231 | rect.left + (regs.rasterizer.scissor_test.x2 + 1) * color_surface->res_scale_width); |
| 226 | GLint scissor_y2 = static_cast<GLint>( | 232 | GLint scissor_y2 = static_cast<GLint>( |
| 227 | rect.bottom + (regs.scissor_test.y2 + 1) * color_surface->res_scale_height); | 233 | rect.bottom + (regs.rasterizer.scissor_test.y2 + 1) * color_surface->res_scale_height); |
| 228 | 234 | ||
| 229 | if (uniform_block_data.data.scissor_x1 != scissor_x1 || | 235 | if (uniform_block_data.data.scissor_x1 != scissor_x1 || |
| 230 | uniform_block_data.data.scissor_x2 != scissor_x2 || | 236 | uniform_block_data.data.scissor_x2 != scissor_x2 || |
| @@ -239,7 +245,7 @@ void RasterizerOpenGL::DrawTriangles() { | |||
| 239 | } | 245 | } |
| 240 | 246 | ||
| 241 | // Sync and bind the texture surfaces | 247 | // Sync and bind the texture surfaces |
| 242 | const auto pica_textures = regs.GetTextures(); | 248 | const auto pica_textures = regs.texturing.GetTextures(); |
| 243 | for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) { | 249 | for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) { |
| 244 | const auto& texture = pica_textures[texture_index]; | 250 | const auto& texture = pica_textures[texture_index]; |
| 245 | 251 | ||
| @@ -316,69 +322,69 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | |||
| 316 | 322 | ||
| 317 | switch (id) { | 323 | switch (id) { |
| 318 | // Culling | 324 | // Culling |
| 319 | case PICA_REG_INDEX(cull_mode): | 325 | case PICA_REG_INDEX(rasterizer.cull_mode): |
| 320 | SyncCullMode(); | 326 | SyncCullMode(); |
| 321 | break; | 327 | break; |
| 322 | 328 | ||
| 323 | // Depth modifiers | 329 | // Depth modifiers |
| 324 | case PICA_REG_INDEX(viewport_depth_range): | 330 | case PICA_REG_INDEX(rasterizer.viewport_depth_range): |
| 325 | SyncDepthScale(); | 331 | SyncDepthScale(); |
| 326 | break; | 332 | break; |
| 327 | case PICA_REG_INDEX(viewport_depth_near_plane): | 333 | case PICA_REG_INDEX(rasterizer.viewport_depth_near_plane): |
| 328 | SyncDepthOffset(); | 334 | SyncDepthOffset(); |
| 329 | break; | 335 | break; |
| 330 | 336 | ||
| 331 | // Depth buffering | 337 | // Depth buffering |
| 332 | case PICA_REG_INDEX(depthmap_enable): | 338 | case PICA_REG_INDEX(rasterizer.depthmap_enable): |
| 333 | shader_dirty = true; | 339 | shader_dirty = true; |
| 334 | break; | 340 | break; |
| 335 | 341 | ||
| 336 | // Blending | 342 | // Blending |
| 337 | case PICA_REG_INDEX(output_merger.alphablend_enable): | 343 | case PICA_REG_INDEX(framebuffer.output_merger.alphablend_enable): |
| 338 | SyncBlendEnabled(); | 344 | SyncBlendEnabled(); |
| 339 | break; | 345 | break; |
| 340 | case PICA_REG_INDEX(output_merger.alpha_blending): | 346 | case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending): |
| 341 | SyncBlendFuncs(); | 347 | SyncBlendFuncs(); |
| 342 | break; | 348 | break; |
| 343 | case PICA_REG_INDEX(output_merger.blend_const): | 349 | case PICA_REG_INDEX(framebuffer.output_merger.blend_const): |
| 344 | SyncBlendColor(); | 350 | SyncBlendColor(); |
| 345 | break; | 351 | break; |
| 346 | 352 | ||
| 347 | // Fog state | 353 | // Fog state |
| 348 | case PICA_REG_INDEX(fog_color): | 354 | case PICA_REG_INDEX(texturing.fog_color): |
| 349 | SyncFogColor(); | 355 | SyncFogColor(); |
| 350 | break; | 356 | break; |
| 351 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8): | 357 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8): |
| 352 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9): | 358 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9): |
| 353 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea): | 359 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea): |
| 354 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb): | 360 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb): |
| 355 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec): | 361 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec): |
| 356 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed): | 362 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed): |
| 357 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee): | 363 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee): |
| 358 | case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef): | 364 | case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef): |
| 359 | uniform_block_data.fog_lut_dirty = true; | 365 | uniform_block_data.fog_lut_dirty = true; |
| 360 | break; | 366 | break; |
| 361 | 367 | ||
| 362 | // Alpha test | 368 | // Alpha test |
| 363 | case PICA_REG_INDEX(output_merger.alpha_test): | 369 | case PICA_REG_INDEX(framebuffer.output_merger.alpha_test): |
| 364 | SyncAlphaTest(); | 370 | SyncAlphaTest(); |
| 365 | shader_dirty = true; | 371 | shader_dirty = true; |
| 366 | break; | 372 | break; |
| 367 | 373 | ||
| 368 | // Sync GL stencil test + stencil write mask | 374 | // Sync GL stencil test + stencil write mask |
| 369 | // (Pica stencil test function register also contains a stencil write mask) | 375 | // (Pica stencil test function register also contains a stencil write mask) |
| 370 | case PICA_REG_INDEX(output_merger.stencil_test.raw_func): | 376 | case PICA_REG_INDEX(framebuffer.output_merger.stencil_test.raw_func): |
| 371 | SyncStencilTest(); | 377 | SyncStencilTest(); |
| 372 | SyncStencilWriteMask(); | 378 | SyncStencilWriteMask(); |
| 373 | break; | 379 | break; |
| 374 | case PICA_REG_INDEX(output_merger.stencil_test.raw_op): | 380 | case PICA_REG_INDEX(framebuffer.output_merger.stencil_test.raw_op): |
| 375 | case PICA_REG_INDEX(framebuffer.depth_format): | 381 | case PICA_REG_INDEX(framebuffer.framebuffer.depth_format): |
| 376 | SyncStencilTest(); | 382 | SyncStencilTest(); |
| 377 | break; | 383 | break; |
| 378 | 384 | ||
| 379 | // Sync GL depth test + depth and color write mask | 385 | // Sync GL depth test + depth and color write mask |
| 380 | // (Pica depth test function register also contains a depth and color write mask) | 386 | // (Pica depth test function register also contains a depth and color write mask) |
| 381 | case PICA_REG_INDEX(output_merger.depth_test_enable): | 387 | case PICA_REG_INDEX(framebuffer.output_merger.depth_test_enable): |
| 382 | SyncDepthTest(); | 388 | SyncDepthTest(); |
| 383 | SyncDepthWriteMask(); | 389 | SyncDepthWriteMask(); |
| 384 | SyncColorWriteMask(); | 390 | SyncColorWriteMask(); |
| @@ -386,82 +392,82 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | |||
| 386 | 392 | ||
| 387 | // Sync GL depth and stencil write mask | 393 | // Sync GL depth and stencil write mask |
| 388 | // (This is a dedicated combined depth / stencil write-enable register) | 394 | // (This is a dedicated combined depth / stencil write-enable register) |
| 389 | case PICA_REG_INDEX(framebuffer.allow_depth_stencil_write): | 395 | case PICA_REG_INDEX(framebuffer.framebuffer.allow_depth_stencil_write): |
| 390 | SyncDepthWriteMask(); | 396 | SyncDepthWriteMask(); |
| 391 | SyncStencilWriteMask(); | 397 | SyncStencilWriteMask(); |
| 392 | break; | 398 | break; |
| 393 | 399 | ||
| 394 | // Sync GL color write mask | 400 | // Sync GL color write mask |
| 395 | // (This is a dedicated color write-enable register) | 401 | // (This is a dedicated color write-enable register) |
| 396 | case PICA_REG_INDEX(framebuffer.allow_color_write): | 402 | case PICA_REG_INDEX(framebuffer.framebuffer.allow_color_write): |
| 397 | SyncColorWriteMask(); | 403 | SyncColorWriteMask(); |
| 398 | break; | 404 | break; |
| 399 | 405 | ||
| 400 | // Scissor test | 406 | // Scissor test |
| 401 | case PICA_REG_INDEX(scissor_test.mode): | 407 | case PICA_REG_INDEX(rasterizer.scissor_test.mode): |
| 402 | shader_dirty = true; | 408 | shader_dirty = true; |
| 403 | break; | 409 | break; |
| 404 | 410 | ||
| 405 | // Logic op | 411 | // Logic op |
| 406 | case PICA_REG_INDEX(output_merger.logic_op): | 412 | case PICA_REG_INDEX(framebuffer.output_merger.logic_op): |
| 407 | SyncLogicOp(); | 413 | SyncLogicOp(); |
| 408 | break; | 414 | break; |
| 409 | 415 | ||
| 410 | // Texture 0 type | 416 | // Texture 0 type |
| 411 | case PICA_REG_INDEX(texture0.type): | 417 | case PICA_REG_INDEX(texturing.texture0.type): |
| 412 | shader_dirty = true; | 418 | shader_dirty = true; |
| 413 | break; | 419 | break; |
| 414 | 420 | ||
| 415 | // TEV stages | 421 | // TEV stages |
| 416 | // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input) | 422 | // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input) |
| 417 | case PICA_REG_INDEX(tev_stage0.color_source1): | 423 | case PICA_REG_INDEX(texturing.tev_stage0.color_source1): |
| 418 | case PICA_REG_INDEX(tev_stage0.color_modifier1): | 424 | case PICA_REG_INDEX(texturing.tev_stage0.color_modifier1): |
| 419 | case PICA_REG_INDEX(tev_stage0.color_op): | 425 | case PICA_REG_INDEX(texturing.tev_stage0.color_op): |
| 420 | case PICA_REG_INDEX(tev_stage0.color_scale): | 426 | case PICA_REG_INDEX(texturing.tev_stage0.color_scale): |
| 421 | case PICA_REG_INDEX(tev_stage1.color_source1): | 427 | case PICA_REG_INDEX(texturing.tev_stage1.color_source1): |
| 422 | case PICA_REG_INDEX(tev_stage1.color_modifier1): | 428 | case PICA_REG_INDEX(texturing.tev_stage1.color_modifier1): |
| 423 | case PICA_REG_INDEX(tev_stage1.color_op): | 429 | case PICA_REG_INDEX(texturing.tev_stage1.color_op): |
| 424 | case PICA_REG_INDEX(tev_stage1.color_scale): | 430 | case PICA_REG_INDEX(texturing.tev_stage1.color_scale): |
| 425 | case PICA_REG_INDEX(tev_stage2.color_source1): | 431 | case PICA_REG_INDEX(texturing.tev_stage2.color_source1): |
| 426 | case PICA_REG_INDEX(tev_stage2.color_modifier1): | 432 | case PICA_REG_INDEX(texturing.tev_stage2.color_modifier1): |
| 427 | case PICA_REG_INDEX(tev_stage2.color_op): | 433 | case PICA_REG_INDEX(texturing.tev_stage2.color_op): |
| 428 | case PICA_REG_INDEX(tev_stage2.color_scale): | 434 | case PICA_REG_INDEX(texturing.tev_stage2.color_scale): |
| 429 | case PICA_REG_INDEX(tev_stage3.color_source1): | 435 | case PICA_REG_INDEX(texturing.tev_stage3.color_source1): |
| 430 | case PICA_REG_INDEX(tev_stage3.color_modifier1): | 436 | case PICA_REG_INDEX(texturing.tev_stage3.color_modifier1): |
| 431 | case PICA_REG_INDEX(tev_stage3.color_op): | 437 | case PICA_REG_INDEX(texturing.tev_stage3.color_op): |
| 432 | case PICA_REG_INDEX(tev_stage3.color_scale): | 438 | case PICA_REG_INDEX(texturing.tev_stage3.color_scale): |
| 433 | case PICA_REG_INDEX(tev_stage4.color_source1): | 439 | case PICA_REG_INDEX(texturing.tev_stage4.color_source1): |
| 434 | case PICA_REG_INDEX(tev_stage4.color_modifier1): | 440 | case PICA_REG_INDEX(texturing.tev_stage4.color_modifier1): |
| 435 | case PICA_REG_INDEX(tev_stage4.color_op): | 441 | case PICA_REG_INDEX(texturing.tev_stage4.color_op): |
| 436 | case PICA_REG_INDEX(tev_stage4.color_scale): | 442 | case PICA_REG_INDEX(texturing.tev_stage4.color_scale): |
| 437 | case PICA_REG_INDEX(tev_stage5.color_source1): | 443 | case PICA_REG_INDEX(texturing.tev_stage5.color_source1): |
| 438 | case PICA_REG_INDEX(tev_stage5.color_modifier1): | 444 | case PICA_REG_INDEX(texturing.tev_stage5.color_modifier1): |
| 439 | case PICA_REG_INDEX(tev_stage5.color_op): | 445 | case PICA_REG_INDEX(texturing.tev_stage5.color_op): |
| 440 | case PICA_REG_INDEX(tev_stage5.color_scale): | 446 | case PICA_REG_INDEX(texturing.tev_stage5.color_scale): |
| 441 | case PICA_REG_INDEX(tev_combiner_buffer_input): | 447 | case PICA_REG_INDEX(texturing.tev_combiner_buffer_input): |
| 442 | shader_dirty = true; | 448 | shader_dirty = true; |
| 443 | break; | 449 | break; |
| 444 | case PICA_REG_INDEX(tev_stage0.const_r): | 450 | case PICA_REG_INDEX(texturing.tev_stage0.const_r): |
| 445 | SyncTevConstColor(0, regs.tev_stage0); | 451 | SyncTevConstColor(0, regs.texturing.tev_stage0); |
| 446 | break; | 452 | break; |
| 447 | case PICA_REG_INDEX(tev_stage1.const_r): | 453 | case PICA_REG_INDEX(texturing.tev_stage1.const_r): |
| 448 | SyncTevConstColor(1, regs.tev_stage1); | 454 | SyncTevConstColor(1, regs.texturing.tev_stage1); |
| 449 | break; | 455 | break; |
| 450 | case PICA_REG_INDEX(tev_stage2.const_r): | 456 | case PICA_REG_INDEX(texturing.tev_stage2.const_r): |
| 451 | SyncTevConstColor(2, regs.tev_stage2); | 457 | SyncTevConstColor(2, regs.texturing.tev_stage2); |
| 452 | break; | 458 | break; |
| 453 | case PICA_REG_INDEX(tev_stage3.const_r): | 459 | case PICA_REG_INDEX(texturing.tev_stage3.const_r): |
| 454 | SyncTevConstColor(3, regs.tev_stage3); | 460 | SyncTevConstColor(3, regs.texturing.tev_stage3); |
| 455 | break; | 461 | break; |
| 456 | case PICA_REG_INDEX(tev_stage4.const_r): | 462 | case PICA_REG_INDEX(texturing.tev_stage4.const_r): |
| 457 | SyncTevConstColor(4, regs.tev_stage4); | 463 | SyncTevConstColor(4, regs.texturing.tev_stage4); |
| 458 | break; | 464 | break; |
| 459 | case PICA_REG_INDEX(tev_stage5.const_r): | 465 | case PICA_REG_INDEX(texturing.tev_stage5.const_r): |
| 460 | SyncTevConstColor(5, regs.tev_stage5); | 466 | SyncTevConstColor(5, regs.texturing.tev_stage5); |
| 461 | break; | 467 | break; |
| 462 | 468 | ||
| 463 | // TEV combiner buffer color | 469 | // TEV combiner buffer color |
| 464 | case PICA_REG_INDEX(tev_combiner_buffer_color): | 470 | case PICA_REG_INDEX(texturing.tev_combiner_buffer_color): |
| 465 | SyncCombinerColor(); | 471 | SyncCombinerColor(); |
| 466 | break; | 472 | break; |
| 467 | 473 | ||
| @@ -976,7 +982,9 @@ void RasterizerOpenGL::SamplerInfo::Create() { | |||
| 976 | // Other attributes have correct defaults | 982 | // Other attributes have correct defaults |
| 977 | } | 983 | } |
| 978 | 984 | ||
| 979 | void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Pica::Regs::TextureConfig& config) { | 985 | void RasterizerOpenGL::SamplerInfo::SyncWithConfig( |
| 986 | const Pica::TexturingRegs::TextureConfig& config) { | ||
| 987 | |||
| 980 | GLuint s = sampler.handle; | 988 | GLuint s = sampler.handle; |
| 981 | 989 | ||
| 982 | if (mag_filter != config.mag_filter) { | 990 | if (mag_filter != config.mag_filter) { |
| @@ -1088,7 +1096,7 @@ void RasterizerOpenGL::SetShader() { | |||
| 1088 | SyncDepthOffset(); | 1096 | SyncDepthOffset(); |
| 1089 | SyncAlphaTest(); | 1097 | SyncAlphaTest(); |
| 1090 | SyncCombinerColor(); | 1098 | SyncCombinerColor(); |
| 1091 | auto& tev_stages = Pica::g_state.regs.GetTevStages(); | 1099 | auto& tev_stages = Pica::g_state.regs.texturing.GetTevStages(); |
| 1092 | for (int index = 0; index < tev_stages.size(); ++index) | 1100 | for (int index = 0; index < tev_stages.size(); ++index) |
| 1093 | SyncTevConstColor(index, tev_stages[index]); | 1101 | SyncTevConstColor(index, tev_stages[index]); |
| 1094 | 1102 | ||
| @@ -1110,30 +1118,31 @@ void RasterizerOpenGL::SetShader() { | |||
| 1110 | void RasterizerOpenGL::SyncCullMode() { | 1118 | void RasterizerOpenGL::SyncCullMode() { |
| 1111 | const auto& regs = Pica::g_state.regs; | 1119 | const auto& regs = Pica::g_state.regs; |
| 1112 | 1120 | ||
| 1113 | switch (regs.cull_mode) { | 1121 | switch (regs.rasterizer.cull_mode) { |
| 1114 | case Pica::Regs::CullMode::KeepAll: | 1122 | case Pica::RasterizerRegs::CullMode::KeepAll: |
| 1115 | state.cull.enabled = false; | 1123 | state.cull.enabled = false; |
| 1116 | break; | 1124 | break; |
| 1117 | 1125 | ||
| 1118 | case Pica::Regs::CullMode::KeepClockWise: | 1126 | case Pica::RasterizerRegs::CullMode::KeepClockWise: |
| 1119 | state.cull.enabled = true; | 1127 | state.cull.enabled = true; |
| 1120 | state.cull.front_face = GL_CW; | 1128 | state.cull.front_face = GL_CW; |
| 1121 | break; | 1129 | break; |
| 1122 | 1130 | ||
| 1123 | case Pica::Regs::CullMode::KeepCounterClockWise: | 1131 | case Pica::RasterizerRegs::CullMode::KeepCounterClockWise: |
| 1124 | state.cull.enabled = true; | 1132 | state.cull.enabled = true; |
| 1125 | state.cull.front_face = GL_CCW; | 1133 | state.cull.front_face = GL_CCW; |
| 1126 | break; | 1134 | break; |
| 1127 | 1135 | ||
| 1128 | default: | 1136 | default: |
| 1129 | LOG_CRITICAL(Render_OpenGL, "Unknown cull mode %d", regs.cull_mode.Value()); | 1137 | LOG_CRITICAL(Render_OpenGL, "Unknown cull mode %d", regs.rasterizer.cull_mode.Value()); |
| 1130 | UNIMPLEMENTED(); | 1138 | UNIMPLEMENTED(); |
| 1131 | break; | 1139 | break; |
| 1132 | } | 1140 | } |
| 1133 | } | 1141 | } |
| 1134 | 1142 | ||
| 1135 | void RasterizerOpenGL::SyncDepthScale() { | 1143 | void RasterizerOpenGL::SyncDepthScale() { |
| 1136 | float depth_scale = Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_range).ToFloat32(); | 1144 | float depth_scale = |
| 1145 | Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_range).ToFloat32(); | ||
| 1137 | if (depth_scale != uniform_block_data.data.depth_scale) { | 1146 | if (depth_scale != uniform_block_data.data.depth_scale) { |
| 1138 | uniform_block_data.data.depth_scale = depth_scale; | 1147 | uniform_block_data.data.depth_scale = depth_scale; |
| 1139 | uniform_block_data.dirty = true; | 1148 | uniform_block_data.dirty = true; |
| @@ -1142,7 +1151,7 @@ void RasterizerOpenGL::SyncDepthScale() { | |||
| 1142 | 1151 | ||
| 1143 | void RasterizerOpenGL::SyncDepthOffset() { | 1152 | void RasterizerOpenGL::SyncDepthOffset() { |
| 1144 | float depth_offset = | 1153 | float depth_offset = |
| 1145 | Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_near_plane).ToFloat32(); | 1154 | Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_near_plane).ToFloat32(); |
| 1146 | if (depth_offset != uniform_block_data.data.depth_offset) { | 1155 | if (depth_offset != uniform_block_data.data.depth_offset) { |
| 1147 | uniform_block_data.data.depth_offset = depth_offset; | 1156 | uniform_block_data.data.depth_offset = depth_offset; |
| 1148 | uniform_block_data.dirty = true; | 1157 | uniform_block_data.dirty = true; |
| @@ -1150,25 +1159,28 @@ void RasterizerOpenGL::SyncDepthOffset() { | |||
| 1150 | } | 1159 | } |
| 1151 | 1160 | ||
| 1152 | void RasterizerOpenGL::SyncBlendEnabled() { | 1161 | void RasterizerOpenGL::SyncBlendEnabled() { |
| 1153 | state.blend.enabled = (Pica::g_state.regs.output_merger.alphablend_enable == 1); | 1162 | state.blend.enabled = (Pica::g_state.regs.framebuffer.output_merger.alphablend_enable == 1); |
| 1154 | } | 1163 | } |
| 1155 | 1164 | ||
| 1156 | void RasterizerOpenGL::SyncBlendFuncs() { | 1165 | void RasterizerOpenGL::SyncBlendFuncs() { |
| 1157 | const auto& regs = Pica::g_state.regs; | 1166 | const auto& regs = Pica::g_state.regs; |
| 1158 | state.blend.rgb_equation = | 1167 | state.blend.rgb_equation = |
| 1159 | PicaToGL::BlendEquation(regs.output_merger.alpha_blending.blend_equation_rgb); | 1168 | PicaToGL::BlendEquation(regs.framebuffer.output_merger.alpha_blending.blend_equation_rgb); |
| 1160 | state.blend.a_equation = | 1169 | state.blend.a_equation = |
| 1161 | PicaToGL::BlendEquation(regs.output_merger.alpha_blending.blend_equation_a); | 1170 | PicaToGL::BlendEquation(regs.framebuffer.output_merger.alpha_blending.blend_equation_a); |
| 1162 | state.blend.src_rgb_func = | 1171 | state.blend.src_rgb_func = |
| 1163 | PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_rgb); | 1172 | PicaToGL::BlendFunc(regs.framebuffer.output_merger.alpha_blending.factor_source_rgb); |
| 1164 | state.blend.dst_rgb_func = | 1173 | state.blend.dst_rgb_func = |
| 1165 | PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_rgb); | 1174 | PicaToGL::BlendFunc(regs.framebuffer.output_merger.alpha_blending.factor_dest_rgb); |
| 1166 | state.blend.src_a_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_a); | 1175 | state.blend.src_a_func = |
| 1167 | state.blend.dst_a_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_a); | 1176 | PicaToGL::BlendFunc(regs.framebuffer.output_merger.alpha_blending.factor_source_a); |
| 1177 | state.blend.dst_a_func = | ||
| 1178 | PicaToGL::BlendFunc(regs.framebuffer.output_merger.alpha_blending.factor_dest_a); | ||
| 1168 | } | 1179 | } |
| 1169 | 1180 | ||
| 1170 | void RasterizerOpenGL::SyncBlendColor() { | 1181 | void RasterizerOpenGL::SyncBlendColor() { |
| 1171 | auto blend_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.output_merger.blend_const.raw); | 1182 | auto blend_color = |
| 1183 | PicaToGL::ColorRGBA8(Pica::g_state.regs.framebuffer.output_merger.blend_const.raw); | ||
| 1172 | state.blend.color.red = blend_color[0]; | 1184 | state.blend.color.red = blend_color[0]; |
| 1173 | state.blend.color.green = blend_color[1]; | 1185 | state.blend.color.green = blend_color[1]; |
| 1174 | state.blend.color.blue = blend_color[2]; | 1186 | state.blend.color.blue = blend_color[2]; |
| @@ -1178,8 +1190,8 @@ void RasterizerOpenGL::SyncBlendColor() { | |||
| 1178 | void RasterizerOpenGL::SyncFogColor() { | 1190 | void RasterizerOpenGL::SyncFogColor() { |
| 1179 | const auto& regs = Pica::g_state.regs; | 1191 | const auto& regs = Pica::g_state.regs; |
| 1180 | uniform_block_data.data.fog_color = { | 1192 | uniform_block_data.data.fog_color = { |
| 1181 | regs.fog_color.r.Value() / 255.0f, regs.fog_color.g.Value() / 255.0f, | 1193 | regs.texturing.fog_color.r.Value() / 255.0f, regs.texturing.fog_color.g.Value() / 255.0f, |
| 1182 | regs.fog_color.b.Value() / 255.0f, | 1194 | regs.texturing.fog_color.b.Value() / 255.0f, |
| 1183 | }; | 1195 | }; |
| 1184 | uniform_block_data.dirty = true; | 1196 | uniform_block_data.dirty = true; |
| 1185 | } | 1197 | } |
| @@ -1200,70 +1212,78 @@ void RasterizerOpenGL::SyncFogLUT() { | |||
| 1200 | 1212 | ||
| 1201 | void RasterizerOpenGL::SyncAlphaTest() { | 1213 | void RasterizerOpenGL::SyncAlphaTest() { |
| 1202 | const auto& regs = Pica::g_state.regs; | 1214 | const auto& regs = Pica::g_state.regs; |
| 1203 | if (regs.output_merger.alpha_test.ref != uniform_block_data.data.alphatest_ref) { | 1215 | if (regs.framebuffer.output_merger.alpha_test.ref != uniform_block_data.data.alphatest_ref) { |
| 1204 | uniform_block_data.data.alphatest_ref = regs.output_merger.alpha_test.ref; | 1216 | uniform_block_data.data.alphatest_ref = regs.framebuffer.output_merger.alpha_test.ref; |
| 1205 | uniform_block_data.dirty = true; | 1217 | uniform_block_data.dirty = true; |
| 1206 | } | 1218 | } |
| 1207 | } | 1219 | } |
| 1208 | 1220 | ||
| 1209 | void RasterizerOpenGL::SyncLogicOp() { | 1221 | void RasterizerOpenGL::SyncLogicOp() { |
| 1210 | state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.output_merger.logic_op); | 1222 | state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.framebuffer.output_merger.logic_op); |
| 1211 | } | 1223 | } |
| 1212 | 1224 | ||
| 1213 | void RasterizerOpenGL::SyncColorWriteMask() { | 1225 | void RasterizerOpenGL::SyncColorWriteMask() { |
| 1214 | const auto& regs = Pica::g_state.regs; | 1226 | const auto& regs = Pica::g_state.regs; |
| 1215 | 1227 | ||
| 1216 | auto IsColorWriteEnabled = [&](u32 value) { | 1228 | auto IsColorWriteEnabled = [&](u32 value) { |
| 1217 | return (regs.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE : GL_FALSE; | 1229 | return (regs.framebuffer.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE |
| 1230 | : GL_FALSE; | ||
| 1218 | }; | 1231 | }; |
| 1219 | 1232 | ||
| 1220 | state.color_mask.red_enabled = IsColorWriteEnabled(regs.output_merger.red_enable); | 1233 | state.color_mask.red_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.red_enable); |
| 1221 | state.color_mask.green_enabled = IsColorWriteEnabled(regs.output_merger.green_enable); | 1234 | state.color_mask.green_enabled = |
| 1222 | state.color_mask.blue_enabled = IsColorWriteEnabled(regs.output_merger.blue_enable); | 1235 | IsColorWriteEnabled(regs.framebuffer.output_merger.green_enable); |
| 1223 | state.color_mask.alpha_enabled = IsColorWriteEnabled(regs.output_merger.alpha_enable); | 1236 | state.color_mask.blue_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.blue_enable); |
| 1237 | state.color_mask.alpha_enabled = | ||
| 1238 | IsColorWriteEnabled(regs.framebuffer.output_merger.alpha_enable); | ||
| 1224 | } | 1239 | } |
| 1225 | 1240 | ||
| 1226 | void RasterizerOpenGL::SyncStencilWriteMask() { | 1241 | void RasterizerOpenGL::SyncStencilWriteMask() { |
| 1227 | const auto& regs = Pica::g_state.regs; | 1242 | const auto& regs = Pica::g_state.regs; |
| 1228 | state.stencil.write_mask = (regs.framebuffer.allow_depth_stencil_write != 0) | 1243 | state.stencil.write_mask = |
| 1229 | ? static_cast<GLuint>(regs.output_merger.stencil_test.write_mask) | 1244 | (regs.framebuffer.framebuffer.allow_depth_stencil_write != 0) |
| 1230 | : 0; | 1245 | ? static_cast<GLuint>(regs.framebuffer.output_merger.stencil_test.write_mask) |
| 1246 | : 0; | ||
| 1231 | } | 1247 | } |
| 1232 | 1248 | ||
| 1233 | void RasterizerOpenGL::SyncDepthWriteMask() { | 1249 | void RasterizerOpenGL::SyncDepthWriteMask() { |
| 1234 | const auto& regs = Pica::g_state.regs; | 1250 | const auto& regs = Pica::g_state.regs; |
| 1235 | state.depth.write_mask = | 1251 | state.depth.write_mask = (regs.framebuffer.framebuffer.allow_depth_stencil_write != 0 && |
| 1236 | (regs.framebuffer.allow_depth_stencil_write != 0 && regs.output_merger.depth_write_enable) | 1252 | regs.framebuffer.output_merger.depth_write_enable) |
| 1237 | ? GL_TRUE | 1253 | ? GL_TRUE |
| 1238 | : GL_FALSE; | 1254 | : GL_FALSE; |
| 1239 | } | 1255 | } |
| 1240 | 1256 | ||
| 1241 | void RasterizerOpenGL::SyncStencilTest() { | 1257 | void RasterizerOpenGL::SyncStencilTest() { |
| 1242 | const auto& regs = Pica::g_state.regs; | 1258 | const auto& regs = Pica::g_state.regs; |
| 1243 | state.stencil.test_enabled = regs.output_merger.stencil_test.enable && | 1259 | state.stencil.test_enabled = |
| 1244 | regs.framebuffer.depth_format == Pica::Regs::DepthFormat::D24S8; | 1260 | regs.framebuffer.output_merger.stencil_test.enable && |
| 1245 | state.stencil.test_func = PicaToGL::CompareFunc(regs.output_merger.stencil_test.func); | 1261 | regs.framebuffer.framebuffer.depth_format == Pica::FramebufferRegs::DepthFormat::D24S8; |
| 1246 | state.stencil.test_ref = regs.output_merger.stencil_test.reference_value; | 1262 | state.stencil.test_func = |
| 1247 | state.stencil.test_mask = regs.output_merger.stencil_test.input_mask; | 1263 | PicaToGL::CompareFunc(regs.framebuffer.output_merger.stencil_test.func); |
| 1264 | state.stencil.test_ref = regs.framebuffer.output_merger.stencil_test.reference_value; | ||
| 1265 | state.stencil.test_mask = regs.framebuffer.output_merger.stencil_test.input_mask; | ||
| 1248 | state.stencil.action_stencil_fail = | 1266 | state.stencil.action_stencil_fail = |
| 1249 | PicaToGL::StencilOp(regs.output_merger.stencil_test.action_stencil_fail); | 1267 | PicaToGL::StencilOp(regs.framebuffer.output_merger.stencil_test.action_stencil_fail); |
| 1250 | state.stencil.action_depth_fail = | 1268 | state.stencil.action_depth_fail = |
| 1251 | PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_fail); | 1269 | PicaToGL::StencilOp(regs.framebuffer.output_merger.stencil_test.action_depth_fail); |
| 1252 | state.stencil.action_depth_pass = | 1270 | state.stencil.action_depth_pass = |
| 1253 | PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_pass); | 1271 | PicaToGL::StencilOp(regs.framebuffer.output_merger.stencil_test.action_depth_pass); |
| 1254 | } | 1272 | } |
| 1255 | 1273 | ||
| 1256 | void RasterizerOpenGL::SyncDepthTest() { | 1274 | void RasterizerOpenGL::SyncDepthTest() { |
| 1257 | const auto& regs = Pica::g_state.regs; | 1275 | const auto& regs = Pica::g_state.regs; |
| 1258 | state.depth.test_enabled = | 1276 | state.depth.test_enabled = regs.framebuffer.output_merger.depth_test_enable == 1 || |
| 1259 | regs.output_merger.depth_test_enable == 1 || regs.output_merger.depth_write_enable == 1; | 1277 | regs.framebuffer.output_merger.depth_write_enable == 1; |
| 1260 | state.depth.test_func = regs.output_merger.depth_test_enable == 1 | 1278 | state.depth.test_func = |
| 1261 | ? PicaToGL::CompareFunc(regs.output_merger.depth_test_func) | 1279 | regs.framebuffer.output_merger.depth_test_enable == 1 |
| 1262 | : GL_ALWAYS; | 1280 | ? PicaToGL::CompareFunc(regs.framebuffer.output_merger.depth_test_func) |
| 1281 | : GL_ALWAYS; | ||
| 1263 | } | 1282 | } |
| 1264 | 1283 | ||
| 1265 | void RasterizerOpenGL::SyncCombinerColor() { | 1284 | void RasterizerOpenGL::SyncCombinerColor() { |
| 1266 | auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw); | 1285 | auto combiner_color = |
| 1286 | PicaToGL::ColorRGBA8(Pica::g_state.regs.texturing.tev_combiner_buffer_color.raw); | ||
| 1267 | if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) { | 1287 | if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) { |
| 1268 | uniform_block_data.data.tev_combiner_buffer_color = combiner_color; | 1288 | uniform_block_data.data.tev_combiner_buffer_color = combiner_color; |
| 1269 | uniform_block_data.dirty = true; | 1289 | uniform_block_data.dirty = true; |
| @@ -1271,7 +1291,7 @@ void RasterizerOpenGL::SyncCombinerColor() { | |||
| 1271 | } | 1291 | } |
| 1272 | 1292 | ||
| 1273 | void RasterizerOpenGL::SyncTevConstColor(int stage_index, | 1293 | void RasterizerOpenGL::SyncTevConstColor(int stage_index, |
| 1274 | const Pica::Regs::TevStageConfig& tev_stage) { | 1294 | const Pica::TexturingRegs::TevStageConfig& tev_stage) { |
| 1275 | auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color); | 1295 | auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color); |
| 1276 | if (const_color != uniform_block_data.data.const_color[stage_index]) { | 1296 | if (const_color != uniform_block_data.data.const_color[stage_index]) { |
| 1277 | uniform_block_data.data.const_color[stage_index] = const_color; | 1297 | uniform_block_data.data.const_color[stage_index] = const_color; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index a1aa07074..bfee911b6 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -16,10 +16,10 @@ | |||
| 16 | #include "common/hash.h" | 16 | #include "common/hash.h" |
| 17 | #include "common/vector_math.h" | 17 | #include "common/vector_math.h" |
| 18 | #include "core/hw/gpu.h" | 18 | #include "core/hw/gpu.h" |
| 19 | #include "video_core/pica.h" | ||
| 20 | #include "video_core/pica_state.h" | 19 | #include "video_core/pica_state.h" |
| 21 | #include "video_core/pica_types.h" | 20 | #include "video_core/pica_types.h" |
| 22 | #include "video_core/rasterizer_interface.h" | 21 | #include "video_core/rasterizer_interface.h" |
| 22 | #include "video_core/regs.h" | ||
| 23 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | 23 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" |
| 24 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 24 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 25 | #include "video_core/renderer_opengl/gl_state.h" | 25 | #include "video_core/renderer_opengl/gl_state.h" |
| @@ -52,20 +52,20 @@ union PicaShaderConfig { | |||
| 52 | 52 | ||
| 53 | const auto& regs = Pica::g_state.regs; | 53 | const auto& regs = Pica::g_state.regs; |
| 54 | 54 | ||
| 55 | state.scissor_test_mode = regs.scissor_test.mode; | 55 | state.scissor_test_mode = regs.rasterizer.scissor_test.mode; |
| 56 | 56 | ||
| 57 | state.depthmap_enable = regs.depthmap_enable; | 57 | state.depthmap_enable = regs.rasterizer.depthmap_enable; |
| 58 | 58 | ||
| 59 | state.alpha_test_func = regs.output_merger.alpha_test.enable | 59 | state.alpha_test_func = regs.framebuffer.output_merger.alpha_test.enable |
| 60 | ? regs.output_merger.alpha_test.func.Value() | 60 | ? regs.framebuffer.output_merger.alpha_test.func.Value() |
| 61 | : Pica::Regs::CompareFunc::Always; | 61 | : Pica::FramebufferRegs::CompareFunc::Always; |
| 62 | 62 | ||
| 63 | state.texture0_type = regs.texture0.type; | 63 | state.texture0_type = regs.texturing.texture0.type; |
| 64 | 64 | ||
| 65 | // Copy relevant tev stages fields. | 65 | // Copy relevant tev stages fields. |
| 66 | // We don't sync const_color here because of the high variance, it is a | 66 | // We don't sync const_color here because of the high variance, it is a |
| 67 | // shader uniform instead. | 67 | // shader uniform instead. |
| 68 | const auto& tev_stages = regs.GetTevStages(); | 68 | const auto& tev_stages = regs.texturing.GetTevStages(); |
| 69 | DEBUG_ASSERT(state.tev_stages.size() == tev_stages.size()); | 69 | DEBUG_ASSERT(state.tev_stages.size() == tev_stages.size()); |
| 70 | for (size_t i = 0; i < tev_stages.size(); i++) { | 70 | for (size_t i = 0; i < tev_stages.size(); i++) { |
| 71 | const auto& tev_stage = tev_stages[i]; | 71 | const auto& tev_stage = tev_stages[i]; |
| @@ -75,11 +75,12 @@ union PicaShaderConfig { | |||
| 75 | state.tev_stages[i].scales_raw = tev_stage.scales_raw; | 75 | state.tev_stages[i].scales_raw = tev_stage.scales_raw; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | state.fog_mode = regs.fog_mode; | 78 | state.fog_mode = regs.texturing.fog_mode; |
| 79 | state.fog_flip = regs.fog_flip != 0; | 79 | state.fog_flip = regs.texturing.fog_flip != 0; |
| 80 | 80 | ||
| 81 | state.combiner_buffer_input = regs.tev_combiner_buffer_input.update_mask_rgb.Value() | | 81 | state.combiner_buffer_input = |
| 82 | regs.tev_combiner_buffer_input.update_mask_a.Value() << 4; | 82 | regs.texturing.tev_combiner_buffer_input.update_mask_rgb.Value() | |
| 83 | regs.texturing.tev_combiner_buffer_input.update_mask_a.Value() << 4; | ||
| 83 | 84 | ||
| 84 | // Fragment lighting | 85 | // Fragment lighting |
| 85 | 86 | ||
| @@ -159,8 +160,8 @@ union PicaShaderConfig { | |||
| 159 | u32 modifiers_raw; | 160 | u32 modifiers_raw; |
| 160 | u32 ops_raw; | 161 | u32 ops_raw; |
| 161 | u32 scales_raw; | 162 | u32 scales_raw; |
| 162 | explicit operator Pica::Regs::TevStageConfig() const noexcept { | 163 | explicit operator Pica::TexturingRegs::TevStageConfig() const noexcept { |
| 163 | Pica::Regs::TevStageConfig stage; | 164 | Pica::TexturingRegs::TevStageConfig stage; |
| 164 | stage.sources_raw = sources_raw; | 165 | stage.sources_raw = sources_raw; |
| 165 | stage.modifiers_raw = modifiers_raw; | 166 | stage.modifiers_raw = modifiers_raw; |
| 166 | stage.ops_raw = ops_raw; | 167 | stage.ops_raw = ops_raw; |
| @@ -171,14 +172,14 @@ union PicaShaderConfig { | |||
| 171 | }; | 172 | }; |
| 172 | 173 | ||
| 173 | struct State { | 174 | struct State { |
| 174 | Pica::Regs::CompareFunc alpha_test_func; | 175 | Pica::FramebufferRegs::CompareFunc alpha_test_func; |
| 175 | Pica::Regs::ScissorMode scissor_test_mode; | 176 | Pica::RasterizerRegs::ScissorMode scissor_test_mode; |
| 176 | Pica::Regs::TextureConfig::TextureType texture0_type; | 177 | Pica::TexturingRegs::TextureConfig::TextureType texture0_type; |
| 177 | std::array<TevStageConfigRaw, 6> tev_stages; | 178 | std::array<TevStageConfigRaw, 6> tev_stages; |
| 178 | u8 combiner_buffer_input; | 179 | u8 combiner_buffer_input; |
| 179 | 180 | ||
| 180 | Pica::Regs::DepthBuffering depthmap_enable; | 181 | Pica::RasterizerRegs::DepthBuffering depthmap_enable; |
| 181 | Pica::Regs::FogMode fog_mode; | 182 | Pica::TexturingRegs::FogMode fog_mode; |
| 182 | bool fog_flip; | 183 | bool fog_flip; |
| 183 | 184 | ||
| 184 | struct { | 185 | struct { |
| @@ -191,18 +192,18 @@ union PicaShaderConfig { | |||
| 191 | 192 | ||
| 192 | bool enable; | 193 | bool enable; |
| 193 | unsigned src_num; | 194 | unsigned src_num; |
| 194 | Pica::Regs::LightingBumpMode bump_mode; | 195 | Pica::LightingRegs::LightingBumpMode bump_mode; |
| 195 | unsigned bump_selector; | 196 | unsigned bump_selector; |
| 196 | bool bump_renorm; | 197 | bool bump_renorm; |
| 197 | bool clamp_highlights; | 198 | bool clamp_highlights; |
| 198 | 199 | ||
| 199 | Pica::Regs::LightingConfig config; | 200 | Pica::LightingRegs::LightingConfig config; |
| 200 | Pica::Regs::LightingFresnelSelector fresnel_selector; | 201 | Pica::LightingRegs::LightingFresnelSelector fresnel_selector; |
| 201 | 202 | ||
| 202 | struct { | 203 | struct { |
| 203 | bool enable; | 204 | bool enable; |
| 204 | bool abs_input; | 205 | bool abs_input; |
| 205 | Pica::Regs::LightingLutInput type; | 206 | Pica::LightingRegs::LightingLutInput type; |
| 206 | float scale; | 207 | float scale; |
| 207 | } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb; | 208 | } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb; |
| 208 | } lighting; | 209 | } lighting; |
| @@ -251,7 +252,7 @@ public: | |||
| 251 | 252 | ||
| 252 | private: | 253 | private: |
| 253 | struct SamplerInfo { | 254 | struct SamplerInfo { |
| 254 | using TextureConfig = Pica::Regs::TextureConfig; | 255 | using TextureConfig = Pica::TexturingRegs::TextureConfig; |
| 255 | 256 | ||
| 256 | OGLSampler sampler; | 257 | OGLSampler sampler; |
| 257 | 258 | ||
| @@ -398,7 +399,7 @@ private: | |||
| 398 | void SyncCombinerColor(); | 399 | void SyncCombinerColor(); |
| 399 | 400 | ||
| 400 | /// Syncs the TEV constant color to match the PICA register | 401 | /// Syncs the TEV constant color to match the PICA register |
| 401 | void SyncTevConstColor(int tev_index, const Pica::Regs::TevStageConfig& tev_stage); | 402 | void SyncTevConstColor(int tev_index, const Pica::TexturingRegs::TevStageConfig& tev_stage); |
| 402 | 403 | ||
| 403 | /// Syncs the lighting global ambient color to match the PICA register | 404 | /// Syncs the lighting global ambient color to match the PICA register |
| 404 | void SyncGlobalAmbient(); | 405 | void SyncGlobalAmbient(); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 60380257a..0818a87b3 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -342,7 +342,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo | |||
| 342 | Pica::Texture::TextureInfo tex_info; | 342 | Pica::Texture::TextureInfo tex_info; |
| 343 | tex_info.width = params.width; | 343 | tex_info.width = params.width; |
| 344 | tex_info.height = params.height; | 344 | tex_info.height = params.height; |
| 345 | tex_info.format = (Pica::Regs::TextureFormat)params.pixel_format; | 345 | tex_info.format = (Pica::TexturingRegs::TextureFormat)params.pixel_format; |
| 346 | tex_info.SetDefaultStride(); | 346 | tex_info.SetDefaultStride(); |
| 347 | tex_info.physical_address = params.addr; | 347 | tex_info.physical_address = params.addr; |
| 348 | 348 | ||
| @@ -510,7 +510,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params | |||
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | CachedSurface* RasterizerCacheOpenGL::GetTextureSurface( | 512 | CachedSurface* RasterizerCacheOpenGL::GetTextureSurface( |
| 513 | const Pica::Regs::FullTextureConfig& config) { | 513 | const Pica::TexturingRegs::FullTextureConfig& config) { |
| 514 | 514 | ||
| 515 | Pica::Texture::TextureInfo info = | 515 | Pica::Texture::TextureInfo info = |
| 516 | Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format); | 516 | Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format); |
| @@ -525,7 +525,9 @@ CachedSurface* RasterizerCacheOpenGL::GetTextureSurface( | |||
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> | 527 | std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> |
| 528 | RasterizerCacheOpenGL::GetFramebufferSurfaces(const Pica::Regs::FramebufferConfig& config) { | 528 | RasterizerCacheOpenGL::GetFramebufferSurfaces( |
| 529 | const Pica::FramebufferRegs::FramebufferConfig& config) { | ||
| 530 | |||
| 529 | const auto& regs = Pica::g_state.regs; | 531 | const auto& regs = Pica::g_state.regs; |
| 530 | 532 | ||
| 531 | // Make sur that framebuffers don't overlap if both color and depth are being used | 533 | // Make sur that framebuffers don't overlap if both color and depth are being used |
| @@ -537,11 +539,12 @@ RasterizerCacheOpenGL::GetFramebufferSurfaces(const Pica::Regs::FramebufferConfi | |||
| 537 | config.GetColorBufferPhysicalAddress(), | 539 | config.GetColorBufferPhysicalAddress(), |
| 538 | fb_area * GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(config.color_format.Value())), | 540 | fb_area * GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(config.color_format.Value())), |
| 539 | config.GetDepthBufferPhysicalAddress(), | 541 | config.GetDepthBufferPhysicalAddress(), |
| 540 | fb_area * Pica::Regs::BytesPerDepthPixel(config.depth_format)); | 542 | fb_area * Pica::FramebufferRegs::BytesPerDepthPixel(config.depth_format)); |
| 541 | bool using_color_fb = config.GetColorBufferPhysicalAddress() != 0; | 543 | bool using_color_fb = config.GetColorBufferPhysicalAddress() != 0; |
| 542 | bool using_depth_fb = config.GetDepthBufferPhysicalAddress() != 0 && | 544 | bool using_depth_fb = |
| 543 | (regs.output_merger.depth_test_enable || | 545 | config.GetDepthBufferPhysicalAddress() != 0 && |
| 544 | regs.output_merger.depth_write_enable || !framebuffers_overlap); | 546 | (regs.framebuffer.output_merger.depth_test_enable || |
| 547 | regs.framebuffer.output_merger.depth_write_enable || !framebuffers_overlap); | ||
| 545 | 548 | ||
| 546 | if (framebuffers_overlap && using_color_fb && using_depth_fb) { | 549 | if (framebuffers_overlap && using_color_fb && using_depth_fb) { |
| 547 | LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; " | 550 | LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; " |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index f57fdb3cc..4072ed49e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | #include "common/common_funcs.h" | 21 | #include "common/common_funcs.h" |
| 22 | #include "common/common_types.h" | 22 | #include "common/common_types.h" |
| 23 | #include "core/hw/gpu.h" | 23 | #include "core/hw/gpu.h" |
| 24 | #include "video_core/pica.h" | 24 | #include "video_core/regs.h" |
| 25 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 25 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 26 | 26 | ||
| 27 | namespace MathUtil { | 27 | namespace MathUtil { |
| @@ -96,15 +96,15 @@ struct CachedSurface { | |||
| 96 | return bpp_table[(unsigned int)format]; | 96 | return bpp_table[(unsigned int)format]; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | static PixelFormat PixelFormatFromTextureFormat(Pica::Regs::TextureFormat format) { | 99 | static PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) { |
| 100 | return ((unsigned int)format < 14) ? (PixelFormat)format : PixelFormat::Invalid; | 100 | return ((unsigned int)format < 14) ? (PixelFormat)format : PixelFormat::Invalid; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | static PixelFormat PixelFormatFromColorFormat(Pica::Regs::ColorFormat format) { | 103 | static PixelFormat PixelFormatFromColorFormat(Pica::FramebufferRegs::ColorFormat format) { |
| 104 | return ((unsigned int)format < 5) ? (PixelFormat)format : PixelFormat::Invalid; | 104 | return ((unsigned int)format < 5) ? (PixelFormat)format : PixelFormat::Invalid; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | static PixelFormat PixelFormatFromDepthFormat(Pica::Regs::DepthFormat format) { | 107 | static PixelFormat PixelFormatFromDepthFormat(Pica::FramebufferRegs::DepthFormat format) { |
| 108 | return ((unsigned int)format < 4) ? (PixelFormat)((unsigned int)format + 14) | 108 | return ((unsigned int)format < 4) ? (PixelFormat)((unsigned int)format + 14) |
| 109 | : PixelFormat::Invalid; | 109 | : PixelFormat::Invalid; |
| 110 | } | 110 | } |
| @@ -212,12 +212,12 @@ public: | |||
| 212 | bool load_if_create, MathUtil::Rectangle<int>& out_rect); | 212 | bool load_if_create, MathUtil::Rectangle<int>& out_rect); |
| 213 | 213 | ||
| 214 | /// Gets a surface based on the texture configuration | 214 | /// Gets a surface based on the texture configuration |
| 215 | CachedSurface* GetTextureSurface(const Pica::Regs::FullTextureConfig& config); | 215 | CachedSurface* GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config); |
| 216 | 216 | ||
| 217 | /// Gets the color and depth surfaces and rect (resolution scaled) based on the framebuffer | 217 | /// Gets the color and depth surfaces and rect (resolution scaled) based on the framebuffer |
| 218 | /// configuration | 218 | /// configuration |
| 219 | std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> GetFramebufferSurfaces( | 219 | std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> GetFramebufferSurfaces( |
| 220 | const Pica::Regs::FramebufferConfig& config); | 220 | const Pica::FramebufferRegs::FramebufferConfig& config); |
| 221 | 221 | ||
| 222 | /// Attempt to get a surface that exactly matches the fill region and format | 222 | /// Attempt to get a surface that exactly matches the fill region and format |
| 223 | CachedSurface* TryGetFillSurface(const GPU::Regs::MemoryFillConfig& config); | 223 | CachedSurface* TryGetFillSurface(const GPU::Regs::MemoryFillConfig& config); |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 4c4f98ac9..3ea25f302 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -7,13 +7,15 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "video_core/pica.h" | 10 | #include "video_core/regs.h" |
| 11 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 11 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 12 | #include "video_core/renderer_opengl/gl_shader_gen.h" | 12 | #include "video_core/renderer_opengl/gl_shader_gen.h" |
| 13 | #include "video_core/renderer_opengl/gl_shader_util.h" | 13 | #include "video_core/renderer_opengl/gl_shader_util.h" |
| 14 | 14 | ||
| 15 | using Pica::Regs; | 15 | using Pica::Regs; |
| 16 | using TevStageConfig = Regs::TevStageConfig; | 16 | using Pica::RasterizerRegs; |
| 17 | using Pica::LightingRegs; | ||
| 18 | using TevStageConfig = Pica::TexturingRegs::TevStageConfig; | ||
| 17 | 19 | ||
| 18 | namespace GLShader { | 20 | namespace GLShader { |
| 19 | 21 | ||
| @@ -46,10 +48,10 @@ static void AppendSource(std::string& out, const PicaShaderConfig& config, | |||
| 46 | case Source::Texture0: | 48 | case Source::Texture0: |
| 47 | // Only unit 0 respects the texturing type (according to 3DBrew) | 49 | // Only unit 0 respects the texturing type (according to 3DBrew) |
| 48 | switch (state.texture0_type) { | 50 | switch (state.texture0_type) { |
| 49 | case Pica::Regs::TextureConfig::Texture2D: | 51 | case Pica::TexturingRegs::TextureConfig::Texture2D: |
| 50 | out += "texture(tex[0], texcoord[0])"; | 52 | out += "texture(tex[0], texcoord[0])"; |
| 51 | break; | 53 | break; |
| 52 | case Pica::Regs::TextureConfig::Projection2D: | 54 | case Pica::TexturingRegs::TextureConfig::Projection2D: |
| 53 | out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))"; | 55 | out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))"; |
| 54 | break; | 56 | break; |
| 55 | default: | 57 | default: |
| @@ -276,8 +278,8 @@ static void AppendAlphaCombiner(std::string& out, TevStageConfig::Operation oper | |||
| 276 | } | 278 | } |
| 277 | 279 | ||
| 278 | /// Writes the if-statement condition used to evaluate alpha testing | 280 | /// Writes the if-statement condition used to evaluate alpha testing |
| 279 | static void AppendAlphaTestCondition(std::string& out, Regs::CompareFunc func) { | 281 | static void AppendAlphaTestCondition(std::string& out, Pica::FramebufferRegs::CompareFunc func) { |
| 280 | using CompareFunc = Regs::CompareFunc; | 282 | using CompareFunc = Pica::FramebufferRegs::CompareFunc; |
| 281 | switch (func) { | 283 | switch (func) { |
| 282 | case CompareFunc::Never: | 284 | case CompareFunc::Never: |
| 283 | out += "true"; | 285 | out += "true"; |
| @@ -307,7 +309,7 @@ static void AppendAlphaTestCondition(std::string& out, Regs::CompareFunc func) { | |||
| 307 | /// Writes the code to emulate the specified TEV stage | 309 | /// Writes the code to emulate the specified TEV stage |
| 308 | static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) { | 310 | static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) { |
| 309 | const auto stage = | 311 | const auto stage = |
| 310 | static_cast<const Pica::Regs::TevStageConfig>(config.state.tev_stages[index]); | 312 | static_cast<const Pica::TexturingRegs::TevStageConfig>(config.state.tev_stages[index]); |
| 311 | if (!IsPassThroughTevStage(stage)) { | 313 | if (!IsPassThroughTevStage(stage)) { |
| 312 | std::string index_name = std::to_string(index); | 314 | std::string index_name = std::to_string(index); |
| 313 | 315 | ||
| @@ -364,7 +366,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 364 | "vec3 refl_value = vec3(0.0);\n"; | 366 | "vec3 refl_value = vec3(0.0);\n"; |
| 365 | 367 | ||
| 366 | // Compute fragment normals | 368 | // Compute fragment normals |
| 367 | if (lighting.bump_mode == Pica::Regs::LightingBumpMode::NormalMap) { | 369 | if (lighting.bump_mode == LightingRegs::LightingBumpMode::NormalMap) { |
| 368 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected | 370 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected |
| 369 | // texture | 371 | // texture |
| 370 | std::string bump_selector = std::to_string(lighting.bump_selector); | 372 | std::string bump_selector = std::to_string(lighting.bump_selector); |
| @@ -378,7 +380,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 378 | "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; | 380 | "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; |
| 379 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; | 381 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; |
| 380 | } | 382 | } |
| 381 | } else if (lighting.bump_mode == Pica::Regs::LightingBumpMode::TangentMap) { | 383 | } else if (lighting.bump_mode == LightingRegs::LightingBumpMode::TangentMap) { |
| 382 | // Bump mapping is enabled using a tangent map | 384 | // Bump mapping is enabled using a tangent map |
| 383 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); | 385 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); |
| 384 | UNIMPLEMENTED(); | 386 | UNIMPLEMENTED(); |
| @@ -392,23 +394,24 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 392 | out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n"; | 394 | out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n"; |
| 393 | 395 | ||
| 394 | // Gets the index into the specified lookup table for specular lighting | 396 | // Gets the index into the specified lookup table for specular lighting |
| 395 | auto GetLutIndex = [&lighting](unsigned light_num, Regs::LightingLutInput input, bool abs) { | 397 | auto GetLutIndex = [&lighting](unsigned light_num, LightingRegs::LightingLutInput input, |
| 398 | bool abs) { | ||
| 396 | const std::string half_angle = "normalize(normalize(view) + light_vector)"; | 399 | const std::string half_angle = "normalize(normalize(view) + light_vector)"; |
| 397 | std::string index; | 400 | std::string index; |
| 398 | switch (input) { | 401 | switch (input) { |
| 399 | case Regs::LightingLutInput::NH: | 402 | case LightingRegs::LightingLutInput::NH: |
| 400 | index = "dot(normal, " + half_angle + ")"; | 403 | index = "dot(normal, " + half_angle + ")"; |
| 401 | break; | 404 | break; |
| 402 | 405 | ||
| 403 | case Regs::LightingLutInput::VH: | 406 | case LightingRegs::LightingLutInput::VH: |
| 404 | index = std::string("dot(normalize(view), " + half_angle + ")"); | 407 | index = std::string("dot(normalize(view), " + half_angle + ")"); |
| 405 | break; | 408 | break; |
| 406 | 409 | ||
| 407 | case Regs::LightingLutInput::NV: | 410 | case LightingRegs::LightingLutInput::NV: |
| 408 | index = std::string("dot(normal, normalize(view))"); | 411 | index = std::string("dot(normal, normalize(view))"); |
| 409 | break; | 412 | break; |
| 410 | 413 | ||
| 411 | case Regs::LightingLutInput::LN: | 414 | case LightingRegs::LightingLutInput::LN: |
| 412 | index = std::string("dot(light_vector, normal)"); | 415 | index = std::string("dot(light_vector, normal)"); |
| 413 | break; | 416 | break; |
| 414 | 417 | ||
| @@ -432,7 +435,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 432 | }; | 435 | }; |
| 433 | 436 | ||
| 434 | // Gets the lighting lookup table value given the specified sampler and index | 437 | // Gets the lighting lookup table value given the specified sampler and index |
| 435 | auto GetLutValue = [](Regs::LightingSampler sampler, std::string lut_index) { | 438 | auto GetLutValue = [](LightingRegs::LightingSampler sampler, std::string lut_index) { |
| 436 | return std::string("texture(lut[" + std::to_string((unsigned)sampler / 4) + "], " + | 439 | return std::string("texture(lut[" + std::to_string((unsigned)sampler / 4) + "], " + |
| 437 | lut_index + ")[" + std::to_string((unsigned)sampler & 3) + "]"); | 440 | lut_index + ")[" + std::to_string((unsigned)sampler & 3) + "]"); |
| 438 | }; | 441 | }; |
| @@ -461,8 +464,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 461 | light_src + ".position) + " + light_src + ".dist_atten_bias)"; | 464 | light_src + ".position) + " + light_src + ".dist_atten_bias)"; |
| 462 | index = "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))"; | 465 | index = "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))"; |
| 463 | const unsigned lut_num = | 466 | const unsigned lut_num = |
| 464 | ((unsigned)Regs::LightingSampler::DistanceAttenuation + light_config.num); | 467 | ((unsigned)LightingRegs::LightingSampler::DistanceAttenuation + light_config.num); |
| 465 | dist_atten = GetLutValue((Regs::LightingSampler)lut_num, index); | 468 | dist_atten = GetLutValue((LightingRegs::LightingSampler)lut_num, index); |
| 466 | } | 469 | } |
| 467 | 470 | ||
| 468 | // If enabled, clamp specular component if lighting result is negative | 471 | // If enabled, clamp specular component if lighting result is negative |
| @@ -472,24 +475,24 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 472 | // Specular 0 component | 475 | // Specular 0 component |
| 473 | std::string d0_lut_value = "1.0"; | 476 | std::string d0_lut_value = "1.0"; |
| 474 | if (lighting.lut_d0.enable && | 477 | if (lighting.lut_d0.enable && |
| 475 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 478 | LightingRegs::IsLightingSamplerSupported( |
| 476 | Pica::Regs::LightingSampler::Distribution0)) { | 479 | lighting.config, LightingRegs::LightingSampler::Distribution0)) { |
| 477 | // Lookup specular "distribution 0" LUT value | 480 | // Lookup specular "distribution 0" LUT value |
| 478 | std::string index = | 481 | std::string index = |
| 479 | GetLutIndex(light_config.num, lighting.lut_d0.type, lighting.lut_d0.abs_input); | 482 | GetLutIndex(light_config.num, lighting.lut_d0.type, lighting.lut_d0.abs_input); |
| 480 | d0_lut_value = "(" + std::to_string(lighting.lut_d0.scale) + " * " + | 483 | d0_lut_value = "(" + std::to_string(lighting.lut_d0.scale) + " * " + |
| 481 | GetLutValue(Regs::LightingSampler::Distribution0, index) + ")"; | 484 | GetLutValue(LightingRegs::LightingSampler::Distribution0, index) + ")"; |
| 482 | } | 485 | } |
| 483 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; | 486 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; |
| 484 | 487 | ||
| 485 | // If enabled, lookup ReflectRed value, otherwise, 1.0 is used | 488 | // If enabled, lookup ReflectRed value, otherwise, 1.0 is used |
| 486 | if (lighting.lut_rr.enable && | 489 | if (lighting.lut_rr.enable && |
| 487 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 490 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 488 | Pica::Regs::LightingSampler::ReflectRed)) { | 491 | LightingRegs::LightingSampler::ReflectRed)) { |
| 489 | std::string index = | 492 | std::string index = |
| 490 | GetLutIndex(light_config.num, lighting.lut_rr.type, lighting.lut_rr.abs_input); | 493 | GetLutIndex(light_config.num, lighting.lut_rr.type, lighting.lut_rr.abs_input); |
| 491 | std::string value = "(" + std::to_string(lighting.lut_rr.scale) + " * " + | 494 | std::string value = "(" + std::to_string(lighting.lut_rr.scale) + " * " + |
| 492 | GetLutValue(Regs::LightingSampler::ReflectRed, index) + ")"; | 495 | GetLutValue(LightingRegs::LightingSampler::ReflectRed, index) + ")"; |
| 493 | out += "refl_value.r = " + value + ";\n"; | 496 | out += "refl_value.r = " + value + ";\n"; |
| 494 | } else { | 497 | } else { |
| 495 | out += "refl_value.r = 1.0;\n"; | 498 | out += "refl_value.r = 1.0;\n"; |
| @@ -497,12 +500,13 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 497 | 500 | ||
| 498 | // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used | 501 | // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used |
| 499 | if (lighting.lut_rg.enable && | 502 | if (lighting.lut_rg.enable && |
| 500 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 503 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 501 | Pica::Regs::LightingSampler::ReflectGreen)) { | 504 | LightingRegs::LightingSampler::ReflectGreen)) { |
| 502 | std::string index = | 505 | std::string index = |
| 503 | GetLutIndex(light_config.num, lighting.lut_rg.type, lighting.lut_rg.abs_input); | 506 | GetLutIndex(light_config.num, lighting.lut_rg.type, lighting.lut_rg.abs_input); |
| 504 | std::string value = "(" + std::to_string(lighting.lut_rg.scale) + " * " + | 507 | std::string value = "(" + std::to_string(lighting.lut_rg.scale) + " * " + |
| 505 | GetLutValue(Regs::LightingSampler::ReflectGreen, index) + ")"; | 508 | GetLutValue(LightingRegs::LightingSampler::ReflectGreen, index) + |
| 509 | ")"; | ||
| 506 | out += "refl_value.g = " + value + ";\n"; | 510 | out += "refl_value.g = " + value + ";\n"; |
| 507 | } else { | 511 | } else { |
| 508 | out += "refl_value.g = refl_value.r;\n"; | 512 | out += "refl_value.g = refl_value.r;\n"; |
| @@ -510,12 +514,13 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 510 | 514 | ||
| 511 | // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used | 515 | // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used |
| 512 | if (lighting.lut_rb.enable && | 516 | if (lighting.lut_rb.enable && |
| 513 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 517 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 514 | Pica::Regs::LightingSampler::ReflectBlue)) { | 518 | LightingRegs::LightingSampler::ReflectBlue)) { |
| 515 | std::string index = | 519 | std::string index = |
| 516 | GetLutIndex(light_config.num, lighting.lut_rb.type, lighting.lut_rb.abs_input); | 520 | GetLutIndex(light_config.num, lighting.lut_rb.type, lighting.lut_rb.abs_input); |
| 517 | std::string value = "(" + std::to_string(lighting.lut_rb.scale) + " * " + | 521 | std::string value = "(" + std::to_string(lighting.lut_rb.scale) + " * " + |
| 518 | GetLutValue(Regs::LightingSampler::ReflectBlue, index) + ")"; | 522 | GetLutValue(LightingRegs::LightingSampler::ReflectBlue, index) + |
| 523 | ")"; | ||
| 519 | out += "refl_value.b = " + value + ";\n"; | 524 | out += "refl_value.b = " + value + ";\n"; |
| 520 | } else { | 525 | } else { |
| 521 | out += "refl_value.b = refl_value.r;\n"; | 526 | out += "refl_value.b = refl_value.r;\n"; |
| @@ -524,35 +529,39 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 524 | // Specular 1 component | 529 | // Specular 1 component |
| 525 | std::string d1_lut_value = "1.0"; | 530 | std::string d1_lut_value = "1.0"; |
| 526 | if (lighting.lut_d1.enable && | 531 | if (lighting.lut_d1.enable && |
| 527 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 532 | LightingRegs::IsLightingSamplerSupported( |
| 528 | Pica::Regs::LightingSampler::Distribution1)) { | 533 | lighting.config, LightingRegs::LightingSampler::Distribution1)) { |
| 529 | // Lookup specular "distribution 1" LUT value | 534 | // Lookup specular "distribution 1" LUT value |
| 530 | std::string index = | 535 | std::string index = |
| 531 | GetLutIndex(light_config.num, lighting.lut_d1.type, lighting.lut_d1.abs_input); | 536 | GetLutIndex(light_config.num, lighting.lut_d1.type, lighting.lut_d1.abs_input); |
| 532 | d1_lut_value = "(" + std::to_string(lighting.lut_d1.scale) + " * " + | 537 | d1_lut_value = "(" + std::to_string(lighting.lut_d1.scale) + " * " + |
| 533 | GetLutValue(Regs::LightingSampler::Distribution1, index) + ")"; | 538 | GetLutValue(LightingRegs::LightingSampler::Distribution1, index) + ")"; |
| 534 | } | 539 | } |
| 535 | std::string specular_1 = | 540 | std::string specular_1 = |
| 536 | "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; | 541 | "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; |
| 537 | 542 | ||
| 538 | // Fresnel | 543 | // Fresnel |
| 539 | if (lighting.lut_fr.enable && Pica::Regs::IsLightingSamplerSupported( | 544 | if (lighting.lut_fr.enable && |
| 540 | lighting.config, Pica::Regs::LightingSampler::Fresnel)) { | 545 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 546 | LightingRegs::LightingSampler::Fresnel)) { | ||
| 541 | // Lookup fresnel LUT value | 547 | // Lookup fresnel LUT value |
| 542 | std::string index = | 548 | std::string index = |
| 543 | GetLutIndex(light_config.num, lighting.lut_fr.type, lighting.lut_fr.abs_input); | 549 | GetLutIndex(light_config.num, lighting.lut_fr.type, lighting.lut_fr.abs_input); |
| 544 | std::string value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + | 550 | std::string value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + |
| 545 | GetLutValue(Regs::LightingSampler::Fresnel, index) + ")"; | 551 | GetLutValue(LightingRegs::LightingSampler::Fresnel, index) + ")"; |
| 546 | 552 | ||
| 547 | // Enabled for difffuse lighting alpha component | 553 | // Enabled for difffuse lighting alpha component |
| 548 | if (lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::PrimaryAlpha || | 554 | if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || |
| 549 | lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) | 555 | lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |
| 550 | out += "diffuse_sum.a *= " + value + ";\n"; | 556 | out += "diffuse_sum.a *= " + value + ";\n"; |
| 557 | } | ||
| 551 | 558 | ||
| 552 | // Enabled for the specular lighting alpha component | 559 | // Enabled for the specular lighting alpha component |
| 553 | if (lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::SecondaryAlpha || | 560 | if (lighting.fresnel_selector == |
| 554 | lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) | 561 | LightingRegs::LightingFresnelSelector::SecondaryAlpha || |
| 562 | lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { | ||
| 555 | out += "specular_sum.a *= " + value + ";\n"; | 563 | out += "specular_sum.a *= " + value + ";\n"; |
| 564 | } | ||
| 556 | } | 565 | } |
| 557 | 566 | ||
| 558 | // Compute primary fragment color (diffuse lighting) function | 567 | // Compute primary fragment color (diffuse lighting) function |
| @@ -633,16 +642,16 @@ vec4 secondary_fragment_color = vec4(0.0); | |||
| 633 | )"; | 642 | )"; |
| 634 | 643 | ||
| 635 | // Do not do any sort of processing if it's obvious we're not going to pass the alpha test | 644 | // Do not do any sort of processing if it's obvious we're not going to pass the alpha test |
| 636 | if (state.alpha_test_func == Regs::CompareFunc::Never) { | 645 | if (state.alpha_test_func == Pica::FramebufferRegs::CompareFunc::Never) { |
| 637 | out += "discard; }"; | 646 | out += "discard; }"; |
| 638 | return out; | 647 | return out; |
| 639 | } | 648 | } |
| 640 | 649 | ||
| 641 | // Append the scissor test | 650 | // Append the scissor test |
| 642 | if (state.scissor_test_mode != Regs::ScissorMode::Disabled) { | 651 | if (state.scissor_test_mode != RasterizerRegs::ScissorMode::Disabled) { |
| 643 | out += "if ("; | 652 | out += "if ("; |
| 644 | // Negate the condition if we have to keep only the pixels outside the scissor box | 653 | // Negate the condition if we have to keep only the pixels outside the scissor box |
| 645 | if (state.scissor_test_mode == Regs::ScissorMode::Include) | 654 | if (state.scissor_test_mode == RasterizerRegs::ScissorMode::Include) |
| 646 | out += "!"; | 655 | out += "!"; |
| 647 | out += "(gl_FragCoord.x >= scissor_x1 && " | 656 | out += "(gl_FragCoord.x >= scissor_x1 && " |
| 648 | "gl_FragCoord.y >= scissor_y1 && " | 657 | "gl_FragCoord.y >= scissor_y1 && " |
| @@ -652,7 +661,7 @@ vec4 secondary_fragment_color = vec4(0.0); | |||
| 652 | 661 | ||
| 653 | out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n"; | 662 | out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n"; |
| 654 | out += "float depth = z_over_w * depth_scale + depth_offset;\n"; | 663 | out += "float depth = z_over_w * depth_scale + depth_offset;\n"; |
| 655 | if (state.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) { | 664 | if (state.depthmap_enable == Pica::RasterizerRegs::DepthBuffering::WBuffering) { |
| 656 | out += "depth /= gl_FragCoord.w;\n"; | 665 | out += "depth /= gl_FragCoord.w;\n"; |
| 657 | } | 666 | } |
| 658 | 667 | ||
| @@ -666,14 +675,14 @@ vec4 secondary_fragment_color = vec4(0.0); | |||
| 666 | for (size_t index = 0; index < state.tev_stages.size(); ++index) | 675 | for (size_t index = 0; index < state.tev_stages.size(); ++index) |
| 667 | WriteTevStage(out, config, (unsigned)index); | 676 | WriteTevStage(out, config, (unsigned)index); |
| 668 | 677 | ||
| 669 | if (state.alpha_test_func != Regs::CompareFunc::Always) { | 678 | if (state.alpha_test_func != Pica::FramebufferRegs::CompareFunc::Always) { |
| 670 | out += "if ("; | 679 | out += "if ("; |
| 671 | AppendAlphaTestCondition(out, state.alpha_test_func); | 680 | AppendAlphaTestCondition(out, state.alpha_test_func); |
| 672 | out += ") discard;\n"; | 681 | out += ") discard;\n"; |
| 673 | } | 682 | } |
| 674 | 683 | ||
| 675 | // Append fog combiner | 684 | // Append fog combiner |
| 676 | if (state.fog_mode == Regs::FogMode::Fog) { | 685 | if (state.fog_mode == Pica::TexturingRegs::FogMode::Fog) { |
| 677 | // Get index into fog LUT | 686 | // Get index into fog LUT |
| 678 | if (state.fog_flip) { | 687 | if (state.fog_flip) { |
| 679 | out += "float fog_index = (1.0 - depth) * 128.0;\n"; | 688 | out += "float fog_index = (1.0 - depth) * 128.0;\n"; |
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h index cc49867c8..4b98dafc4 100644 --- a/src/video_core/renderer_opengl/pica_to_gl.h +++ b/src/video_core/renderer_opengl/pica_to_gl.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include "common/common_funcs.h" | 12 | #include "common/common_funcs.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 15 | #include "video_core/pica.h" | 15 | #include "video_core/regs.h" |
| 16 | 16 | ||
| 17 | using GLvec2 = std::array<GLfloat, 2>; | 17 | using GLvec2 = std::array<GLfloat, 2>; |
| 18 | using GLvec3 = std::array<GLfloat, 3>; | 18 | using GLvec3 = std::array<GLfloat, 3>; |
| @@ -20,7 +20,7 @@ using GLvec4 = std::array<GLfloat, 4>; | |||
| 20 | 20 | ||
| 21 | namespace PicaToGL { | 21 | namespace PicaToGL { |
| 22 | 22 | ||
| 23 | inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) { | 23 | inline GLenum TextureFilterMode(Pica::TexturingRegs::TextureConfig::TextureFilter mode) { |
| 24 | static const GLenum filter_mode_table[] = { | 24 | static const GLenum filter_mode_table[] = { |
| 25 | GL_NEAREST, // TextureFilter::Nearest | 25 | GL_NEAREST, // TextureFilter::Nearest |
| 26 | GL_LINEAR, // TextureFilter::Linear | 26 | GL_LINEAR, // TextureFilter::Linear |
| @@ -47,7 +47,7 @@ inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) { | |||
| 47 | return gl_mode; | 47 | return gl_mode; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | inline GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) { | 50 | inline GLenum WrapMode(Pica::TexturingRegs::TextureConfig::WrapMode mode) { |
| 51 | static const GLenum wrap_mode_table[] = { | 51 | static const GLenum wrap_mode_table[] = { |
| 52 | GL_CLAMP_TO_EDGE, // WrapMode::ClampToEdge | 52 | GL_CLAMP_TO_EDGE, // WrapMode::ClampToEdge |
| 53 | GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder | 53 | GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder |
| @@ -76,7 +76,7 @@ inline GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) { | |||
| 76 | return gl_mode; | 76 | return gl_mode; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | inline GLenum BlendEquation(Pica::Regs::BlendEquation equation) { | 79 | inline GLenum BlendEquation(Pica::FramebufferRegs::BlendEquation equation) { |
| 80 | static const GLenum blend_equation_table[] = { | 80 | static const GLenum blend_equation_table[] = { |
| 81 | GL_FUNC_ADD, // BlendEquation::Add | 81 | GL_FUNC_ADD, // BlendEquation::Add |
| 82 | GL_FUNC_SUBTRACT, // BlendEquation::Subtract | 82 | GL_FUNC_SUBTRACT, // BlendEquation::Subtract |
| @@ -96,7 +96,7 @@ inline GLenum BlendEquation(Pica::Regs::BlendEquation equation) { | |||
| 96 | return blend_equation_table[(unsigned)equation]; | 96 | return blend_equation_table[(unsigned)equation]; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | inline GLenum BlendFunc(Pica::Regs::BlendFactor factor) { | 99 | inline GLenum BlendFunc(Pica::FramebufferRegs::BlendFactor factor) { |
| 100 | static const GLenum blend_func_table[] = { | 100 | static const GLenum blend_func_table[] = { |
| 101 | GL_ZERO, // BlendFactor::Zero | 101 | GL_ZERO, // BlendFactor::Zero |
| 102 | GL_ONE, // BlendFactor::One | 102 | GL_ONE, // BlendFactor::One |
| @@ -126,7 +126,7 @@ inline GLenum BlendFunc(Pica::Regs::BlendFactor factor) { | |||
| 126 | return blend_func_table[(unsigned)factor]; | 126 | return blend_func_table[(unsigned)factor]; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | inline GLenum LogicOp(Pica::Regs::LogicOp op) { | 129 | inline GLenum LogicOp(Pica::FramebufferRegs::LogicOp op) { |
| 130 | static const GLenum logic_op_table[] = { | 130 | static const GLenum logic_op_table[] = { |
| 131 | GL_CLEAR, // Clear | 131 | GL_CLEAR, // Clear |
| 132 | GL_AND, // And | 132 | GL_AND, // And |
| @@ -157,7 +157,7 @@ inline GLenum LogicOp(Pica::Regs::LogicOp op) { | |||
| 157 | return logic_op_table[(unsigned)op]; | 157 | return logic_op_table[(unsigned)op]; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | inline GLenum CompareFunc(Pica::Regs::CompareFunc func) { | 160 | inline GLenum CompareFunc(Pica::FramebufferRegs::CompareFunc func) { |
| 161 | static const GLenum compare_func_table[] = { | 161 | static const GLenum compare_func_table[] = { |
| 162 | GL_NEVER, // CompareFunc::Never | 162 | GL_NEVER, // CompareFunc::Never |
| 163 | GL_ALWAYS, // CompareFunc::Always | 163 | GL_ALWAYS, // CompareFunc::Always |
| @@ -180,7 +180,7 @@ inline GLenum CompareFunc(Pica::Regs::CompareFunc func) { | |||
| 180 | return compare_func_table[(unsigned)func]; | 180 | return compare_func_table[(unsigned)func]; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | inline GLenum StencilOp(Pica::Regs::StencilAction action) { | 183 | inline GLenum StencilOp(Pica::FramebufferRegs::StencilAction action) { |
| 184 | static const GLenum stencil_op_table[] = { | 184 | static const GLenum stencil_op_table[] = { |
| 185 | GL_KEEP, // StencilAction::Keep | 185 | GL_KEEP, // StencilAction::Keep |
| 186 | GL_ZERO, // StencilAction::Zero | 186 | GL_ZERO, // StencilAction::Zero |
| @@ -210,7 +210,7 @@ inline GLvec4 ColorRGBA8(const u32 color) { | |||
| 210 | }}; | 210 | }}; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | inline std::array<GLfloat, 3> LightColor(const Pica::Regs::LightColor& color) { | 213 | inline std::array<GLfloat, 3> LightColor(const Pica::LightingRegs::LightColor& color) { |
| 214 | return {{ | 214 | return {{ |
| 215 | color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, | 215 | color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, |
| 216 | }}; | 216 | }}; |
diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp index f5f7ea61d..c860375a1 100644 --- a/src/video_core/shader/shader.cpp +++ b/src/video_core/shader/shader.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #include "common/bit_set.h" | 7 | #include "common/bit_set.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "common/microprofile.h" | 9 | #include "common/microprofile.h" |
| 10 | #include "video_core/pica.h" | ||
| 11 | #include "video_core/pica_state.h" | 10 | #include "video_core/pica_state.h" |
| 11 | #include "video_core/regs.h" | ||
| 12 | #include "video_core/shader/shader.h" | 12 | #include "video_core/shader/shader.h" |
| 13 | #include "video_core/shader/shader_interpreter.h" | 13 | #include "video_core/shader/shader_interpreter.h" |
| 14 | #ifdef ARCHITECTURE_x86_64 | 14 | #ifdef ARCHITECTURE_x86_64 |
| @@ -20,7 +20,7 @@ namespace Pica { | |||
| 20 | 20 | ||
| 21 | namespace Shader { | 21 | namespace Shader { |
| 22 | 22 | ||
| 23 | OutputVertex OutputVertex::FromAttributeBuffer(const Regs& regs, AttributeBuffer& input) { | 23 | OutputVertex OutputVertex::FromAttributeBuffer(const RasterizerRegs& regs, AttributeBuffer& input) { |
| 24 | // Setup output data | 24 | // Setup output data |
| 25 | union { | 25 | union { |
| 26 | OutputVertex ret{}; | 26 | OutputVertex ret{}; |
| @@ -33,16 +33,16 @@ OutputVertex OutputVertex::FromAttributeBuffer(const Regs& regs, AttributeBuffer | |||
| 33 | for (unsigned int i = 0; i < num_attributes; ++i) { | 33 | for (unsigned int i = 0; i < num_attributes; ++i) { |
| 34 | const auto& output_register_map = regs.vs_output_attributes[i]; | 34 | const auto& output_register_map = regs.vs_output_attributes[i]; |
| 35 | 35 | ||
| 36 | Regs::VSOutputAttributes::Semantic semantics[4] = { | 36 | RasterizerRegs::VSOutputAttributes::Semantic semantics[4] = { |
| 37 | output_register_map.map_x, output_register_map.map_y, output_register_map.map_z, | 37 | output_register_map.map_x, output_register_map.map_y, output_register_map.map_z, |
| 38 | output_register_map.map_w}; | 38 | output_register_map.map_w}; |
| 39 | 39 | ||
| 40 | for (unsigned comp = 0; comp < 4; ++comp) { | 40 | for (unsigned comp = 0; comp < 4; ++comp) { |
| 41 | Regs::VSOutputAttributes::Semantic semantic = semantics[comp]; | 41 | RasterizerRegs::VSOutputAttributes::Semantic semantic = semantics[comp]; |
| 42 | float24* out = &vertex_slots[semantic]; | 42 | float24* out = &vertex_slots[semantic]; |
| 43 | if (semantic < vertex_slots.size()) { | 43 | if (semantic < vertex_slots.size()) { |
| 44 | *out = input.attr[i][comp]; | 44 | *out = input.attr[i][comp]; |
| 45 | } else if (semantic != Regs::VSOutputAttributes::INVALID) { | 45 | } else if (semantic != RasterizerRegs::VSOutputAttributes::INVALID) { |
| 46 | LOG_ERROR(HW_GPU, "Invalid/unknown semantic id: %u", (unsigned int)semantic); | 46 | LOG_ERROR(HW_GPU, "Invalid/unknown semantic id: %u", (unsigned int)semantic); |
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| @@ -66,7 +66,7 @@ OutputVertex OutputVertex::FromAttributeBuffer(const Regs& regs, AttributeBuffer | |||
| 66 | return ret; | 66 | return ret; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | void UnitState::LoadInput(const Regs::ShaderConfig& config, const AttributeBuffer& input) { | 69 | void UnitState::LoadInput(const ShaderRegs& config, const AttributeBuffer& input) { |
| 70 | const unsigned max_attribute = config.max_input_attribute_index; | 70 | const unsigned max_attribute = config.max_input_attribute_index; |
| 71 | 71 | ||
| 72 | for (unsigned attr = 0; attr <= max_attribute; ++attr) { | 72 | for (unsigned attr = 0; attr <= max_attribute; ++attr) { |
| @@ -75,7 +75,7 @@ void UnitState::LoadInput(const Regs::ShaderConfig& config, const AttributeBuffe | |||
| 75 | } | 75 | } |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | void UnitState::WriteOutput(const Regs::ShaderConfig& config, AttributeBuffer& output) { | 78 | void UnitState::WriteOutput(const ShaderRegs& config, AttributeBuffer& output) { |
| 79 | unsigned int output_i = 0; | 79 | unsigned int output_i = 0; |
| 80 | for (unsigned int reg : Common::BitSet<u32>(config.output_mask)) { | 80 | for (unsigned int reg : Common::BitSet<u32>(config.output_mask)) { |
| 81 | output.attr[output_i++] = registers.output[reg]; | 81 | output.attr[output_i++] = registers.output[reg]; |
diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h index b188d3edf..d52682479 100644 --- a/src/video_core/shader/shader.h +++ b/src/video_core/shader/shader.h | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #include "common/common_funcs.h" | 12 | #include "common/common_funcs.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/vector_math.h" | 14 | #include "common/vector_math.h" |
| 15 | #include "video_core/pica.h" | ||
| 16 | #include "video_core/pica_types.h" | 15 | #include "video_core/pica_types.h" |
| 16 | #include "video_core/regs.h" | ||
| 17 | 17 | ||
| 18 | using nihstro::RegisterType; | 18 | using nihstro::RegisterType; |
| 19 | using nihstro::SourceRegister; | 19 | using nihstro::SourceRegister; |
| @@ -39,19 +39,19 @@ struct OutputVertex { | |||
| 39 | INSERT_PADDING_WORDS(1); | 39 | INSERT_PADDING_WORDS(1); |
| 40 | Math::Vec2<float24> tc2; | 40 | Math::Vec2<float24> tc2; |
| 41 | 41 | ||
| 42 | static OutputVertex FromAttributeBuffer(const Regs& regs, AttributeBuffer& output); | 42 | static OutputVertex FromAttributeBuffer(const RasterizerRegs& regs, AttributeBuffer& output); |
| 43 | }; | 43 | }; |
| 44 | #define ASSERT_POS(var, pos) \ | 44 | #define ASSERT_POS(var, pos) \ |
| 45 | static_assert(offsetof(OutputVertex, var) == pos * sizeof(float24), "Semantic at wrong " \ | 45 | static_assert(offsetof(OutputVertex, var) == pos * sizeof(float24), "Semantic at wrong " \ |
| 46 | "offset.") | 46 | "offset.") |
| 47 | ASSERT_POS(pos, Regs::VSOutputAttributes::POSITION_X); | 47 | ASSERT_POS(pos, RasterizerRegs::VSOutputAttributes::POSITION_X); |
| 48 | ASSERT_POS(quat, Regs::VSOutputAttributes::QUATERNION_X); | 48 | ASSERT_POS(quat, RasterizerRegs::VSOutputAttributes::QUATERNION_X); |
| 49 | ASSERT_POS(color, Regs::VSOutputAttributes::COLOR_R); | 49 | ASSERT_POS(color, RasterizerRegs::VSOutputAttributes::COLOR_R); |
| 50 | ASSERT_POS(tc0, Regs::VSOutputAttributes::TEXCOORD0_U); | 50 | ASSERT_POS(tc0, RasterizerRegs::VSOutputAttributes::TEXCOORD0_U); |
| 51 | ASSERT_POS(tc1, Regs::VSOutputAttributes::TEXCOORD1_U); | 51 | ASSERT_POS(tc1, RasterizerRegs::VSOutputAttributes::TEXCOORD1_U); |
| 52 | ASSERT_POS(tc0_w, Regs::VSOutputAttributes::TEXCOORD0_W); | 52 | ASSERT_POS(tc0_w, RasterizerRegs::VSOutputAttributes::TEXCOORD0_W); |
| 53 | ASSERT_POS(view, Regs::VSOutputAttributes::VIEW_X); | 53 | ASSERT_POS(view, RasterizerRegs::VSOutputAttributes::VIEW_X); |
| 54 | ASSERT_POS(tc2, Regs::VSOutputAttributes::TEXCOORD2_U); | 54 | ASSERT_POS(tc2, RasterizerRegs::VSOutputAttributes::TEXCOORD2_U); |
| 55 | #undef ASSERT_POS | 55 | #undef ASSERT_POS |
| 56 | static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); | 56 | static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); |
| 57 | static_assert(sizeof(OutputVertex) == 24 * sizeof(float), "OutputVertex has invalid size"); | 57 | static_assert(sizeof(OutputVertex) == 24 * sizeof(float), "OutputVertex has invalid size"); |
| @@ -116,9 +116,9 @@ struct UnitState { | |||
| 116 | * @param config Shader configuration registers corresponding to the unit. | 116 | * @param config Shader configuration registers corresponding to the unit. |
| 117 | * @param input Attribute buffer to load into the input registers. | 117 | * @param input Attribute buffer to load into the input registers. |
| 118 | */ | 118 | */ |
| 119 | void LoadInput(const Regs::ShaderConfig& config, const AttributeBuffer& input); | 119 | void LoadInput(const ShaderRegs& config, const AttributeBuffer& input); |
| 120 | 120 | ||
| 121 | void WriteOutput(const Regs::ShaderConfig& config, AttributeBuffer& output); | 121 | void WriteOutput(const ShaderRegs& config, AttributeBuffer& output); |
| 122 | }; | 122 | }; |
| 123 | 123 | ||
| 124 | struct ShaderSetup { | 124 | struct ShaderSetup { |
diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp index 81522b8f5..f4d1c46c5 100644 --- a/src/video_core/shader/shader_interpreter.cpp +++ b/src/video_core/shader/shader_interpreter.cpp | |||
| @@ -669,7 +669,7 @@ void InterpreterEngine::Run(const ShaderSetup& setup, UnitState& state) const { | |||
| 669 | 669 | ||
| 670 | DebugData<true> InterpreterEngine::ProduceDebugInfo(const ShaderSetup& setup, | 670 | DebugData<true> InterpreterEngine::ProduceDebugInfo(const ShaderSetup& setup, |
| 671 | const AttributeBuffer& input, | 671 | const AttributeBuffer& input, |
| 672 | const Regs::ShaderConfig& config) const { | 672 | const ShaderRegs& config) const { |
| 673 | UnitState state; | 673 | UnitState state; |
| 674 | DebugData<true> debug_data; | 674 | DebugData<true> debug_data; |
| 675 | 675 | ||
diff --git a/src/video_core/shader/shader_interpreter.h b/src/video_core/shader/shader_interpreter.h index d7a61e122..5682b3a39 100644 --- a/src/video_core/shader/shader_interpreter.h +++ b/src/video_core/shader/shader_interpreter.h | |||
| @@ -23,7 +23,7 @@ public: | |||
| 23 | * @return Debug information for this shader with regards to the given vertex | 23 | * @return Debug information for this shader with regards to the given vertex |
| 24 | */ | 24 | */ |
| 25 | DebugData<true> ProduceDebugInfo(const ShaderSetup& setup, const AttributeBuffer& input, | 25 | DebugData<true> ProduceDebugInfo(const ShaderSetup& setup, const AttributeBuffer& input, |
| 26 | const Regs::ShaderConfig& config) const; | 26 | const ShaderRegs& config) const; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | } // namespace | 29 | } // namespace |
diff --git a/src/video_core/texture/texture_decode.cpp b/src/video_core/texture/texture_decode.cpp index f611a1aa9..40d363184 100644 --- a/src/video_core/texture/texture_decode.cpp +++ b/src/video_core/texture/texture_decode.cpp | |||
| @@ -10,12 +10,12 @@ | |||
| 10 | #include "common/math_util.h" | 10 | #include "common/math_util.h" |
| 11 | #include "common/swap.h" | 11 | #include "common/swap.h" |
| 12 | #include "common/vector_math.h" | 12 | #include "common/vector_math.h" |
| 13 | #include "video_core/pica.h" | 13 | #include "video_core/regs_texturing.h" |
| 14 | #include "video_core/texture/etc1.h" | 14 | #include "video_core/texture/etc1.h" |
| 15 | #include "video_core/texture/texture_decode.h" | 15 | #include "video_core/texture/texture_decode.h" |
| 16 | #include "video_core/utils.h" | 16 | #include "video_core/utils.h" |
| 17 | 17 | ||
| 18 | using TextureFormat = Pica::Regs::TextureFormat; | 18 | using TextureFormat = Pica::TexturingRegs::TextureFormat; |
| 19 | 19 | ||
| 20 | namespace Pica { | 20 | namespace Pica { |
| 21 | namespace Texture { | 21 | namespace Texture { |
| @@ -82,32 +82,32 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int | |||
| 82 | using VideoCore::MortonInterleave; | 82 | using VideoCore::MortonInterleave; |
| 83 | 83 | ||
| 84 | switch (info.format) { | 84 | switch (info.format) { |
| 85 | case Regs::TextureFormat::RGBA8: { | 85 | case TextureFormat::RGBA8: { |
| 86 | auto res = Color::DecodeRGBA8(source + MortonInterleave(x, y) * 4); | 86 | auto res = Color::DecodeRGBA8(source + MortonInterleave(x, y) * 4); |
| 87 | return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; | 87 | return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | case Regs::TextureFormat::RGB8: { | 90 | case TextureFormat::RGB8: { |
| 91 | auto res = Color::DecodeRGB8(source + MortonInterleave(x, y) * 3); | 91 | auto res = Color::DecodeRGB8(source + MortonInterleave(x, y) * 3); |
| 92 | return {res.r(), res.g(), res.b(), 255}; | 92 | return {res.r(), res.g(), res.b(), 255}; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | case Regs::TextureFormat::RGB5A1: { | 95 | case TextureFormat::RGB5A1: { |
| 96 | auto res = Color::DecodeRGB5A1(source + MortonInterleave(x, y) * 2); | 96 | auto res = Color::DecodeRGB5A1(source + MortonInterleave(x, y) * 2); |
| 97 | return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; | 97 | return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | case Regs::TextureFormat::RGB565: { | 100 | case TextureFormat::RGB565: { |
| 101 | auto res = Color::DecodeRGB565(source + MortonInterleave(x, y) * 2); | 101 | auto res = Color::DecodeRGB565(source + MortonInterleave(x, y) * 2); |
| 102 | return {res.r(), res.g(), res.b(), 255}; | 102 | return {res.r(), res.g(), res.b(), 255}; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | case Regs::TextureFormat::RGBA4: { | 105 | case TextureFormat::RGBA4: { |
| 106 | auto res = Color::DecodeRGBA4(source + MortonInterleave(x, y) * 2); | 106 | auto res = Color::DecodeRGBA4(source + MortonInterleave(x, y) * 2); |
| 107 | return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; | 107 | return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | case Regs::TextureFormat::IA8: { | 110 | case TextureFormat::IA8: { |
| 111 | const u8* source_ptr = source + MortonInterleave(x, y) * 2; | 111 | const u8* source_ptr = source + MortonInterleave(x, y) * 2; |
| 112 | 112 | ||
| 113 | if (disable_alpha) { | 113 | if (disable_alpha) { |
| @@ -118,17 +118,17 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int | |||
| 118 | } | 118 | } |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | case Regs::TextureFormat::RG8: { | 121 | case TextureFormat::RG8: { |
| 122 | auto res = Color::DecodeRG8(source + MortonInterleave(x, y) * 2); | 122 | auto res = Color::DecodeRG8(source + MortonInterleave(x, y) * 2); |
| 123 | return {res.r(), res.g(), 0, 255}; | 123 | return {res.r(), res.g(), 0, 255}; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | case Regs::TextureFormat::I8: { | 126 | case TextureFormat::I8: { |
| 127 | const u8* source_ptr = source + MortonInterleave(x, y); | 127 | const u8* source_ptr = source + MortonInterleave(x, y); |
| 128 | return {*source_ptr, *source_ptr, *source_ptr, 255}; | 128 | return {*source_ptr, *source_ptr, *source_ptr, 255}; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | case Regs::TextureFormat::A8: { | 131 | case TextureFormat::A8: { |
| 132 | const u8* source_ptr = source + MortonInterleave(x, y); | 132 | const u8* source_ptr = source + MortonInterleave(x, y); |
| 133 | 133 | ||
| 134 | if (disable_alpha) { | 134 | if (disable_alpha) { |
| @@ -138,7 +138,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int | |||
| 138 | } | 138 | } |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | case Regs::TextureFormat::IA4: { | 141 | case TextureFormat::IA4: { |
| 142 | const u8* source_ptr = source + MortonInterleave(x, y); | 142 | const u8* source_ptr = source + MortonInterleave(x, y); |
| 143 | 143 | ||
| 144 | u8 i = Color::Convert4To8(((*source_ptr) & 0xF0) >> 4); | 144 | u8 i = Color::Convert4To8(((*source_ptr) & 0xF0) >> 4); |
| @@ -152,7 +152,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int | |||
| 152 | } | 152 | } |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | case Regs::TextureFormat::I4: { | 155 | case TextureFormat::I4: { |
| 156 | u32 morton_offset = MortonInterleave(x, y); | 156 | u32 morton_offset = MortonInterleave(x, y); |
| 157 | const u8* source_ptr = source + morton_offset / 2; | 157 | const u8* source_ptr = source + morton_offset / 2; |
| 158 | 158 | ||
| @@ -162,7 +162,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int | |||
| 162 | return {i, i, i, 255}; | 162 | return {i, i, i, 255}; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | case Regs::TextureFormat::A4: { | 165 | case TextureFormat::A4: { |
| 166 | u32 morton_offset = MortonInterleave(x, y); | 166 | u32 morton_offset = MortonInterleave(x, y); |
| 167 | const u8* source_ptr = source + morton_offset / 2; | 167 | const u8* source_ptr = source + morton_offset / 2; |
| 168 | 168 | ||
| @@ -176,9 +176,9 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int | |||
| 176 | } | 176 | } |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | case Regs::TextureFormat::ETC1: | 179 | case TextureFormat::ETC1: |
| 180 | case Regs::TextureFormat::ETC1A4: { | 180 | case TextureFormat::ETC1A4: { |
| 181 | bool has_alpha = (info.format == Regs::TextureFormat::ETC1A4); | 181 | bool has_alpha = (info.format == TextureFormat::ETC1A4); |
| 182 | size_t subtile_size = has_alpha ? 16 : 8; | 182 | size_t subtile_size = has_alpha ? 16 : 8; |
| 183 | 183 | ||
| 184 | // ETC1 further subdivides each 8x8 tile into four 4x4 subtiles | 184 | // ETC1 further subdivides each 8x8 tile into four 4x4 subtiles |
| @@ -214,8 +214,8 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int | |||
| 214 | } | 214 | } |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, | 217 | TextureInfo TextureInfo::FromPicaRegister(const TexturingRegs::TextureConfig& config, |
| 218 | const Regs::TextureFormat& format) { | 218 | const TexturingRegs::TextureFormat& format) { |
| 219 | TextureInfo info; | 219 | TextureInfo info; |
| 220 | info.physical_address = config.GetPhysicalAddress(); | 220 | info.physical_address = config.GetPhysicalAddress(); |
| 221 | info.width = config.width; | 221 | info.width = config.width; |
diff --git a/src/video_core/texture/texture_decode.h b/src/video_core/texture/texture_decode.h index 5c636939a..8507cfeb8 100644 --- a/src/video_core/texture/texture_decode.h +++ b/src/video_core/texture/texture_decode.h | |||
| @@ -6,27 +6,27 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/vector_math.h" | 8 | #include "common/vector_math.h" |
| 9 | #include "video_core/pica.h" | 9 | #include "video_core/regs_texturing.h" |
| 10 | 10 | ||
| 11 | namespace Pica { | 11 | namespace Pica { |
| 12 | namespace Texture { | 12 | namespace Texture { |
| 13 | 13 | ||
| 14 | /// Returns the byte size of a 8*8 tile of the specified texture format. | 14 | /// Returns the byte size of a 8*8 tile of the specified texture format. |
| 15 | size_t CalculateTileSize(Pica::Regs::TextureFormat format); | 15 | size_t CalculateTileSize(TexturingRegs::TextureFormat format); |
| 16 | 16 | ||
| 17 | struct TextureInfo { | 17 | struct TextureInfo { |
| 18 | PAddr physical_address; | 18 | PAddr physical_address; |
| 19 | unsigned int width; | 19 | unsigned int width; |
| 20 | unsigned int height; | 20 | unsigned int height; |
| 21 | ptrdiff_t stride; | 21 | ptrdiff_t stride; |
| 22 | Pica::Regs::TextureFormat format; | 22 | TexturingRegs::TextureFormat format; |
| 23 | 23 | ||
| 24 | static TextureInfo FromPicaRegister(const Pica::Regs::TextureConfig& config, | 24 | static TextureInfo FromPicaRegister(const TexturingRegs::TextureConfig& config, |
| 25 | const Pica::Regs::TextureFormat& format); | 25 | const TexturingRegs::TextureFormat& format); |
| 26 | 26 | ||
| 27 | /// Calculates stride from format and width, assuming that the entire texture is contiguous. | 27 | /// Calculates stride from format and width, assuming that the entire texture is contiguous. |
| 28 | void SetDefaultStride() { | 28 | void SetDefaultStride() { |
| 29 | stride = Pica::Texture::CalculateTileSize(format) * (width / 8); | 29 | stride = CalculateTileSize(format) * (width / 8); |
| 30 | } | 30 | } |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
diff --git a/src/video_core/vertex_loader.cpp b/src/video_core/vertex_loader.cpp index bf83b61ca..37c5224a9 100644 --- a/src/video_core/vertex_loader.cpp +++ b/src/video_core/vertex_loader.cpp | |||
| @@ -8,15 +8,15 @@ | |||
| 8 | #include "common/vector_math.h" | 8 | #include "common/vector_math.h" |
| 9 | #include "core/memory.h" | 9 | #include "core/memory.h" |
| 10 | #include "video_core/debug_utils/debug_utils.h" | 10 | #include "video_core/debug_utils/debug_utils.h" |
| 11 | #include "video_core/pica.h" | ||
| 12 | #include "video_core/pica_state.h" | 11 | #include "video_core/pica_state.h" |
| 13 | #include "video_core/pica_types.h" | 12 | #include "video_core/pica_types.h" |
| 13 | #include "video_core/regs_pipeline.h" | ||
| 14 | #include "video_core/shader/shader.h" | 14 | #include "video_core/shader/shader.h" |
| 15 | #include "video_core/vertex_loader.h" | 15 | #include "video_core/vertex_loader.h" |
| 16 | 16 | ||
| 17 | namespace Pica { | 17 | namespace Pica { |
| 18 | 18 | ||
| 19 | void VertexLoader::Setup(const Pica::Regs& regs) { | 19 | void VertexLoader::Setup(const PipelineRegs& regs) { |
| 20 | ASSERT_MSG(!is_setup, "VertexLoader is not intended to be setup more than once."); | 20 | ASSERT_MSG(!is_setup, "VertexLoader is not intended to be setup more than once."); |
| 21 | 21 | ||
| 22 | const auto& attribute_config = regs.vertex_attributes; | 22 | const auto& attribute_config = regs.vertex_attributes; |
| @@ -85,15 +85,16 @@ void VertexLoader::LoadVertex(u32 base_address, int index, int vertex, | |||
| 85 | memory_accesses.AddAccess( | 85 | memory_accesses.AddAccess( |
| 86 | source_addr, | 86 | source_addr, |
| 87 | vertex_attribute_elements[i] * | 87 | vertex_attribute_elements[i] * |
| 88 | ((vertex_attribute_formats[i] == Regs::VertexAttributeFormat::FLOAT) | 88 | ((vertex_attribute_formats[i] == PipelineRegs::VertexAttributeFormat::FLOAT) |
| 89 | ? 4 | 89 | ? 4 |
| 90 | : (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::SHORT) | 90 | : (vertex_attribute_formats[i] == |
| 91 | PipelineRegs::VertexAttributeFormat::SHORT) | ||
| 91 | ? 2 | 92 | ? 2 |
| 92 | : 1)); | 93 | : 1)); |
| 93 | } | 94 | } |
| 94 | 95 | ||
| 95 | switch (vertex_attribute_formats[i]) { | 96 | switch (vertex_attribute_formats[i]) { |
| 96 | case Regs::VertexAttributeFormat::BYTE: { | 97 | case PipelineRegs::VertexAttributeFormat::BYTE: { |
| 97 | const s8* srcdata = | 98 | const s8* srcdata = |
| 98 | reinterpret_cast<const s8*>(Memory::GetPhysicalPointer(source_addr)); | 99 | reinterpret_cast<const s8*>(Memory::GetPhysicalPointer(source_addr)); |
| 99 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { | 100 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { |
| @@ -101,7 +102,7 @@ void VertexLoader::LoadVertex(u32 base_address, int index, int vertex, | |||
| 101 | } | 102 | } |
| 102 | break; | 103 | break; |
| 103 | } | 104 | } |
| 104 | case Regs::VertexAttributeFormat::UBYTE: { | 105 | case PipelineRegs::VertexAttributeFormat::UBYTE: { |
| 105 | const u8* srcdata = | 106 | const u8* srcdata = |
| 106 | reinterpret_cast<const u8*>(Memory::GetPhysicalPointer(source_addr)); | 107 | reinterpret_cast<const u8*>(Memory::GetPhysicalPointer(source_addr)); |
| 107 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { | 108 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { |
| @@ -109,7 +110,7 @@ void VertexLoader::LoadVertex(u32 base_address, int index, int vertex, | |||
| 109 | } | 110 | } |
| 110 | break; | 111 | break; |
| 111 | } | 112 | } |
| 112 | case Regs::VertexAttributeFormat::SHORT: { | 113 | case PipelineRegs::VertexAttributeFormat::SHORT: { |
| 113 | const s16* srcdata = | 114 | const s16* srcdata = |
| 114 | reinterpret_cast<const s16*>(Memory::GetPhysicalPointer(source_addr)); | 115 | reinterpret_cast<const s16*>(Memory::GetPhysicalPointer(source_addr)); |
| 115 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { | 116 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { |
| @@ -117,7 +118,7 @@ void VertexLoader::LoadVertex(u32 base_address, int index, int vertex, | |||
| 117 | } | 118 | } |
| 118 | break; | 119 | break; |
| 119 | } | 120 | } |
| 120 | case Regs::VertexAttributeFormat::FLOAT: { | 121 | case PipelineRegs::VertexAttributeFormat::FLOAT: { |
| 121 | const float* srcdata = | 122 | const float* srcdata = |
| 122 | reinterpret_cast<const float*>(Memory::GetPhysicalPointer(source_addr)); | 123 | reinterpret_cast<const float*>(Memory::GetPhysicalPointer(source_addr)); |
| 123 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { | 124 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { |
diff --git a/src/video_core/vertex_loader.h b/src/video_core/vertex_loader.h index 51f3d45b4..02db10aee 100644 --- a/src/video_core/vertex_loader.h +++ b/src/video_core/vertex_loader.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | #include <array> | 3 | #include <array> |
| 4 | #include "common/common_types.h" | 4 | #include "common/common_types.h" |
| 5 | #include "video_core/pica.h" | 5 | #include "video_core/regs_pipeline.h" |
| 6 | 6 | ||
| 7 | namespace Pica { | 7 | namespace Pica { |
| 8 | 8 | ||
| @@ -17,11 +17,11 @@ struct AttributeBuffer; | |||
| 17 | class VertexLoader { | 17 | class VertexLoader { |
| 18 | public: | 18 | public: |
| 19 | VertexLoader() = default; | 19 | VertexLoader() = default; |
| 20 | explicit VertexLoader(const Pica::Regs& regs) { | 20 | explicit VertexLoader(const PipelineRegs& regs) { |
| 21 | Setup(regs); | 21 | Setup(regs); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | void Setup(const Pica::Regs& regs); | 24 | void Setup(const PipelineRegs& regs); |
| 25 | void LoadVertex(u32 base_address, int index, int vertex, Shader::AttributeBuffer& input, | 25 | void LoadVertex(u32 base_address, int index, int vertex, Shader::AttributeBuffer& input, |
| 26 | DebugUtils::MemoryAccessTracker& memory_accesses); | 26 | DebugUtils::MemoryAccessTracker& memory_accesses); |
| 27 | 27 | ||
| @@ -32,7 +32,7 @@ public: | |||
| 32 | private: | 32 | private: |
| 33 | std::array<u32, 16> vertex_attribute_sources; | 33 | std::array<u32, 16> vertex_attribute_sources; |
| 34 | std::array<u32, 16> vertex_attribute_strides{}; | 34 | std::array<u32, 16> vertex_attribute_strides{}; |
| 35 | std::array<Regs::VertexAttributeFormat, 16> vertex_attribute_formats; | 35 | std::array<PipelineRegs::VertexAttributeFormat, 16> vertex_attribute_formats; |
| 36 | std::array<u32, 16> vertex_attribute_elements{}; | 36 | std::array<u32, 16> vertex_attribute_elements{}; |
| 37 | std::array<bool, 16> vertex_attribute_is_default; | 37 | std::array<bool, 16> vertex_attribute_is_default; |
| 38 | int num_total_attributes = 0; | 38 | int num_total_attributes = 0; |