diff options
| -rw-r--r-- | src/video_core/regs_texturing.h | 27 | ||||
| -rw-r--r-- | src/video_core/swrasterizer/rasterizer.cpp | 53 | 
2 files changed, 77 insertions, 3 deletions
diff --git a/src/video_core/regs_texturing.h b/src/video_core/regs_texturing.h index e4038b41b..3f5355fa9 100644 --- a/src/video_core/regs_texturing.h +++ b/src/video_core/regs_texturing.h @@ -133,7 +133,32 @@ struct TexturingRegs {          BitField<16, 1, u32> clear_texture_cache; // TODO: unimplemented      } main_config;      TextureConfig texture0; -    INSERT_PADDING_WORDS(0x8); + +    enum class CubeFace { +        PositiveX = 0, +        NegativeX = 1, +        PositiveY = 2, +        NegativeY = 3, +        PositiveZ = 4, +        NegativeZ = 5, +    }; + +    BitField<0, 22, u32> cube_address[5]; + +    PAddr GetCubePhysicalAddress(CubeFace face) const { +        PAddr address = texture0.address; +        if (face != CubeFace::PositiveX) { +            // Bits [22:27] from the main texture address is shared with all cubemap additional +            // addresses. +            auto& face_addr = cube_address[static_cast<size_t>(face) - 1]; +            address &= ~face_addr.mask; +            address |= face_addr; +        } +        // A multiplier of 8 is also needed in the same way as the main address. +        return address * 8; +    } + +    INSERT_PADDING_WORDS(0x3);      BitField<0, 4, TextureFormat> texture0_format;      BitField<0, 1, u32> fragment_lighting_enable;      INSERT_PADDING_WORDS(0x1); diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index e9edf0360..8b7b1defb 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -5,6 +5,7 @@  #include <algorithm>  #include <array>  #include <cmath> +#include <tuple>  #include "common/assert.h"  #include "common/bit_field.h"  #include "common/color.h" @@ -70,6 +71,49 @@ static int SignedArea(const Math::Vec2<Fix12P4>& vtx1, const Math::Vec2<Fix12P4>      return Math::Cross(vec1, vec2).z;  }; +/// Convert a 3D vector for cube map coordinates to 2D texture coordinates along with the face name +static std::tuple<float24, float24, PAddr> ConvertCubeCoord(float24 u, float24 v, float24 w, +                                                            const TexturingRegs& regs) { +    const float abs_u = std::abs(u.ToFloat32()); +    const float abs_v = std::abs(v.ToFloat32()); +    const float abs_w = std::abs(w.ToFloat32()); +    float24 x, y, z; +    PAddr addr; +    if (abs_u > abs_v && abs_u > abs_w) { +        if (u > float24::FromFloat32(0)) { +            addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveX); +            y = -v; +        } else { +            addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeX); +            y = v; +        } +        x = -w; +        z = u; +    } else if (abs_v > abs_w) { +        if (v > float24::FromFloat32(0)) { +            addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveY); +            x = u; +        } else { +            addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeY); +            x = -u; +        } +        y = w; +        z = v; +    } else { +        if (w > float24::FromFloat32(0)) { +            addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveZ); +            y = -v; +        } else { +            addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeZ); +            y = v; +        } +        x = u; +        z = w; +    } +    const float24 half = float24::FromFloat32(0.5f); +    return std::make_tuple(x / z * half + half, y / z * half + half, addr); +} +  MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240));  /** @@ -284,10 +328,16 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve                  // Only unit 0 respects the texturing type (according to 3DBrew)                  // TODO: Refactor so cubemaps and shadowmaps can be handled +                PAddr texture_address = texture.config.GetPhysicalAddress();                  if (i == 0) {                      switch (texture.config.type) {                      case TexturingRegs::TextureConfig::Texture2D:                          break; +                    case TexturingRegs::TextureConfig::TextureCube: { +                        auto w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); +                        std::tie(u, v, texture_address) = ConvertCubeCoord(u, v, w, regs.texturing); +                        break; +                    }                      case TexturingRegs::TextureConfig::Projection2D: {                          auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w);                          u /= tc0_w; @@ -322,8 +372,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve                      t = texture.config.height - 1 -                          GetWrappedTexCoord(texture.config.wrap_t, t, texture.config.height); -                    u8* texture_data = -                        Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); +                    const u8* texture_data = Memory::GetPhysicalPointer(texture_address);                      auto info =                          Texture::TextureInfo::FromPicaRegister(texture.config, texture.format);  | 
