diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp index ee79f0edf..adaa18cfc 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp @@ -123,15 +123,16 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); - if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || - COMMAND_IN_RANGE(command_id, texture2)) { + if (COMMAND_IN_RANGE(command_id, texturing.texture0) || + COMMAND_IN_RANGE(command_id, texturing.texture1) || + COMMAND_IN_RANGE(command_id, texturing.texture2)) { unsigned texture_index; - if (COMMAND_IN_RANGE(command_id, texture0)) { + if (COMMAND_IN_RANGE(command_id, texturing.texture0)) { texture_index = 0; - } else if (COMMAND_IN_RANGE(command_id, texture1)) { + } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) { texture_index = 1; - } else if (COMMAND_IN_RANGE(command_id, texture2)) { + } else if (COMMAND_IN_RANGE(command_id, texturing.texture2)) { texture_index = 2; } else { UNREACHABLE_MSG("Unknown texture command"); @@ -146,19 +147,20 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); - if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || - COMMAND_IN_RANGE(command_id, texture2)) { + if (COMMAND_IN_RANGE(command_id, texturing.texture0) || + COMMAND_IN_RANGE(command_id, texturing.texture1) || + COMMAND_IN_RANGE(command_id, texturing.texture2)) { unsigned texture_index; - if (COMMAND_IN_RANGE(command_id, texture0)) { + if (COMMAND_IN_RANGE(command_id, texturing.texture0)) { texture_index = 0; - } else if (COMMAND_IN_RANGE(command_id, texture1)) { + } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) { texture_index = 1; } else { texture_index = 2; } - const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; + const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index]; const auto config = texture.config; const auto format = texture.format; diff --git a/src/citra_qt/debugger/graphics/graphics_surface.cpp b/src/citra_qt/debugger/graphics/graphics_surface.cpp index bd82b00d4..406a49f42 100644 --- a/src/citra_qt/debugger/graphics/graphics_surface.cpp +++ b/src/citra_qt/debugger/graphics/graphics_surface.cpp @@ -512,7 +512,7 @@ void GraphicsSurfaceWidget::OnUpdate() { break; } - const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; + const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index]; auto info = Pica::Texture::TextureInfo::FromPicaRegister(texture.config, texture.format); surface_address = info.physical_address; @@ -574,7 +574,7 @@ void GraphicsSurfaceWidget::OnUpdate() { info.physical_address = surface_address; info.width = surface_width; info.height = surface_height; - info.format = static_cast(surface_format); + info.format = static_cast(surface_format); info.SetDefaultStride(); for (unsigned int y = 0; y < surface_height; ++y) { @@ -689,7 +689,8 @@ void GraphicsSurfaceWidget::SaveSurface() { unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) { if (format <= Format::MaxTextureFormat) { - return Pica::Regs::NibblesPerPixel(static_cast(format)); + return Pica::TexturingRegs::NibblesPerPixel( + static_cast(format)); } switch (format) { diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 522d7cc13..c0358fc20 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -33,6 +33,7 @@ set(HEADERS rasterizer.h rasterizer_interface.h regs_rasterizer.h + regs_texturing.h renderer_base.h renderer_opengl/gl_rasterizer.h renderer_opengl/gl_rasterizer_cache.h diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index b4a9f23cf..fa3432f60 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -225,13 +225,13 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { if (g_debug_context && g_debug_context->recorder) { for (int i = 0; i < 3; ++i) { - const auto texture = regs.GetTextures()[i]; + const auto texture = regs.texturing.GetTextures()[i]; if (!texture.enabled) continue; u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); g_debug_context->recorder->MemoryAccessed( - texture_data, Pica::Regs::NibblesPerPixel(texture.format) * + texture_data, Pica::TexturingRegs::NibblesPerPixel(texture.format) * texture.config.width / 2 * texture.config.height, texture.config.GetPhysicalAddress()); } @@ -438,16 +438,16 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { break; } - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef): { - g_state.fog.lut[regs.fog_lut_offset % 128].raw = value; - regs.fog_lut_offset.Assign(regs.fog_lut_offset + 1); + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef): { + g_state.fog.lut[regs.texturing.fog_lut_offset % 128].raw = value; + regs.texturing.fog_lut_offset.Assign(regs.texturing.fog_lut_offset + 1); break; } diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 618268654..81cd35cd9 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp @@ -331,7 +331,7 @@ static void FlushIOFile(png_structp png_ptr) { } #endif -void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { +void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data) { #ifndef HAVE_PNG return; #else @@ -396,7 +396,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { info.width = texture_config.width; info.height = texture_config.height; info.stride = row_stride; - info.format = g_state.regs.texture0_format; + info.format = g_state.regs.texturing.texture0_format; Math::Vec4 texture_color = Pica::Texture::LookupTexture(data, x, y, info); buf[3 * x + y * row_stride] = texture_color.r(); 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 return ret; } -static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfig::Source& source) { - using Source = Pica::Regs::TevStageConfig::Source; +static std::string GetTevStageConfigSourceString( + const TexturingRegs::TevStageConfig::Source& source) { + + using Source = TexturingRegs::TevStageConfig::Source; static const std::map source_map = { {Source::PrimaryColor, "PrimaryColor"}, {Source::PrimaryFragmentColor, "PrimaryFragmentColor"}, @@ -457,9 +459,10 @@ static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfi } static std::string GetTevStageConfigColorSourceString( - const Pica::Regs::TevStageConfig::Source& source, - const Pica::Regs::TevStageConfig::ColorModifier modifier) { - using ColorModifier = Pica::Regs::TevStageConfig::ColorModifier; + const TexturingRegs::TevStageConfig::Source& source, + const TexturingRegs::TevStageConfig::ColorModifier modifier) { + + using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier; static const std::map color_modifier_map = { {ColorModifier::SourceColor, "%source.rgb"}, {ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"}, @@ -483,9 +486,10 @@ static std::string GetTevStageConfigColorSourceString( } static std::string GetTevStageConfigAlphaSourceString( - const Pica::Regs::TevStageConfig::Source& source, - const Pica::Regs::TevStageConfig::AlphaModifier modifier) { - using AlphaModifier = Pica::Regs::TevStageConfig::AlphaModifier; + const TexturingRegs::TevStageConfig::Source& source, + const TexturingRegs::TevStageConfig::AlphaModifier modifier) { + + using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier; static const std::map alpha_modifier_map = { {AlphaModifier::SourceAlpha, "%source.a"}, {AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"}, @@ -507,8 +511,9 @@ static std::string GetTevStageConfigAlphaSourceString( } static std::string GetTevStageConfigOperationString( - const Pica::Regs::TevStageConfig::Operation& operation) { - using Operation = Pica::Regs::TevStageConfig::Operation; + const TexturingRegs::TevStageConfig::Operation& operation) { + + using Operation = TexturingRegs::TevStageConfig::Operation; static const std::map combiner_map = { {Operation::Replace, "%source1"}, {Operation::Modulate, "(%source1 * %source2)"}, @@ -528,7 +533,7 @@ static std::string GetTevStageConfigOperationString( return op_it->second; } -std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage) { +std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage) { auto op_str = GetTevStageConfigOperationString(tev_stage.color_op); op_str = ReplacePattern( op_str, "%source1", @@ -541,7 +546,7 @@ std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfi GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3)); } -std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage) { +std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage) { auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op); op_str = ReplacePattern( op_str, "%source1", @@ -554,7 +559,7 @@ std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfi GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3)); } -void DumpTevStageConfig(const std::array& stages) { +void DumpTevStageConfig(const std::array& stages) { std::string stage_info = "Tev setup:\n"; for (size_t index = 0; index < stages.size(); ++index) { 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 51270bc9c..e58b76d41 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h @@ -205,13 +205,13 @@ inline bool IsPicaTracing() { void OnPicaRegWrite(PicaTrace::Write write); std::unique_ptr FinishPicaTracing(); -void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data); +void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data); -std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage); -std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage); +std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage); +std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage); /// Dumps the Tev stage config to log at trace level -void DumpTevStageConfig(const std::array& stages); +void DumpTevStageConfig(const std::array& stages); /** * Used in the vertex loader to merge access records. TODO: Investigate if actually useful. diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 9d7262b43..71194198a 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -19,6 +19,7 @@ #include "common/logging/log.h" #include "common/vector_math.h" #include "video_core/regs_rasterizer.h" +#include "video_core/regs_texturing.h" namespace Pica { @@ -49,81 +50,7 @@ struct Regs { u32 trigger_irq; INSERT_PADDING_WORDS(0x2f); RasterizerRegs rasterizer; - - struct TextureConfig { - enum TextureType : u32 { - Texture2D = 0, - TextureCube = 1, - Shadow2D = 2, - Projection2D = 3, - ShadowCube = 4, - Disabled = 5, - }; - - enum WrapMode : u32 { - ClampToEdge = 0, - ClampToBorder = 1, - Repeat = 2, - MirroredRepeat = 3, - }; - - enum TextureFilter : u32 { - Nearest = 0, - Linear = 1, - }; - - union { - u32 raw; - BitField<0, 8, u32> r; - BitField<8, 8, u32> g; - BitField<16, 8, u32> b; - BitField<24, 8, u32> a; - } border_color; - - union { - BitField<0, 16, u32> height; - BitField<16, 16, u32> width; - }; - - union { - BitField<1, 1, TextureFilter> mag_filter; - BitField<2, 1, TextureFilter> min_filter; - BitField<8, 2, WrapMode> wrap_t; - BitField<12, 2, WrapMode> wrap_s; - BitField<28, 2, TextureType> - type; ///< @note Only valid for texture 0 according to 3DBrew. - }; - - INSERT_PADDING_WORDS(0x1); - - u32 address; - - u32 GetPhysicalAddress() const { - return DecodeAddressRegister(address); - } - - // texture1 and texture2 store the texture format directly after the address - // whereas texture0 inserts some additional flags inbetween. - // Hence, we store the format separately so that all other parameters can be described - // in a single structure. - }; - - enum class TextureFormat : u32 { - RGBA8 = 0, - RGB8 = 1, - RGB5A1 = 2, - RGB565 = 3, - RGBA4 = 4, - IA8 = 5, - RG8 = 6, ///< @note Also called HILO8 in 3DBrew. - I8 = 7, - A8 = 8, - IA4 = 9, - I4 = 10, - A4 = 11, - ETC1 = 12, // compressed - ETC1A4 = 13, // compressed - }; + TexturingRegs texturing; enum class LogicOp : u32 { Clear = 0, @@ -144,239 +71,6 @@ struct Regs { OrInverted = 15, }; - static unsigned NibblesPerPixel(TextureFormat format) { - switch (format) { - case TextureFormat::RGBA8: - return 8; - - case TextureFormat::RGB8: - return 6; - - case TextureFormat::RGB5A1: - case TextureFormat::RGB565: - case TextureFormat::RGBA4: - case TextureFormat::IA8: - case TextureFormat::RG8: - return 4; - - case TextureFormat::I4: - case TextureFormat::A4: - return 1; - - case TextureFormat::I8: - case TextureFormat::A8: - case TextureFormat::IA4: - return 2; - - default: // placeholder for yet unknown formats - UNIMPLEMENTED(); - return 0; - } - } - - union { - BitField<0, 1, u32> texture0_enable; - BitField<1, 1, u32> texture1_enable; - BitField<2, 1, u32> texture2_enable; - }; - TextureConfig texture0; - INSERT_PADDING_WORDS(0x8); - BitField<0, 4, TextureFormat> texture0_format; - BitField<0, 1, u32> fragment_lighting_enable; - INSERT_PADDING_WORDS(0x1); - TextureConfig texture1; - BitField<0, 4, TextureFormat> texture1_format; - INSERT_PADDING_WORDS(0x2); - TextureConfig texture2; - BitField<0, 4, TextureFormat> texture2_format; - INSERT_PADDING_WORDS(0x21); - - struct FullTextureConfig { - const bool enabled; - const TextureConfig config; - const TextureFormat format; - }; - const std::array GetTextures() const { - return {{ - {texture0_enable.ToBool(), texture0, texture0_format}, - {texture1_enable.ToBool(), texture1, texture1_format}, - {texture2_enable.ToBool(), texture2, texture2_format}, - }}; - } - - // 0xc0-0xff: Texture Combiner (akin to glTexEnv) - struct TevStageConfig { - enum class Source : u32 { - PrimaryColor = 0x0, - PrimaryFragmentColor = 0x1, - SecondaryFragmentColor = 0x2, - - Texture0 = 0x3, - Texture1 = 0x4, - Texture2 = 0x5, - Texture3 = 0x6, - - PreviousBuffer = 0xd, - Constant = 0xe, - Previous = 0xf, - }; - - enum class ColorModifier : u32 { - SourceColor = 0x0, - OneMinusSourceColor = 0x1, - SourceAlpha = 0x2, - OneMinusSourceAlpha = 0x3, - SourceRed = 0x4, - OneMinusSourceRed = 0x5, - - SourceGreen = 0x8, - OneMinusSourceGreen = 0x9, - - SourceBlue = 0xc, - OneMinusSourceBlue = 0xd, - }; - - enum class AlphaModifier : u32 { - SourceAlpha = 0x0, - OneMinusSourceAlpha = 0x1, - SourceRed = 0x2, - OneMinusSourceRed = 0x3, - SourceGreen = 0x4, - OneMinusSourceGreen = 0x5, - SourceBlue = 0x6, - OneMinusSourceBlue = 0x7, - }; - - enum class Operation : u32 { - Replace = 0, - Modulate = 1, - Add = 2, - AddSigned = 3, - Lerp = 4, - Subtract = 5, - Dot3_RGB = 6, - - MultiplyThenAdd = 8, - AddThenMultiply = 9, - }; - - union { - u32 sources_raw; - BitField<0, 4, Source> color_source1; - BitField<4, 4, Source> color_source2; - BitField<8, 4, Source> color_source3; - BitField<16, 4, Source> alpha_source1; - BitField<20, 4, Source> alpha_source2; - BitField<24, 4, Source> alpha_source3; - }; - - union { - u32 modifiers_raw; - BitField<0, 4, ColorModifier> color_modifier1; - BitField<4, 4, ColorModifier> color_modifier2; - BitField<8, 4, ColorModifier> color_modifier3; - BitField<12, 3, AlphaModifier> alpha_modifier1; - BitField<16, 3, AlphaModifier> alpha_modifier2; - BitField<20, 3, AlphaModifier> alpha_modifier3; - }; - - union { - u32 ops_raw; - BitField<0, 4, Operation> color_op; - BitField<16, 4, Operation> alpha_op; - }; - - union { - u32 const_color; - BitField<0, 8, u32> const_r; - BitField<8, 8, u32> const_g; - BitField<16, 8, u32> const_b; - BitField<24, 8, u32> const_a; - }; - - union { - u32 scales_raw; - BitField<0, 2, u32> color_scale; - BitField<16, 2, u32> alpha_scale; - }; - - inline unsigned GetColorMultiplier() const { - return (color_scale < 3) ? (1 << color_scale) : 1; - } - - inline unsigned GetAlphaMultiplier() const { - return (alpha_scale < 3) ? (1 << alpha_scale) : 1; - } - }; - - TevStageConfig tev_stage0; - INSERT_PADDING_WORDS(0x3); - TevStageConfig tev_stage1; - INSERT_PADDING_WORDS(0x3); - TevStageConfig tev_stage2; - INSERT_PADDING_WORDS(0x3); - TevStageConfig tev_stage3; - INSERT_PADDING_WORDS(0x3); - - enum class FogMode : u32 { - None = 0, - Fog = 5, - Gas = 7, - }; - - union { - BitField<0, 3, FogMode> fog_mode; - BitField<16, 1, u32> fog_flip; - - union { - // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in - // these masks are set - BitField<8, 4, u32> update_mask_rgb; - BitField<12, 4, u32> update_mask_a; - - bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { - return (stage_index < 4) && (update_mask_rgb & (1 << stage_index)); - } - - bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const { - return (stage_index < 4) && (update_mask_a & (1 << stage_index)); - } - } tev_combiner_buffer_input; - }; - - union { - u32 raw; - BitField<0, 8, u32> r; - BitField<8, 8, u32> g; - BitField<16, 8, u32> b; - } fog_color; - - INSERT_PADDING_WORDS(0x4); - - BitField<0, 16, u32> fog_lut_offset; - - INSERT_PADDING_WORDS(0x1); - - u32 fog_lut_data[8]; - - TevStageConfig tev_stage4; - INSERT_PADDING_WORDS(0x3); - TevStageConfig tev_stage5; - - union { - u32 raw; - BitField<0, 8, u32> r; - BitField<8, 8, u32> g; - BitField<16, 8, u32> b; - BitField<24, 8, u32> a; - } tev_combiner_buffer_color; - - INSERT_PADDING_WORDS(0x2); - - const std::array GetTevStages() const { - return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}}; - }; - enum class BlendEquation : u32 { Add = 0, Subtract = 1, @@ -1241,26 +935,28 @@ ASSERT_REG_POSITION(rasterizer.scissor_test, 0x65); ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68); ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D); -ASSERT_REG_POSITION(texture0_enable, 0x80); -ASSERT_REG_POSITION(texture0, 0x81); -ASSERT_REG_POSITION(texture0_format, 0x8e); -ASSERT_REG_POSITION(fragment_lighting_enable, 0x8f); -ASSERT_REG_POSITION(texture1, 0x91); -ASSERT_REG_POSITION(texture1_format, 0x96); -ASSERT_REG_POSITION(texture2, 0x99); -ASSERT_REG_POSITION(texture2_format, 0x9e); -ASSERT_REG_POSITION(tev_stage0, 0xc0); -ASSERT_REG_POSITION(tev_stage1, 0xc8); -ASSERT_REG_POSITION(tev_stage2, 0xd0); -ASSERT_REG_POSITION(tev_stage3, 0xd8); -ASSERT_REG_POSITION(tev_combiner_buffer_input, 0xe0); -ASSERT_REG_POSITION(fog_mode, 0xe0); -ASSERT_REG_POSITION(fog_color, 0xe1); -ASSERT_REG_POSITION(fog_lut_offset, 0xe6); -ASSERT_REG_POSITION(fog_lut_data, 0xe8); -ASSERT_REG_POSITION(tev_stage4, 0xf0); -ASSERT_REG_POSITION(tev_stage5, 0xf8); -ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd); +ASSERT_REG_POSITION(texturing, 0x80); +ASSERT_REG_POSITION(texturing.texture0_enable, 0x80); +ASSERT_REG_POSITION(texturing.texture0, 0x81); +ASSERT_REG_POSITION(texturing.texture0_format, 0x8e); +ASSERT_REG_POSITION(texturing.fragment_lighting_enable, 0x8f); +ASSERT_REG_POSITION(texturing.texture1, 0x91); +ASSERT_REG_POSITION(texturing.texture1_format, 0x96); +ASSERT_REG_POSITION(texturing.texture2, 0x99); +ASSERT_REG_POSITION(texturing.texture2_format, 0x9e); +ASSERT_REG_POSITION(texturing.tev_stage0, 0xc0); +ASSERT_REG_POSITION(texturing.tev_stage1, 0xc8); +ASSERT_REG_POSITION(texturing.tev_stage2, 0xd0); +ASSERT_REG_POSITION(texturing.tev_stage3, 0xd8); +ASSERT_REG_POSITION(texturing.tev_combiner_buffer_input, 0xe0); +ASSERT_REG_POSITION(texturing.fog_mode, 0xe0); +ASSERT_REG_POSITION(texturing.fog_color, 0xe1); +ASSERT_REG_POSITION(texturing.fog_lut_offset, 0xe6); +ASSERT_REG_POSITION(texturing.fog_lut_data, 0xe8); +ASSERT_REG_POSITION(texturing.tev_stage4, 0xf0); +ASSERT_REG_POSITION(texturing.tev_stage5, 0xf8); +ASSERT_REG_POSITION(texturing.tev_combiner_buffer_color, 0xfd); + ASSERT_REG_POSITION(output_merger, 0x100); ASSERT_REG_POSITION(framebuffer, 0x110); ASSERT_REG_POSITION(lighting, 0x140); diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index f82873480..48bc26571 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -397,8 +397,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); - auto textures = regs.GetTextures(); - auto tev_stages = regs.GetTevStages(); + auto textures = regs.texturing.GetTextures(); + auto tev_stages = regs.texturing.GetTevStages(); bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable && g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8; @@ -515,9 +515,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve // TODO: Refactor so cubemaps and shadowmaps can be handled if (i == 0) { switch (texture.config.type) { - case Regs::TextureConfig::Texture2D: + case TexturingRegs::TextureConfig::Texture2D: break; - case Regs::TextureConfig::Projection2D: { + case TexturingRegs::TextureConfig::Projection2D: { auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); u /= tc0_w; v /= tc0_w; @@ -536,21 +536,21 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve int t = (int)(v * float24::FromFloat32(static_cast(texture.config.height))) .ToFloat32(); - static auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, - unsigned size) { + static auto GetWrappedTexCoord = [](TexturingRegs::TextureConfig::WrapMode mode, + int val, unsigned size) { switch (mode) { - case Regs::TextureConfig::ClampToEdge: + case TexturingRegs::TextureConfig::ClampToEdge: val = std::max(val, 0); val = std::min(val, (int)size - 1); return val; - case Regs::TextureConfig::ClampToBorder: + case TexturingRegs::TextureConfig::ClampToBorder: return val; - case Regs::TextureConfig::Repeat: + case TexturingRegs::TextureConfig::Repeat: return (int)((unsigned)val % size); - case Regs::TextureConfig::MirroredRepeat: { + case TexturingRegs::TextureConfig::MirroredRepeat: { unsigned int coord = ((unsigned)val % (2 * size)); if (coord >= size) coord = 2 * size - 1 - coord; @@ -564,9 +564,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve } }; - if ((texture.config.wrap_s == Regs::TextureConfig::ClampToBorder && + if ((texture.config.wrap_s == TexturingRegs::TextureConfig::ClampToBorder && (s < 0 || static_cast(s) >= texture.config.width)) || - (texture.config.wrap_t == Regs::TextureConfig::ClampToBorder && + (texture.config.wrap_t == TexturingRegs::TextureConfig::ClampToBorder && (t < 0 || static_cast(t) >= texture.config.height))) { auto border_color = texture.config.border_color; texture_color[i] = {border_color.r, border_color.g, border_color.b, @@ -602,17 +602,19 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve Math::Vec4 combiner_output; Math::Vec4 combiner_buffer = {0, 0, 0, 0}; Math::Vec4 next_combiner_buffer = { - regs.tev_combiner_buffer_color.r, regs.tev_combiner_buffer_color.g, - regs.tev_combiner_buffer_color.b, regs.tev_combiner_buffer_color.a, + regs.texturing.tev_combiner_buffer_color.r, + regs.texturing.tev_combiner_buffer_color.g, + regs.texturing.tev_combiner_buffer_color.b, + regs.texturing.tev_combiner_buffer_color.a, }; for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) { const auto& tev_stage = tev_stages[tev_stage_index]; - using Source = Regs::TevStageConfig::Source; - using ColorModifier = Regs::TevStageConfig::ColorModifier; - using AlphaModifier = Regs::TevStageConfig::AlphaModifier; - using Operation = Regs::TevStageConfig::Operation; + using Source = TexturingRegs::TevStageConfig::Source; + using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier; + using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier; + using Operation = TexturingRegs::TevStageConfig::Operation; auto GetSource = [&](Source source) -> Math::Vec4 { switch (source) { @@ -864,14 +866,14 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve combiner_buffer = next_combiner_buffer; - if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor( + if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor( tev_stage_index)) { next_combiner_buffer.r() = combiner_output.r(); next_combiner_buffer.g() = combiner_output.g(); next_combiner_buffer.b() = combiner_output.b(); } - if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha( + if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha( tev_stage_index)) { next_combiner_buffer.a() = combiner_output.a(); } @@ -924,16 +926,16 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve // Not fully accurate. We'd have to know what data type is used to // store the depth etc. Using float for now until we know more // about Pica datatypes - if (regs.fog_mode == Regs::FogMode::Fog) { + if (regs.texturing.fog_mode == TexturingRegs::FogMode::Fog) { const Math::Vec3 fog_color = { - static_cast(regs.fog_color.r.Value()), - static_cast(regs.fog_color.g.Value()), - static_cast(regs.fog_color.b.Value()), + static_cast(regs.texturing.fog_color.r.Value()), + static_cast(regs.texturing.fog_color.g.Value()), + static_cast(regs.texturing.fog_color.b.Value()), }; // Get index into fog LUT float fog_index; - if (g_state.regs.fog_flip) { + if (g_state.regs.texturing.fog_flip) { fog_index = (1.0f - depth) * 128.0f; } else { fog_index = depth * 128.0f; 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 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/assert.h" +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" + +namespace Pica { + +struct TexturingRegs { + struct TextureConfig { + enum TextureType : u32 { + Texture2D = 0, + TextureCube = 1, + Shadow2D = 2, + Projection2D = 3, + ShadowCube = 4, + Disabled = 5, + }; + + enum WrapMode : u32 { + ClampToEdge = 0, + ClampToBorder = 1, + Repeat = 2, + MirroredRepeat = 3, + }; + + enum TextureFilter : u32 { + Nearest = 0, + Linear = 1, + }; + + union { + u32 raw; + BitField<0, 8, u32> r; + BitField<8, 8, u32> g; + BitField<16, 8, u32> b; + BitField<24, 8, u32> a; + } border_color; + + union { + BitField<0, 16, u32> height; + BitField<16, 16, u32> width; + }; + + union { + BitField<1, 1, TextureFilter> mag_filter; + BitField<2, 1, TextureFilter> min_filter; + BitField<8, 2, WrapMode> wrap_t; + BitField<12, 2, WrapMode> wrap_s; + BitField<28, 2, TextureType> + type; ///< @note Only valid for texture 0 according to 3DBrew. + }; + + INSERT_PADDING_WORDS(0x1); + + u32 address; + + PAddr GetPhysicalAddress() const { + return address * 8; + } + + // texture1 and texture2 store the texture format directly after the address + // whereas texture0 inserts some additional flags inbetween. + // Hence, we store the format separately so that all other parameters can be described + // in a single structure. + }; + + enum class TextureFormat : u32 { + RGBA8 = 0, + RGB8 = 1, + RGB5A1 = 2, + RGB565 = 3, + RGBA4 = 4, + IA8 = 5, + RG8 = 6, ///< @note Also called HILO8 in 3DBrew. + I8 = 7, + A8 = 8, + IA4 = 9, + I4 = 10, + A4 = 11, + ETC1 = 12, // compressed + ETC1A4 = 13, // compressed + }; + + static unsigned NibblesPerPixel(TextureFormat format) { + switch (format) { + case TextureFormat::RGBA8: + return 8; + + case TextureFormat::RGB8: + return 6; + + case TextureFormat::RGB5A1: + case TextureFormat::RGB565: + case TextureFormat::RGBA4: + case TextureFormat::IA8: + case TextureFormat::RG8: + return 4; + + case TextureFormat::I4: + case TextureFormat::A4: + return 1; + + case TextureFormat::I8: + case TextureFormat::A8: + case TextureFormat::IA4: + + default: // placeholder for yet unknown formats + UNIMPLEMENTED(); + return 0; + } + } + + union { + BitField<0, 1, u32> texture0_enable; + BitField<1, 1, u32> texture1_enable; + BitField<2, 1, u32> texture2_enable; + }; + TextureConfig texture0; + INSERT_PADDING_WORDS(0x8); + BitField<0, 4, TextureFormat> texture0_format; + BitField<0, 1, u32> fragment_lighting_enable; + INSERT_PADDING_WORDS(0x1); + TextureConfig texture1; + BitField<0, 4, TextureFormat> texture1_format; + INSERT_PADDING_WORDS(0x2); + TextureConfig texture2; + BitField<0, 4, TextureFormat> texture2_format; + INSERT_PADDING_WORDS(0x21); + + struct FullTextureConfig { + const bool enabled; + const TextureConfig config; + const TextureFormat format; + }; + const std::array GetTextures() const { + return {{ + {texture0_enable.ToBool(), texture0, texture0_format}, + {texture1_enable.ToBool(), texture1, texture1_format}, + {texture2_enable.ToBool(), texture2, texture2_format}, + }}; + } + + // 0xc0-0xff: Texture Combiner (akin to glTexEnv) + struct TevStageConfig { + enum class Source : u32 { + PrimaryColor = 0x0, + PrimaryFragmentColor = 0x1, + SecondaryFragmentColor = 0x2, + + Texture0 = 0x3, + Texture1 = 0x4, + Texture2 = 0x5, + Texture3 = 0x6, + + PreviousBuffer = 0xd, + Constant = 0xe, + Previous = 0xf, + }; + + enum class ColorModifier : u32 { + SourceColor = 0x0, + OneMinusSourceColor = 0x1, + SourceAlpha = 0x2, + OneMinusSourceAlpha = 0x3, + SourceRed = 0x4, + OneMinusSourceRed = 0x5, + + SourceGreen = 0x8, + OneMinusSourceGreen = 0x9, + + SourceBlue = 0xc, + OneMinusSourceBlue = 0xd, + }; + + enum class AlphaModifier : u32 { + SourceAlpha = 0x0, + OneMinusSourceAlpha = 0x1, + SourceRed = 0x2, + OneMinusSourceRed = 0x3, + SourceGreen = 0x4, + OneMinusSourceGreen = 0x5, + SourceBlue = 0x6, + OneMinusSourceBlue = 0x7, + }; + + enum class Operation : u32 { + Replace = 0, + Modulate = 1, + Add = 2, + AddSigned = 3, + Lerp = 4, + Subtract = 5, + Dot3_RGB = 6, + + MultiplyThenAdd = 8, + AddThenMultiply = 9, + }; + + union { + u32 sources_raw; + BitField<0, 4, Source> color_source1; + BitField<4, 4, Source> color_source2; + BitField<8, 4, Source> color_source3; + BitField<16, 4, Source> alpha_source1; + BitField<20, 4, Source> alpha_source2; + BitField<24, 4, Source> alpha_source3; + }; + + union { + u32 modifiers_raw; + BitField<0, 4, ColorModifier> color_modifier1; + BitField<4, 4, ColorModifier> color_modifier2; + BitField<8, 4, ColorModifier> color_modifier3; + BitField<12, 3, AlphaModifier> alpha_modifier1; + BitField<16, 3, AlphaModifier> alpha_modifier2; + BitField<20, 3, AlphaModifier> alpha_modifier3; + }; + + union { + u32 ops_raw; + BitField<0, 4, Operation> color_op; + BitField<16, 4, Operation> alpha_op; + }; + + union { + u32 const_color; + BitField<0, 8, u32> const_r; + BitField<8, 8, u32> const_g; + BitField<16, 8, u32> const_b; + BitField<24, 8, u32> const_a; + }; + + union { + u32 scales_raw; + BitField<0, 2, u32> color_scale; + BitField<16, 2, u32> alpha_scale; + }; + + inline unsigned GetColorMultiplier() const { + return (color_scale < 3) ? (1 << color_scale) : 1; + } + + inline unsigned GetAlphaMultiplier() const { + return (alpha_scale < 3) ? (1 << alpha_scale) : 1; + } + }; + + TevStageConfig tev_stage0; + INSERT_PADDING_WORDS(0x3); + TevStageConfig tev_stage1; + INSERT_PADDING_WORDS(0x3); + TevStageConfig tev_stage2; + INSERT_PADDING_WORDS(0x3); + TevStageConfig tev_stage3; + INSERT_PADDING_WORDS(0x3); + + enum class FogMode : u32 { + None = 0, + Fog = 5, + Gas = 7, + }; + + union { + BitField<0, 3, FogMode> fog_mode; + BitField<16, 1, u32> fog_flip; + + union { + // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in + // these masks are set + BitField<8, 4, u32> update_mask_rgb; + BitField<12, 4, u32> update_mask_a; + + bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { + return (stage_index < 4) && (update_mask_rgb & (1 << stage_index)); + } + + bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const { + return (stage_index < 4) && (update_mask_a & (1 << stage_index)); + } + } tev_combiner_buffer_input; + }; + + union { + u32 raw; + BitField<0, 8, u32> r; + BitField<8, 8, u32> g; + BitField<16, 8, u32> b; + } fog_color; + + INSERT_PADDING_WORDS(0x4); + + BitField<0, 16, u32> fog_lut_offset; + + INSERT_PADDING_WORDS(0x1); + + u32 fog_lut_data[8]; + + TevStageConfig tev_stage4; + INSERT_PADDING_WORDS(0x3); + TevStageConfig tev_stage5; + + union { + u32 raw; + BitField<0, 8, u32> r; + BitField<8, 8, u32> g; + BitField<16, 8, u32> b; + BitField<24, 8, u32> a; + } tev_combiner_buffer_color; + + INSERT_PADDING_WORDS(0x2); + + const std::array GetTevStages() const { + return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}}; + }; +}; + +static_assert(sizeof(TexturingRegs) == 0x80 * sizeof(u32), + "TexturingRegs struct has incorrect size"); + +} // namespace Pica diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c4061c005..f7eaa17e2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -26,13 +26,15 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); -static bool IsPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) { - return (stage.color_op == Pica::Regs::TevStageConfig::Operation::Replace && - stage.alpha_op == Pica::Regs::TevStageConfig::Operation::Replace && - stage.color_source1 == Pica::Regs::TevStageConfig::Source::Previous && - stage.alpha_source1 == Pica::Regs::TevStageConfig::Source::Previous && - stage.color_modifier1 == Pica::Regs::TevStageConfig::ColorModifier::SourceColor && - stage.alpha_modifier1 == Pica::Regs::TevStageConfig::AlphaModifier::SourceAlpha && +static bool IsPassThroughTevStage(const Pica::TexturingRegs::TevStageConfig& stage) { + using TevStageConfig = Pica::TexturingRegs::TevStageConfig; + + return (stage.color_op == TevStageConfig::Operation::Replace && + stage.alpha_op == TevStageConfig::Operation::Replace && + stage.color_source1 == TevStageConfig::Source::Previous && + stage.alpha_source1 == TevStageConfig::Source::Previous && + stage.color_modifier1 == TevStageConfig::ColorModifier::SourceColor && + stage.alpha_modifier1 == TevStageConfig::AlphaModifier::SourceAlpha && stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1); } @@ -242,7 +244,7 @@ void RasterizerOpenGL::DrawTriangles() { } // Sync and bind the texture surfaces - const auto pica_textures = regs.GetTextures(); + const auto pica_textures = regs.texturing.GetTextures(); for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) { const auto& texture = pica_textures[texture_index]; @@ -348,17 +350,17 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { break; // Fog state - case PICA_REG_INDEX(fog_color): + case PICA_REG_INDEX(texturing.fog_color): SyncFogColor(); break; - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee): - case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee): + case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef): uniform_block_data.fog_lut_dirty = true; break; @@ -411,60 +413,60 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { break; // Texture 0 type - case PICA_REG_INDEX(texture0.type): + case PICA_REG_INDEX(texturing.texture0.type): shader_dirty = true; break; // TEV stages // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input) - case PICA_REG_INDEX(tev_stage0.color_source1): - case PICA_REG_INDEX(tev_stage0.color_modifier1): - case PICA_REG_INDEX(tev_stage0.color_op): - case PICA_REG_INDEX(tev_stage0.color_scale): - case PICA_REG_INDEX(tev_stage1.color_source1): - case PICA_REG_INDEX(tev_stage1.color_modifier1): - case PICA_REG_INDEX(tev_stage1.color_op): - case PICA_REG_INDEX(tev_stage1.color_scale): - case PICA_REG_INDEX(tev_stage2.color_source1): - case PICA_REG_INDEX(tev_stage2.color_modifier1): - case PICA_REG_INDEX(tev_stage2.color_op): - case PICA_REG_INDEX(tev_stage2.color_scale): - case PICA_REG_INDEX(tev_stage3.color_source1): - case PICA_REG_INDEX(tev_stage3.color_modifier1): - case PICA_REG_INDEX(tev_stage3.color_op): - case PICA_REG_INDEX(tev_stage3.color_scale): - case PICA_REG_INDEX(tev_stage4.color_source1): - case PICA_REG_INDEX(tev_stage4.color_modifier1): - case PICA_REG_INDEX(tev_stage4.color_op): - case PICA_REG_INDEX(tev_stage4.color_scale): - case PICA_REG_INDEX(tev_stage5.color_source1): - case PICA_REG_INDEX(tev_stage5.color_modifier1): - case PICA_REG_INDEX(tev_stage5.color_op): - case PICA_REG_INDEX(tev_stage5.color_scale): - case PICA_REG_INDEX(tev_combiner_buffer_input): + case PICA_REG_INDEX(texturing.tev_stage0.color_source1): + case PICA_REG_INDEX(texturing.tev_stage0.color_modifier1): + case PICA_REG_INDEX(texturing.tev_stage0.color_op): + case PICA_REG_INDEX(texturing.tev_stage0.color_scale): + case PICA_REG_INDEX(texturing.tev_stage1.color_source1): + case PICA_REG_INDEX(texturing.tev_stage1.color_modifier1): + case PICA_REG_INDEX(texturing.tev_stage1.color_op): + case PICA_REG_INDEX(texturing.tev_stage1.color_scale): + case PICA_REG_INDEX(texturing.tev_stage2.color_source1): + case PICA_REG_INDEX(texturing.tev_stage2.color_modifier1): + case PICA_REG_INDEX(texturing.tev_stage2.color_op): + case PICA_REG_INDEX(texturing.tev_stage2.color_scale): + case PICA_REG_INDEX(texturing.tev_stage3.color_source1): + case PICA_REG_INDEX(texturing.tev_stage3.color_modifier1): + case PICA_REG_INDEX(texturing.tev_stage3.color_op): + case PICA_REG_INDEX(texturing.tev_stage3.color_scale): + case PICA_REG_INDEX(texturing.tev_stage4.color_source1): + case PICA_REG_INDEX(texturing.tev_stage4.color_modifier1): + case PICA_REG_INDEX(texturing.tev_stage4.color_op): + case PICA_REG_INDEX(texturing.tev_stage4.color_scale): + case PICA_REG_INDEX(texturing.tev_stage5.color_source1): + case PICA_REG_INDEX(texturing.tev_stage5.color_modifier1): + case PICA_REG_INDEX(texturing.tev_stage5.color_op): + case PICA_REG_INDEX(texturing.tev_stage5.color_scale): + case PICA_REG_INDEX(texturing.tev_combiner_buffer_input): shader_dirty = true; break; - case PICA_REG_INDEX(tev_stage0.const_r): - SyncTevConstColor(0, regs.tev_stage0); + case PICA_REG_INDEX(texturing.tev_stage0.const_r): + SyncTevConstColor(0, regs.texturing.tev_stage0); break; - case PICA_REG_INDEX(tev_stage1.const_r): - SyncTevConstColor(1, regs.tev_stage1); + case PICA_REG_INDEX(texturing.tev_stage1.const_r): + SyncTevConstColor(1, regs.texturing.tev_stage1); break; - case PICA_REG_INDEX(tev_stage2.const_r): - SyncTevConstColor(2, regs.tev_stage2); + case PICA_REG_INDEX(texturing.tev_stage2.const_r): + SyncTevConstColor(2, regs.texturing.tev_stage2); break; - case PICA_REG_INDEX(tev_stage3.const_r): - SyncTevConstColor(3, regs.tev_stage3); + case PICA_REG_INDEX(texturing.tev_stage3.const_r): + SyncTevConstColor(3, regs.texturing.tev_stage3); break; - case PICA_REG_INDEX(tev_stage4.const_r): - SyncTevConstColor(4, regs.tev_stage4); + case PICA_REG_INDEX(texturing.tev_stage4.const_r): + SyncTevConstColor(4, regs.texturing.tev_stage4); break; - case PICA_REG_INDEX(tev_stage5.const_r): - SyncTevConstColor(5, regs.tev_stage5); + case PICA_REG_INDEX(texturing.tev_stage5.const_r): + SyncTevConstColor(5, regs.texturing.tev_stage5); break; // TEV combiner buffer color - case PICA_REG_INDEX(tev_combiner_buffer_color): + case PICA_REG_INDEX(texturing.tev_combiner_buffer_color): SyncCombinerColor(); break; @@ -979,7 +981,9 @@ void RasterizerOpenGL::SamplerInfo::Create() { // Other attributes have correct defaults } -void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Pica::Regs::TextureConfig& config) { +void RasterizerOpenGL::SamplerInfo::SyncWithConfig( + const Pica::TexturingRegs::TextureConfig& config) { + GLuint s = sampler.handle; if (mag_filter != config.mag_filter) { @@ -1091,7 +1095,7 @@ void RasterizerOpenGL::SetShader() { SyncDepthOffset(); SyncAlphaTest(); SyncCombinerColor(); - auto& tev_stages = Pica::g_state.regs.GetTevStages(); + auto& tev_stages = Pica::g_state.regs.texturing.GetTevStages(); for (int index = 0; index < tev_stages.size(); ++index) SyncTevConstColor(index, tev_stages[index]); @@ -1182,8 +1186,8 @@ void RasterizerOpenGL::SyncBlendColor() { void RasterizerOpenGL::SyncFogColor() { const auto& regs = Pica::g_state.regs; uniform_block_data.data.fog_color = { - regs.fog_color.r.Value() / 255.0f, regs.fog_color.g.Value() / 255.0f, - regs.fog_color.b.Value() / 255.0f, + regs.texturing.fog_color.r.Value() / 255.0f, regs.texturing.fog_color.g.Value() / 255.0f, + regs.texturing.fog_color.b.Value() / 255.0f, }; uniform_block_data.dirty = true; } @@ -1267,7 +1271,8 @@ void RasterizerOpenGL::SyncDepthTest() { } void RasterizerOpenGL::SyncCombinerColor() { - auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw); + auto combiner_color = + PicaToGL::ColorRGBA8(Pica::g_state.regs.texturing.tev_combiner_buffer_color.raw); if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) { uniform_block_data.data.tev_combiner_buffer_color = combiner_color; uniform_block_data.dirty = true; @@ -1275,7 +1280,7 @@ void RasterizerOpenGL::SyncCombinerColor() { } void RasterizerOpenGL::SyncTevConstColor(int stage_index, - const Pica::Regs::TevStageConfig& tev_stage) { + const Pica::TexturingRegs::TevStageConfig& tev_stage) { auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color); if (const_color != uniform_block_data.data.const_color[stage_index]) { 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 bd7b6874a..519df6478 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -60,12 +60,12 @@ union PicaShaderConfig { ? regs.output_merger.alpha_test.func.Value() : Pica::Regs::CompareFunc::Always; - state.texture0_type = regs.texture0.type; + state.texture0_type = regs.texturing.texture0.type; // Copy relevant tev stages fields. // We don't sync const_color here because of the high variance, it is a // shader uniform instead. - const auto& tev_stages = regs.GetTevStages(); + const auto& tev_stages = regs.texturing.GetTevStages(); DEBUG_ASSERT(state.tev_stages.size() == tev_stages.size()); for (size_t i = 0; i < tev_stages.size(); i++) { const auto& tev_stage = tev_stages[i]; @@ -75,11 +75,12 @@ union PicaShaderConfig { state.tev_stages[i].scales_raw = tev_stage.scales_raw; } - state.fog_mode = regs.fog_mode; - state.fog_flip = regs.fog_flip != 0; + state.fog_mode = regs.texturing.fog_mode; + state.fog_flip = regs.texturing.fog_flip != 0; - state.combiner_buffer_input = regs.tev_combiner_buffer_input.update_mask_rgb.Value() | - regs.tev_combiner_buffer_input.update_mask_a.Value() << 4; + state.combiner_buffer_input = + regs.texturing.tev_combiner_buffer_input.update_mask_rgb.Value() | + regs.texturing.tev_combiner_buffer_input.update_mask_a.Value() << 4; // Fragment lighting @@ -159,8 +160,8 @@ union PicaShaderConfig { u32 modifiers_raw; u32 ops_raw; u32 scales_raw; - explicit operator Pica::Regs::TevStageConfig() const noexcept { - Pica::Regs::TevStageConfig stage; + explicit operator Pica::TexturingRegs::TevStageConfig() const noexcept { + Pica::TexturingRegs::TevStageConfig stage; stage.sources_raw = sources_raw; stage.modifiers_raw = modifiers_raw; stage.ops_raw = ops_raw; @@ -173,12 +174,12 @@ union PicaShaderConfig { struct State { Pica::Regs::CompareFunc alpha_test_func; Pica::RasterizerRegs::ScissorMode scissor_test_mode; - Pica::Regs::TextureConfig::TextureType texture0_type; + Pica::TexturingRegs::TextureConfig::TextureType texture0_type; std::array tev_stages; u8 combiner_buffer_input; Pica::RasterizerRegs::DepthBuffering depthmap_enable; - Pica::Regs::FogMode fog_mode; + Pica::TexturingRegs::FogMode fog_mode; bool fog_flip; struct { @@ -251,7 +252,7 @@ public: private: struct SamplerInfo { - using TextureConfig = Pica::Regs::TextureConfig; + using TextureConfig = Pica::TexturingRegs::TextureConfig; OGLSampler sampler; @@ -398,7 +399,7 @@ private: void SyncCombinerColor(); /// Syncs the TEV constant color to match the PICA register - void SyncTevConstColor(int tev_index, const Pica::Regs::TevStageConfig& tev_stage); + void SyncTevConstColor(int tev_index, const Pica::TexturingRegs::TevStageConfig& tev_stage); /// Syncs the lighting global ambient color to match the PICA register 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..6d08d1a67 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 Pica::Texture::TextureInfo tex_info; tex_info.width = params.width; tex_info.height = params.height; - tex_info.format = (Pica::Regs::TextureFormat)params.pixel_format; + tex_info.format = (Pica::TexturingRegs::TextureFormat)params.pixel_format; tex_info.SetDefaultStride(); tex_info.physical_address = params.addr; @@ -510,7 +510,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params } CachedSurface* RasterizerCacheOpenGL::GetTextureSurface( - const Pica::Regs::FullTextureConfig& config) { + const Pica::TexturingRegs::FullTextureConfig& config) { Pica::Texture::TextureInfo info = Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index f57fdb3cc..c354dfa33 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -96,7 +96,7 @@ struct CachedSurface { return bpp_table[(unsigned int)format]; } - static PixelFormat PixelFormatFromTextureFormat(Pica::Regs::TextureFormat format) { + static PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) { return ((unsigned int)format < 14) ? (PixelFormat)format : PixelFormat::Invalid; } @@ -212,7 +212,7 @@ public: bool load_if_create, MathUtil::Rectangle& out_rect); /// Gets a surface based on the texture configuration - CachedSurface* GetTextureSurface(const Pica::Regs::FullTextureConfig& config); + CachedSurface* GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config); /// Gets the color and depth surfaces and rect (resolution scaled) based on the framebuffer /// configuration diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index c34c3463f..c3b0fdcee 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -14,7 +14,7 @@ using Pica::Regs; using Pica::RasterizerRegs; -using TevStageConfig = Regs::TevStageConfig; +using TevStageConfig = Pica::TexturingRegs::TevStageConfig; namespace GLShader { @@ -47,10 +47,10 @@ static void AppendSource(std::string& out, const PicaShaderConfig& config, case Source::Texture0: // Only unit 0 respects the texturing type (according to 3DBrew) switch (state.texture0_type) { - case Pica::Regs::TextureConfig::Texture2D: + case Pica::TexturingRegs::TextureConfig::Texture2D: out += "texture(tex[0], texcoord[0])"; break; - case Pica::Regs::TextureConfig::Projection2D: + case Pica::TexturingRegs::TextureConfig::Projection2D: out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))"; break; default: @@ -308,7 +308,7 @@ static void AppendAlphaTestCondition(std::string& out, Regs::CompareFunc func) { /// Writes the code to emulate the specified TEV stage static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) { const auto stage = - static_cast(config.state.tev_stages[index]); + static_cast(config.state.tev_stages[index]); if (!IsPassThroughTevStage(stage)) { std::string index_name = std::to_string(index); @@ -674,7 +674,7 @@ vec4 secondary_fragment_color = vec4(0.0); } // Append fog combiner - if (state.fog_mode == Regs::FogMode::Fog) { + if (state.fog_mode == Pica::TexturingRegs::FogMode::Fog) { // Get index into fog LUT if (state.fog_flip) { 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..37cfbd45a 100644 --- a/src/video_core/renderer_opengl/pica_to_gl.h +++ b/src/video_core/renderer_opengl/pica_to_gl.h @@ -20,7 +20,7 @@ using GLvec4 = std::array; namespace PicaToGL { -inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) { +inline GLenum TextureFilterMode(Pica::TexturingRegs::TextureConfig::TextureFilter mode) { static const GLenum filter_mode_table[] = { GL_NEAREST, // TextureFilter::Nearest GL_LINEAR, // TextureFilter::Linear @@ -47,7 +47,7 @@ inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) { return gl_mode; } -inline GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) { +inline GLenum WrapMode(Pica::TexturingRegs::TextureConfig::WrapMode mode) { static const GLenum wrap_mode_table[] = { GL_CLAMP_TO_EDGE, // WrapMode::ClampToEdge GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder 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 @@ #include "common/math_util.h" #include "common/swap.h" #include "common/vector_math.h" -#include "video_core/pica.h" +#include "video_core/regs_texturing.h" #include "video_core/texture/etc1.h" #include "video_core/texture/texture_decode.h" #include "video_core/utils.h" -using TextureFormat = Pica::Regs::TextureFormat; +using TextureFormat = Pica::TexturingRegs::TextureFormat; namespace Pica { namespace Texture { @@ -82,32 +82,32 @@ Math::Vec4 LookupTexelInTile(const u8* source, unsigned int x, unsigned int using VideoCore::MortonInterleave; switch (info.format) { - case Regs::TextureFormat::RGBA8: { + case TextureFormat::RGBA8: { auto res = Color::DecodeRGBA8(source + MortonInterleave(x, y) * 4); return {res.r(), res.g(), res.b(), static_cast(disable_alpha ? 255 : res.a())}; } - case Regs::TextureFormat::RGB8: { + case TextureFormat::RGB8: { auto res = Color::DecodeRGB8(source + MortonInterleave(x, y) * 3); return {res.r(), res.g(), res.b(), 255}; } - case Regs::TextureFormat::RGB5A1: { + case TextureFormat::RGB5A1: { auto res = Color::DecodeRGB5A1(source + MortonInterleave(x, y) * 2); return {res.r(), res.g(), res.b(), static_cast(disable_alpha ? 255 : res.a())}; } - case Regs::TextureFormat::RGB565: { + case TextureFormat::RGB565: { auto res = Color::DecodeRGB565(source + MortonInterleave(x, y) * 2); return {res.r(), res.g(), res.b(), 255}; } - case Regs::TextureFormat::RGBA4: { + case TextureFormat::RGBA4: { auto res = Color::DecodeRGBA4(source + MortonInterleave(x, y) * 2); return {res.r(), res.g(), res.b(), static_cast(disable_alpha ? 255 : res.a())}; } - case Regs::TextureFormat::IA8: { + case TextureFormat::IA8: { const u8* source_ptr = source + MortonInterleave(x, y) * 2; if (disable_alpha) { @@ -118,17 +118,17 @@ Math::Vec4 LookupTexelInTile(const u8* source, unsigned int x, unsigned int } } - case Regs::TextureFormat::RG8: { + case TextureFormat::RG8: { auto res = Color::DecodeRG8(source + MortonInterleave(x, y) * 2); return {res.r(), res.g(), 0, 255}; } - case Regs::TextureFormat::I8: { + case TextureFormat::I8: { const u8* source_ptr = source + MortonInterleave(x, y); return {*source_ptr, *source_ptr, *source_ptr, 255}; } - case Regs::TextureFormat::A8: { + case TextureFormat::A8: { const u8* source_ptr = source + MortonInterleave(x, y); if (disable_alpha) { @@ -138,7 +138,7 @@ Math::Vec4 LookupTexelInTile(const u8* source, unsigned int x, unsigned int } } - case Regs::TextureFormat::IA4: { + case TextureFormat::IA4: { const u8* source_ptr = source + MortonInterleave(x, y); u8 i = Color::Convert4To8(((*source_ptr) & 0xF0) >> 4); @@ -152,7 +152,7 @@ Math::Vec4 LookupTexelInTile(const u8* source, unsigned int x, unsigned int } } - case Regs::TextureFormat::I4: { + case TextureFormat::I4: { u32 morton_offset = MortonInterleave(x, y); const u8* source_ptr = source + morton_offset / 2; @@ -162,7 +162,7 @@ Math::Vec4 LookupTexelInTile(const u8* source, unsigned int x, unsigned int return {i, i, i, 255}; } - case Regs::TextureFormat::A4: { + case TextureFormat::A4: { u32 morton_offset = MortonInterleave(x, y); const u8* source_ptr = source + morton_offset / 2; @@ -176,9 +176,9 @@ Math::Vec4 LookupTexelInTile(const u8* source, unsigned int x, unsigned int } } - case Regs::TextureFormat::ETC1: - case Regs::TextureFormat::ETC1A4: { - bool has_alpha = (info.format == Regs::TextureFormat::ETC1A4); + case TextureFormat::ETC1: + case TextureFormat::ETC1A4: { + bool has_alpha = (info.format == TextureFormat::ETC1A4); size_t subtile_size = has_alpha ? 16 : 8; // ETC1 further subdivides each 8x8 tile into four 4x4 subtiles @@ -214,8 +214,8 @@ Math::Vec4 LookupTexelInTile(const u8* source, unsigned int x, unsigned int } } -TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, - const Regs::TextureFormat& format) { +TextureInfo TextureInfo::FromPicaRegister(const TexturingRegs::TextureConfig& config, + const TexturingRegs::TextureFormat& format) { TextureInfo info; info.physical_address = config.GetPhysicalAddress(); 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 @@ #include "common/common_types.h" #include "common/vector_math.h" -#include "video_core/pica.h" +#include "video_core/regs_texturing.h" namespace Pica { namespace Texture { /// Returns the byte size of a 8*8 tile of the specified texture format. -size_t CalculateTileSize(Pica::Regs::TextureFormat format); +size_t CalculateTileSize(TexturingRegs::TextureFormat format); struct TextureInfo { PAddr physical_address; unsigned int width; unsigned int height; ptrdiff_t stride; - Pica::Regs::TextureFormat format; + TexturingRegs::TextureFormat format; - static TextureInfo FromPicaRegister(const Pica::Regs::TextureConfig& config, - const Pica::Regs::TextureFormat& format); + static TextureInfo FromPicaRegister(const TexturingRegs::TextureConfig& config, + const TexturingRegs::TextureFormat& format); /// Calculates stride from format and width, assuming that the entire texture is contiguous. void SetDefaultStride() { - stride = Pica::Texture::CalculateTileSize(format) * (width / 8); + stride = CalculateTileSize(format) * (width / 8); } };