From 78a3f9fa232467aff74e7561a65b8b78a18b24bd Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sat, 17 Jun 2023 11:59:45 -0700 Subject: [PATCH 1/5] Add PICA texel-format and topology types Slowly stepping the codebase towards having renderer-agnostic types and keeping the translation of PICA-types to OpenGL/VK/DX/Software/etc to the renderer-backend. --- include/PICA/regs.hpp | 49 ++++++++++++++++++++++++- include/renderer_gl/renderer_gl.hpp | 19 +++++----- include/renderer_gl/surfaces.hpp | 53 +++++----------------------- src/core/PICA/gpu.cpp | 14 +++----- src/core/PICA/regs.cpp | 8 ++--- src/core/renderer_gl/renderer_gl.cpp | 18 ++++++---- 6 files changed, 85 insertions(+), 76 deletions(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 0b3246db..607e72e6 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -127,4 +127,51 @@ namespace PICAInternalRegs { VertexShaderOpDescriptorData6 = 0x2DC, VertexShaderOpDescriptorData7 = 0x2DD, }; -} \ No newline at end of file +} + +enum class PICAColorFmt : u32 { + RGBA8 = 0, + BGR8 = 1, + RGB5A1 = 2, + RGB565 = 3, + RGBA4 = 4, + + // Technically selectable, but their function is unknown + Unknown5 = 5, + Unknown6 = 6, + Unknown7 = 7, +}; + +enum class PICADepthFmt : u32 { + Depth16 = 0, + Unknown1 = 1, // Technically selectable, but function is unknown + Depth24 = 2, + Depth24Stencil8 = 3, +}; + +// Size occupied by each pixel in bytes + +// All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) +inline constexpr usize sizePerPixel(PICAColorFmt format) { + switch (format) { + case PICAColorFmt::BGR8: return 3; + case PICAColorFmt::RGBA8: return 4; + default: return 2; + } +} + +inline constexpr usize sizePerPixel(PICADepthFmt format) { + switch (format) { + case PICADepthFmt::Depth16: return 2; + case PICADepthFmt::Depth24: return 3; + case PICADepthFmt::Depth24Stencil8: return 4; + default: return 1; // Invalid format + } +} + +enum class PICAPrimType : u32 { + TriangleList = 0, + TriangleStrip = 1, + TriangleFan = 2, + GeometryPrimitive = 3, +}; \ No newline at end of file diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index f387cb69..86ebcfe2 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -7,6 +7,7 @@ #include "opengl.hpp" #include "surface_cache.hpp" #include "textures.hpp" +#include "PICA/regs.hpp" // More circular dependencies! class GPU; @@ -46,11 +47,11 @@ class Renderer { OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)' u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer - ColourBuffer::Formats colourBufferFormat; // Format of the colours stored in the colour buffer + PICAColorFmt colourBufferFormat; // Format of the colours stored in the colour buffer // Same for the depth/stencil buffer u32 depthBufferLoc; - DepthBuffer::Formats depthBufferFormat; + PICADepthFmt depthBufferFormat; // Dummy VAO/VBO for blitting the final output OpenGL::VertexArray dummyVAO; @@ -75,23 +76,19 @@ class Renderer { void getGraphicsContext(); // Set up graphics context for rendering void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); // Clear a GPU buffer in VRAM void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer - void drawVertices(OpenGL::Primitives primType, std::span vertices); // Draw the given vertices + void drawVertices(PICAPrimType primType, std::span vertices); // Draw the given vertices void setFBSize(u32 width, u32 height) { fbSize.x() = width; fbSize.y() = height; } - void setColourFormat(ColourBuffer::Formats format) { colourBufferFormat = format; } - void setColourFormat(u32 format) { colourBufferFormat = static_cast(format); } - - void setDepthFormat(DepthBuffer::Formats format) { depthBufferFormat = format; } - void setDepthFormat(u32 format) { - if (format == 1) { + void setColourFormat(PICAColorFmt format) { colourBufferFormat = format; } + void setDepthFormat(PICADepthFmt format) { + if (format == PICADepthFmt::Unknown1) { Helpers::panic("[PICA] Undocumented depth-stencil mode!"); } - - depthBufferFormat = static_cast(format); + depthBufferFormat = format; } void setColourBufferLoc(u32 loc) { colourBufferLoc = loc; } diff --git a/include/renderer_gl/surfaces.hpp b/include/renderer_gl/surfaces.hpp index 680a1454..7685a765 100644 --- a/include/renderer_gl/surfaces.hpp +++ b/include/renderer_gl/surfaces.hpp @@ -1,4 +1,5 @@ #pragma once +#include "PICA/regs.hpp" #include "boost/icl/interval.hpp" #include "helpers.hpp" #include "opengl.hpp" @@ -7,18 +8,8 @@ template using Interval = boost::icl::right_open_interval; struct ColourBuffer { - enum class Formats : u32 { - RGBA8 = 0, - BGR8 = 1, - RGB5A1 = 2, - RGB565 = 3, - RGBA4 = 4, - - Trash1 = 5, Trash2 = 6, Trash3 = 7 // Technically selectable, but their function is unknown - }; - u32 location; - Formats format; + PICAColorFmt format; OpenGL::uvec2 size; bool valid; @@ -30,7 +21,7 @@ struct ColourBuffer { ColourBuffer() : valid(false) {} - ColourBuffer(u32 loc, Formats format, u32 x, u32 y, bool valid = true) + ColourBuffer(u32 loc, PICAColorFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -78,31 +69,14 @@ struct ColourBuffer { size.x() == other.size.x() && size.y() == other.size.y(); } - // Size occupied by each pixel in bytes - // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) - size_t sizePerPixel() { - switch (format) { - case Formats::BGR8: return 3; - case Formats::RGBA8: return 4; - default: return 2; - } - } - size_t sizeInBytes() { - return (size_t)size.x() * (size_t)size.y() * sizePerPixel(); + return (size_t)size.x() * (size_t)size.y() * sizePerPixel(format); } }; struct DepthBuffer { - enum class Formats : u32 { - Depth16 = 0, - Garbage = 1, - Depth24 = 2, - Depth24Stencil8 = 3 - }; - u32 location; - Formats format; + PICADepthFmt format; OpenGL::uvec2 size; // Implicitly set to the size of the framebuffer bool valid; @@ -113,7 +87,7 @@ struct DepthBuffer { DepthBuffer() : valid(false) {} - DepthBuffer(u32 loc, Formats format, u32 x, u32 y, bool valid = true) : + DepthBuffer(u32 loc, PICADepthFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -122,7 +96,7 @@ struct DepthBuffer { } bool hasStencil() { - return format == Formats::Depth24Stencil8; + return format == PICADepthFmt::Depth24Stencil8; } void allocate() { @@ -167,18 +141,7 @@ struct DepthBuffer { size.x() == other.size.x() && size.y() == other.size.y(); } - // Size occupied by each pixel in bytes - size_t sizePerPixel() { - switch (format) { - case Formats::Depth16: return 2; - case Formats::Depth24: return 3; - case Formats::Depth24Stencil8: return 4; - - default: return 1; // Invalid format - } - } - size_t sizeInBytes() { - return (size_t)size.x() * (size_t)size.y() * sizePerPixel(); + return (size_t)size.x() * (size_t)size.y() * sizePerPixel(format); } }; \ No newline at end of file diff --git a/src/core/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index f0e832a2..a8e79417 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -55,11 +55,12 @@ void GPU::drawArrays() { // Configures the type of primitive and the number of vertex shader outputs const u32 primConfig = regs[PICAInternalRegs::PrimitiveConfig]; - const u32 primType = Helpers::getBits<8, 2>(primConfig); - if (primType != 0 && primType != 1 && primType != 3) Helpers::panic("[PICA] Tried to draw unimplemented shape %d\n", primType); + const PICAPrimType primType = static_cast(Helpers::getBits<8, 2>(primConfig)); + if (primType == PICAPrimType::TriangleFan) Helpers::panic("[PICA] Tried to draw unimplemented shape %d\n", primType); if (vertexCount > Renderer::vertexBufferSize) Helpers::panic("[PICA] vertexCount > vertexBufferSize"); - if ((primType == 0 && vertexCount % 3) || (primType == 1 && vertexCount < 3)) { + if ((primType == PICAPrimType::TriangleList && vertexCount % 3) || + (primType == PICAPrimType::TriangleStrip && vertexCount < 3)) { Helpers::panic("Invalid vertex count for primitive. Type: %d, vert count: %d\n", primType, vertexCount); } @@ -203,12 +204,7 @@ void GPU::drawArrays() { //printf("(u, v ) = (%f, %f)\n", vertices[i].UVs.u(), vertices[i].UVs.v()); } - // The fourth type is meant to be "Geometry primitive". TODO: Find out what that is - static constexpr std::array primTypes = { - OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle - }; - const auto shape = primTypes[primType]; - renderer.drawVertices(shape, std::span(vertices).first(vertexCount)); + renderer.drawVertices(primType, std::span(vertices).first(vertexCount)); } Vertex GPU::getImmediateModeVertex() { diff --git a/src/core/PICA/regs.cpp b/src/core/PICA/regs.cpp index 26feaf9d..9dbd584b 100644 --- a/src/core/PICA/regs.cpp +++ b/src/core/PICA/regs.cpp @@ -68,7 +68,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { case ColourBufferFormat: { u32 format = getBits<16, 3>(value); - renderer.setColourFormat(format); + renderer.setColourFormat(static_cast(format)); break; } @@ -79,8 +79,8 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { } case DepthBufferFormat: { - u32 fmt = value & 0x3; - renderer.setDepthFormat(fmt); + u32 format = value & 0x3; + renderer.setDepthFormat(static_cast(format)); break; } @@ -157,7 +157,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { // If we've reached 3 verts, issue a draw call // Handle rendering depending on the primitive type if (immediateModeVertIndex == 3) { - renderer.drawVertices(OpenGL::Triangle, immediateModeVertices); + renderer.drawVertices(PICAPrimType::TriangleList, immediateModeVertices); switch (primType) { // Triangle or geometry primitive. Draw a triangle and discard all vertices diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 9265e2f4..1a8f1f5b 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -144,10 +144,10 @@ void Renderer::reset() { // Init the colour/depth buffer settings to some random defaults on reset colourBufferLoc = 0; - colourBufferFormat = ColourBuffer::Formats::RGBA8; + colourBufferFormat = PICAColorFmt::RGBA8; depthBufferLoc = 0; - depthBufferFormat = DepthBuffer::Formats::Depth16; + depthBufferFormat = PICADepthFmt::Depth16; if (triangleProgram.exists()) { const auto oldProgram = OpenGL::getProgram(); @@ -264,7 +264,13 @@ void Renderer::setupBlending() { } } -void Renderer::drawVertices(OpenGL::Primitives primType, std::span vertices) { +void Renderer::drawVertices(PICAPrimType primType, std::span vertices) { + // The fourth type is meant to be "Geometry primitive". TODO: Find out what that is + static constexpr std::array primTypes = { + OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle + }; + const auto primitiveTopology = primTypes[static_cast(primType)]; + // Adjust alpha test if necessary const u32 alphaControl = regs[PICAInternalRegs::AlphaTestConfig]; if (alphaControl != oldAlphaControl) { @@ -352,7 +358,7 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span } vbo.bufferVertsSub(vertices); - OpenGL::draw(primType, vertices.size()); + OpenGL::draw(primitiveTopology, vertices.size()); } constexpr u32 topScreenBuffer = 0x1f000000; @@ -423,8 +429,8 @@ void Renderer::bindDepthBuffer() { tex = depthBufferCache.add(sampleBuffer).texture.m_handle; } - if (DepthBuffer::Formats::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?"); - auto attachment = depthBufferFormat == DepthBuffer::Formats::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; + if (PICADepthFmt::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?"); + auto attachment = depthBufferFormat == PICADepthFmt::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0); } From 838d3f27f9e43f2d4e52cb25a3a4ce6728d1fc16 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sat, 17 Jun 2023 18:23:47 -0700 Subject: [PATCH 2/5] Migrate PICA-types into `PICA` namespace Rather than prefixing these types with `PICA`, a namespace is used instead. --- include/PICA/gpu.hpp | 2 +- include/PICA/regs.hpp | 307 ++++++++++++++------------- include/renderer_gl/renderer_gl.hpp | 12 +- include/renderer_gl/surfaces.hpp | 14 +- src/core/PICA/gpu.cpp | 26 +-- src/core/PICA/regs.cpp | 12 +- src/core/renderer_gl/renderer_gl.cpp | 32 +-- 7 files changed, 204 insertions(+), 201 deletions(-) diff --git a/include/PICA/gpu.hpp b/include/PICA/gpu.hpp index 4b60b3ef..2512e698 100644 --- a/include/PICA/gpu.hpp +++ b/include/PICA/gpu.hpp @@ -47,7 +47,7 @@ class GPU { }; u64 getVertexShaderInputConfig() { - return u64(regs[PICAInternalRegs::VertexShaderInputCfgLow]) | (u64(regs[PICAInternalRegs::VertexShaderInputCfgHigh]) << 32); + return u64(regs[PICA::InternalRegs::VertexShaderInputCfgLow]) | (u64(regs[PICA::InternalRegs::VertexShaderInputCfgHigh]) << 32); } std::array attributeInfo; // Info for each of the 12 attributes diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 607e72e6..c5da123a 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -1,177 +1,180 @@ #pragma once #include "helpers.hpp" -namespace PICAInternalRegs { - enum : u32 { - // Rasterizer registers - ViewportWidth = 0x41, - ViewportInvw = 0x42, - ViewportHeight = 0x43, - ViewportInvh = 0x44, +namespace PICA { + namespace InternalRegs { + enum : u32 { + // Rasterizer registers + ViewportWidth = 0x41, + ViewportInvw = 0x42, + ViewportHeight = 0x43, + ViewportInvh = 0x44, - DepthScale = 0x4D, - DepthOffset = 0x4E, - ShaderOutputCount = 0x4F, + DepthScale = 0x4D, + DepthOffset = 0x4E, + ShaderOutputCount = 0x4F, - DepthmapEnable = 0x6D, - TexUnitCfg = 0x80, + DepthmapEnable = 0x6D, + TexUnitCfg = 0x80, - // Framebuffer registers - ColourOperation = 0x100, - BlendFunc = 0x101, - BlendColour = 0x103, - AlphaTestConfig = 0x104, - DepthAndColorMask = 0x107, - DepthBufferFormat = 0x116, - ColourBufferFormat = 0x117, - DepthBufferLoc = 0x11C, - ColourBufferLoc = 0x11D, - FramebufferSize = 0x11E, + // Framebuffer registers + ColourOperation = 0x100, + BlendFunc = 0x101, + BlendColour = 0x103, + AlphaTestConfig = 0x104, + DepthAndColorMask = 0x107, + DepthBufferFormat = 0x116, + ColourBufferFormat = 0x117, + DepthBufferLoc = 0x11C, + ColourBufferLoc = 0x11D, + FramebufferSize = 0x11E, - // Geometry pipeline registers - VertexAttribLoc = 0x200, - AttribFormatLow = 0x201, - AttribFormatHigh = 0x202, - IndexBufferConfig = 0x227, - VertexCountReg = 0x228, - VertexOffsetReg = 0x22A, - SignalDrawArrays = 0x22E, - SignalDrawElements = 0x22F, + // Geometry pipeline registers + VertexAttribLoc = 0x200, + AttribFormatLow = 0x201, + AttribFormatHigh = 0x202, + IndexBufferConfig = 0x227, + VertexCountReg = 0x228, + VertexOffsetReg = 0x22A, + SignalDrawArrays = 0x22E, + SignalDrawElements = 0x22F, - Attrib0Offset = 0x203, - Attrib1Offset = 0x206, - Attrib2Offset = 0x209, - Attrib3Offset = 0x20C, - Attrib4Offset = 0x20F, - Attrib5Offset = 0x212, - Attrib6Offset = 0x215, - Attrib7Offset = 0x218, - Attrib8Offset = 0x21B, - Attrib9Offset = 0x21E, - Attrib10Offset = 0x221, - Attrib11Offset = 0x224, + Attrib0Offset = 0x203, + Attrib1Offset = 0x206, + Attrib2Offset = 0x209, + Attrib3Offset = 0x20C, + Attrib4Offset = 0x20F, + Attrib5Offset = 0x212, + Attrib6Offset = 0x215, + Attrib7Offset = 0x218, + Attrib8Offset = 0x21B, + Attrib9Offset = 0x21E, + Attrib10Offset = 0x221, + Attrib11Offset = 0x224, - Attrib0Config2 = 0x205, - Attrib1Config2 = 0x208, - Attrib2Config2 = 0x20B, - Attrib3Config2 = 0x20E, - Attrib4Config2 = 0x211, - Attrib5Config2 = 0x214, - Attrib6Config2 = 0x217, - Attrib7Config2 = 0x21A, - Attrib8Config2 = 0x21D, - Attrib9Config2 = 0x220, - Attrib10Config2 = 0x223, - Attrib11Config2 = 0x226, + Attrib0Config2 = 0x205, + Attrib1Config2 = 0x208, + Attrib2Config2 = 0x20B, + Attrib3Config2 = 0x20E, + Attrib4Config2 = 0x211, + Attrib5Config2 = 0x214, + Attrib6Config2 = 0x217, + Attrib7Config2 = 0x21A, + Attrib8Config2 = 0x21D, + Attrib9Config2 = 0x220, + Attrib10Config2 = 0x223, + Attrib11Config2 = 0x226, - AttribInfoStart = Attrib0Offset, - AttribInfoEnd = Attrib11Config2, + AttribInfoStart = Attrib0Offset, + AttribInfoEnd = Attrib11Config2, - // Fixed attribute registers - FixedAttribIndex = 0x232, - FixedAttribData0 = 0x233, - FixedAttribData1 = 0x234, - FixedAttribData2 = 0x235, + // Fixed attribute registers + FixedAttribIndex = 0x232, + FixedAttribData0 = 0x233, + FixedAttribData1 = 0x234, + FixedAttribData2 = 0x235, - // Command processor registers - CmdBufSize0 = 0x238, - CmdBufSize1 = 0x239, - CmdBufAddr0 = 0x23A, - CmdBufAddr1 = 0x23B, - CmdBufTrigger0 = 0x23C, - CmdBufTrigger1 = 0x23D, + // Command processor registers + CmdBufSize0 = 0x238, + CmdBufSize1 = 0x239, + CmdBufAddr0 = 0x23A, + CmdBufAddr1 = 0x23B, + CmdBufTrigger0 = 0x23C, + CmdBufTrigger1 = 0x23D, - PrimitiveConfig = 0x25E, - PrimitiveRestart = 0x25F, + PrimitiveConfig = 0x25E, + PrimitiveRestart = 0x25F, - // Vertex shader registers - VertexShaderAttrNum = 0x242, - VertexBoolUniform = 0x2B0, - VertexIntUniform0 = 0x2B1, - VertexIntUniform1 = 0x2B2, - VertexIntUniform2 = 0x2B3, - VertexIntUniform3 = 0x2B4, + // Vertex shader registers + VertexShaderAttrNum = 0x242, + VertexBoolUniform = 0x2B0, + VertexIntUniform0 = 0x2B1, + VertexIntUniform1 = 0x2B2, + VertexIntUniform2 = 0x2B3, + VertexIntUniform3 = 0x2B4, - VertexShaderEntrypoint = 0x2BA, - VertexShaderTransferEnd = 0x2BF, - VertexFloatUniformIndex = 0x2C0, - VertexFloatUniformData0 = 0x2C1, - VertexFloatUniformData1 = 0x2C2, - VertexFloatUniformData2 = 0x2C3, - VertexFloatUniformData3 = 0x2C4, - VertexFloatUniformData4 = 0x2C5, - VertexFloatUniformData5 = 0x2C6, - VertexFloatUniformData6 = 0x2C7, - VertexFloatUniformData7 = 0x2C8, + VertexShaderEntrypoint = 0x2BA, + VertexShaderTransferEnd = 0x2BF, + VertexFloatUniformIndex = 0x2C0, + VertexFloatUniformData0 = 0x2C1, + VertexFloatUniformData1 = 0x2C2, + VertexFloatUniformData2 = 0x2C3, + VertexFloatUniformData3 = 0x2C4, + VertexFloatUniformData4 = 0x2C5, + VertexFloatUniformData5 = 0x2C6, + VertexFloatUniformData6 = 0x2C7, + VertexFloatUniformData7 = 0x2C8, - VertexShaderInputBufferCfg = 0x2B9, - VertexShaderInputCfgLow = 0x2BB, - VertexShaderInputCfgHigh = 0x2BC, + VertexShaderInputBufferCfg = 0x2B9, + VertexShaderInputCfgLow = 0x2BB, + VertexShaderInputCfgHigh = 0x2BC, - VertexShaderTransferIndex = 0x2CB, - VertexShaderData0 = 0x2CC, - VertexShaderData1 = 0x2CD, - VertexShaderData2 = 0x2CE, - VertexShaderData3 = 0x2CF, - VertexShaderData4 = 0x2D0, - VertexShaderData5 = 0x2D1, - VertexShaderData6 = 0x2D2, - VertexShaderData7 = 0x2D3, - VertexShaderOpDescriptorIndex = 0x2D5, - VertexShaderOpDescriptorData0 = 0x2D6, - VertexShaderOpDescriptorData1 = 0x2D7, - VertexShaderOpDescriptorData2 = 0x2D8, - VertexShaderOpDescriptorData3 = 0x2D9, - VertexShaderOpDescriptorData4 = 0x2DA, - VertexShaderOpDescriptorData5 = 0x2DB, - VertexShaderOpDescriptorData6 = 0x2DC, - VertexShaderOpDescriptorData7 = 0x2DD, + VertexShaderTransferIndex = 0x2CB, + VertexShaderData0 = 0x2CC, + VertexShaderData1 = 0x2CD, + VertexShaderData2 = 0x2CE, + VertexShaderData3 = 0x2CF, + VertexShaderData4 = 0x2D0, + VertexShaderData5 = 0x2D1, + VertexShaderData6 = 0x2D2, + VertexShaderData7 = 0x2D3, + VertexShaderOpDescriptorIndex = 0x2D5, + VertexShaderOpDescriptorData0 = 0x2D6, + VertexShaderOpDescriptorData1 = 0x2D7, + VertexShaderOpDescriptorData2 = 0x2D8, + VertexShaderOpDescriptorData3 = 0x2D9, + VertexShaderOpDescriptorData4 = 0x2DA, + VertexShaderOpDescriptorData5 = 0x2DB, + VertexShaderOpDescriptorData6 = 0x2DC, + VertexShaderOpDescriptorData7 = 0x2DD, + }; + } + + enum class ColorFmt : u32 { + RGBA8 = 0, + BGR8 = 1, + RGB5A1 = 2, + RGB565 = 3, + RGBA4 = 4, + + // Technically selectable, but their function is unknown + Unknown5 = 5, + Unknown6 = 6, + Unknown7 = 7, }; -} -enum class PICAColorFmt : u32 { - RGBA8 = 0, - BGR8 = 1, - RGB5A1 = 2, - RGB565 = 3, - RGBA4 = 4, + enum class DepthFmt : u32 { + Depth16 = 0, + Unknown1 = 1, // Technically selectable, but function is unknown + Depth24 = 2, + Depth24Stencil8 = 3, + }; - // Technically selectable, but their function is unknown - Unknown5 = 5, - Unknown6 = 6, - Unknown7 = 7, -}; + // Size occupied by each pixel in bytes -enum class PICADepthFmt : u32 { - Depth16 = 0, - Unknown1 = 1, // Technically selectable, but function is unknown - Depth24 = 2, - Depth24Stencil8 = 3, -}; - -// Size occupied by each pixel in bytes - -// All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) -inline constexpr usize sizePerPixel(PICAColorFmt format) { - switch (format) { - case PICAColorFmt::BGR8: return 3; - case PICAColorFmt::RGBA8: return 4; - default: return 2; + // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) + inline constexpr usize sizePerPixel(ColorFmt format) { + switch (format) { + case ColorFmt::BGR8: return 3; + case ColorFmt::RGBA8: return 4; + default: return 2; + } } -} -inline constexpr usize sizePerPixel(PICADepthFmt format) { - switch (format) { - case PICADepthFmt::Depth16: return 2; - case PICADepthFmt::Depth24: return 3; - case PICADepthFmt::Depth24Stencil8: return 4; - default: return 1; // Invalid format + inline constexpr usize sizePerPixel(DepthFmt format) { + switch (format) { + case DepthFmt::Depth16: return 2; + case DepthFmt::Depth24: return 3; + case DepthFmt::Depth24Stencil8: return 4; + default: return 1; // Invalid format + } } -} -enum class PICAPrimType : u32 { - TriangleList = 0, - TriangleStrip = 1, - TriangleFan = 2, - GeometryPrimitive = 3, -}; \ No newline at end of file + enum class PrimType : u32 { + TriangleList = 0, + TriangleStrip = 1, + TriangleFan = 2, + GeometryPrimitive = 3, + }; + +} // namespace PICA \ No newline at end of file diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 86ebcfe2..383fa484 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -47,11 +47,11 @@ class Renderer { OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)' u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer - PICAColorFmt colourBufferFormat; // Format of the colours stored in the colour buffer + PICA::ColorFmt colourBufferFormat; // Format of the colours stored in the colour buffer // Same for the depth/stencil buffer u32 depthBufferLoc; - PICADepthFmt depthBufferFormat; + PICA::DepthFmt depthBufferFormat; // Dummy VAO/VBO for blitting the final output OpenGL::VertexArray dummyVAO; @@ -76,16 +76,16 @@ class Renderer { void getGraphicsContext(); // Set up graphics context for rendering void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); // Clear a GPU buffer in VRAM void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer - void drawVertices(PICAPrimType primType, std::span vertices); // Draw the given vertices + void drawVertices(PICA::PrimType primType, std::span vertices); // Draw the given vertices void setFBSize(u32 width, u32 height) { fbSize.x() = width; fbSize.y() = height; } - void setColourFormat(PICAColorFmt format) { colourBufferFormat = format; } - void setDepthFormat(PICADepthFmt format) { - if (format == PICADepthFmt::Unknown1) { + void setColourFormat(PICA::ColorFmt format) { colourBufferFormat = format; } + void setDepthFormat(PICA::DepthFmt format) { + if (format == PICA::DepthFmt::Unknown1) { Helpers::panic("[PICA] Undocumented depth-stencil mode!"); } depthBufferFormat = format; diff --git a/include/renderer_gl/surfaces.hpp b/include/renderer_gl/surfaces.hpp index 7685a765..f6d5230d 100644 --- a/include/renderer_gl/surfaces.hpp +++ b/include/renderer_gl/surfaces.hpp @@ -9,7 +9,7 @@ using Interval = boost::icl::right_open_interval; struct ColourBuffer { u32 location; - PICAColorFmt format; + PICA::ColorFmt format; OpenGL::uvec2 size; bool valid; @@ -21,7 +21,7 @@ struct ColourBuffer { ColourBuffer() : valid(false) {} - ColourBuffer(u32 loc, PICAColorFmt format, u32 x, u32 y, bool valid = true) + ColourBuffer(u32 loc, PICA::ColorFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -70,13 +70,13 @@ struct ColourBuffer { } size_t sizeInBytes() { - return (size_t)size.x() * (size_t)size.y() * sizePerPixel(format); + return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format); } }; struct DepthBuffer { u32 location; - PICADepthFmt format; + PICA::DepthFmt format; OpenGL::uvec2 size; // Implicitly set to the size of the framebuffer bool valid; @@ -87,7 +87,7 @@ struct DepthBuffer { DepthBuffer() : valid(false) {} - DepthBuffer(u32 loc, PICADepthFmt format, u32 x, u32 y, bool valid = true) : + DepthBuffer(u32 loc, PICA::DepthFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -96,7 +96,7 @@ struct DepthBuffer { } bool hasStencil() { - return format == PICADepthFmt::Depth24Stencil8; + return format == PICA::DepthFmt::Depth24Stencil8; } void allocate() { @@ -142,6 +142,6 @@ struct DepthBuffer { } size_t sizeInBytes() { - return (size_t)size.x() * (size_t)size.y() * sizePerPixel(format); + return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format); } }; \ No newline at end of file diff --git a/src/core/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index a8e79417..beaa4f50 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -50,45 +50,45 @@ template void GPU::drawArrays() { // Base address for vertex attributes // The vertex base is always on a quadword boundary because the PICA does weird alignment shit any time possible - const u32 vertexBase = ((regs[PICAInternalRegs::VertexAttribLoc] >> 1) & 0xfffffff) * 16; - const u32 vertexCount = regs[PICAInternalRegs::VertexCountReg]; // Total # of vertices to transfer + const u32 vertexBase = ((regs[PICA::InternalRegs::VertexAttribLoc] >> 1) & 0xfffffff) * 16; + const u32 vertexCount = regs[PICA::InternalRegs::VertexCountReg]; // Total # of vertices to transfer // Configures the type of primitive and the number of vertex shader outputs - const u32 primConfig = regs[PICAInternalRegs::PrimitiveConfig]; - const PICAPrimType primType = static_cast(Helpers::getBits<8, 2>(primConfig)); - if (primType == PICAPrimType::TriangleFan) Helpers::panic("[PICA] Tried to draw unimplemented shape %d\n", primType); + const u32 primConfig = regs[PICA::InternalRegs::PrimitiveConfig]; + const PICA::PrimType primType = static_cast(Helpers::getBits<8, 2>(primConfig)); + if (primType == PICA::PrimType::TriangleFan) Helpers::panic("[PICA] Tried to draw unimplemented shape %d\n", primType); if (vertexCount > Renderer::vertexBufferSize) Helpers::panic("[PICA] vertexCount > vertexBufferSize"); - if ((primType == PICAPrimType::TriangleList && vertexCount % 3) || - (primType == PICAPrimType::TriangleStrip && vertexCount < 3)) { + if ((primType == PICA::PrimType::TriangleList && vertexCount % 3) || + (primType == PICA::PrimType::TriangleStrip && vertexCount < 3)) { Helpers::panic("Invalid vertex count for primitive. Type: %d, vert count: %d\n", primType, vertexCount); } // Get the configuration for the index buffer, used only for indexed drawing - u32 indexBufferConfig = regs[PICAInternalRegs::IndexBufferConfig]; + u32 indexBufferConfig = regs[PICA::InternalRegs::IndexBufferConfig]; u32 indexBufferPointer = vertexBase + (indexBufferConfig & 0xfffffff); bool shortIndex = Helpers::getBit<31>(indexBufferConfig); // Indicates whether vert indices are 16-bit or 8-bit // Stuff the global attribute config registers in one u64 to make attr parsing easier // TODO: Cache this when the vertex attribute format registers are written to - u64 vertexCfg = u64(regs[PICAInternalRegs::AttribFormatLow]) | (u64(regs[PICAInternalRegs::AttribFormatHigh]) << 32); + u64 vertexCfg = u64(regs[PICA::InternalRegs::AttribFormatLow]) | (u64(regs[PICA::InternalRegs::AttribFormatHigh]) << 32); if constexpr (!indexed) { - u32 offset = regs[PICAInternalRegs::VertexOffsetReg]; + u32 offset = regs[PICA::InternalRegs::VertexOffsetReg]; log("PICA::DrawArrays(vertex count = %d, vertexOffset = %d)\n", vertexCount, offset); } else { log("PICA::DrawElements(vertex count = %d, index buffer config = %08X)\n", vertexCount, indexBufferConfig); } // Total number of input attributes to shader. Differs between GS and VS. Currently stubbed to the VS one, as we don't have geometry shaders. - const u32 inputAttrCount = (regs[PICAInternalRegs::VertexShaderInputBufferCfg] & 0xf) + 1; + const u32 inputAttrCount = (regs[PICA::InternalRegs::VertexShaderInputBufferCfg] & 0xf) + 1; const u64 inputAttrCfg = getVertexShaderInputConfig(); for (u32 i = 0; i < vertexCount; i++) { u32 vertexIndex; // Index of the vertex in the VBO if constexpr (!indexed) { - vertexIndex = i + regs[PICAInternalRegs::VertexOffsetReg]; + vertexIndex = i + regs[PICA::InternalRegs::VertexOffsetReg]; } else { if (shortIndex) { auto ptr = getPointerPhys(indexBufferPointer); @@ -209,7 +209,7 @@ void GPU::drawArrays() { Vertex GPU::getImmediateModeVertex() { Vertex v; - const int totalAttrCount = (regs[PICAInternalRegs::VertexShaderAttrNum] & 0xf) + 1; + const int totalAttrCount = (regs[PICA::InternalRegs::VertexShaderAttrNum] & 0xf) + 1; // Copy immediate mode attributes to vertex shader unit for (int i = 0; i < totalAttrCount; i++) { diff --git a/src/core/PICA/regs.cpp b/src/core/PICA/regs.cpp index 9dbd584b..14f61ef7 100644 --- a/src/core/PICA/regs.cpp +++ b/src/core/PICA/regs.cpp @@ -33,7 +33,7 @@ u32 GPU::readInternalReg(u32 index) { } void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { - using namespace PICAInternalRegs; + using namespace PICA::InternalRegs; if (index > regNum) { Helpers::panic("Tried to write to invalid GPU register. Index: %X, value: %08X\n", index, value); @@ -68,7 +68,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { case ColourBufferFormat: { u32 format = getBits<16, 3>(value); - renderer.setColourFormat(static_cast(format)); + renderer.setColourFormat(static_cast(format)); break; } @@ -80,7 +80,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { case DepthBufferFormat: { u32 format = value & 0x3; - renderer.setDepthFormat(static_cast(format)); + renderer.setDepthFormat(static_cast(format)); break; } @@ -137,7 +137,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { if (fixedAttribIndex < 12) [[likely]] { shaderUnit.vs.fixedAttributes[fixedAttribIndex++] = attr; } else if (fixedAttribIndex == 15) { // Otherwise if it's 15, we're submitting an immediate mode vertex - const uint totalAttrCount = (regs[PICAInternalRegs::VertexShaderAttrNum] & 0xf) + 1; + const uint totalAttrCount = (regs[PICA::InternalRegs::VertexShaderAttrNum] & 0xf) + 1; if (totalAttrCount <= immediateModeAttrIndex) { printf("Broken state in the immediate mode vertex submission pipeline. Failing silently\n"); immediateModeAttrIndex = 0; @@ -151,13 +151,13 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { immediateModeVertices[immediateModeVertIndex++] = v; // Get primitive type - const u32 primConfig = regs[PICAInternalRegs::PrimitiveConfig]; + const u32 primConfig = regs[PICA::InternalRegs::PrimitiveConfig]; const u32 primType = getBits<8, 2>(primConfig); // If we've reached 3 verts, issue a draw call // Handle rendering depending on the primitive type if (immediateModeVertIndex == 3) { - renderer.drawVertices(PICAPrimType::TriangleList, immediateModeVertices); + renderer.drawVertices(PICA::PrimType::TriangleList, immediateModeVertices); switch (primType) { // Triangle or geometry primitive. Draw a triangle and discard all vertices diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 1a8f1f5b..ab93af73 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -144,10 +144,10 @@ void Renderer::reset() { // Init the colour/depth buffer settings to some random defaults on reset colourBufferLoc = 0; - colourBufferFormat = PICAColorFmt::RGBA8; + colourBufferFormat = PICA::ColorFmt::RGBA8; depthBufferLoc = 0; - depthBufferFormat = PICADepthFmt::Depth16; + depthBufferFormat = PICA::DepthFmt::Depth16; if (triangleProgram.exists()) { const auto oldProgram = OpenGL::getProgram(); @@ -221,7 +221,7 @@ void Renderer::getGraphicsContext() { // Set up the OpenGL blending context to match the emulated PICA void Renderer::setupBlending() { - const bool blendingEnabled = (regs[PICAInternalRegs::ColourOperation] & (1 << 8)) != 0; + const bool blendingEnabled = (regs[PICA::InternalRegs::ColourOperation] & (1 << 8)) != 0; // Map of PICA blending equations to OpenGL blending equations. The unused blending equations are equivalent to equation 0 (add) static constexpr std::array blendingEquations = { @@ -241,7 +241,7 @@ void Renderer::setupBlending() { OpenGL::enableBlend(); // Get blending equations - const u32 blendControl = regs[PICAInternalRegs::BlendFunc]; + const u32 blendControl = regs[PICA::InternalRegs::BlendFunc]; const u32 rgbEquation = blendControl & 0x7; const u32 alphaEquation = getBits<8, 3>(blendControl); @@ -251,7 +251,7 @@ void Renderer::setupBlending() { const u32 alphaSourceFunc = getBits<24, 4>(blendControl); const u32 alphaDestFunc = getBits<28, 4>(blendControl); - const u32 constantColor = regs[PICAInternalRegs::BlendColour]; + const u32 constantColor = regs[PICA::InternalRegs::BlendColour]; const u32 r = constantColor & 0xff; const u32 g = getBits<8, 8>(constantColor); const u32 b = getBits<16, 8>(constantColor); @@ -264,7 +264,7 @@ void Renderer::setupBlending() { } } -void Renderer::drawVertices(PICAPrimType primType, std::span vertices) { +void Renderer::drawVertices(PICA::PrimType primType, std::span vertices) { // The fourth type is meant to be "Geometry primitive". TODO: Find out what that is static constexpr std::array primTypes = { OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle @@ -272,7 +272,7 @@ void Renderer::drawVertices(PICAPrimType primType, std::span verti const auto primitiveTopology = primTypes[static_cast(primType)]; // Adjust alpha test if necessary - const u32 alphaControl = regs[PICAInternalRegs::AlphaTestConfig]; + const u32 alphaControl = regs[PICA::InternalRegs::AlphaTestConfig]; if (alphaControl != oldAlphaControl) { oldAlphaControl = alphaControl; glUniform1ui(alphaControlLoc, alphaControl); @@ -282,7 +282,7 @@ void Renderer::drawVertices(PICAPrimType primType, std::span verti OpenGL::Framebuffer poop = getColourFBO(); poop.bind(OpenGL::DrawAndReadFramebuffer); - const u32 depthControl = regs[PICAInternalRegs::DepthAndColorMask]; + const u32 depthControl = regs[PICA::InternalRegs::DepthAndColorMask]; const bool depthEnable = depthControl & 1; const bool depthWriteEnable = getBit<12>(depthControl); const int depthFunc = getBits<4, 3>(depthControl); @@ -293,9 +293,9 @@ void Renderer::drawVertices(PICAPrimType primType, std::span verti GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL }; - const float depthScale = f24::fromRaw(regs[PICAInternalRegs::DepthScale] & 0xffffff).toFloat32(); - const float depthOffset = f24::fromRaw(regs[PICAInternalRegs::DepthOffset] & 0xffffff).toFloat32(); - const bool depthMapEnable = regs[PICAInternalRegs::DepthmapEnable] & 1; + const float depthScale = f24::fromRaw(regs[PICA::InternalRegs::DepthScale] & 0xffffff).toFloat32(); + const float depthOffset = f24::fromRaw(regs[PICA::InternalRegs::DepthOffset] & 0xffffff).toFloat32(); + const bool depthMapEnable = regs[PICA::InternalRegs::DepthmapEnable] & 1; // Update depth uniforms if (oldDepthScale != depthScale) { @@ -328,15 +328,15 @@ void Renderer::drawVertices(PICAPrimType primType, std::span verti } // Update the texture unit configuration uniform if it changed - const u32 texUnitConfig = regs[PICAInternalRegs::TexUnitCfg]; + const u32 texUnitConfig = regs[PICA::InternalRegs::TexUnitCfg]; if (oldTexUnitConfig != texUnitConfig) { oldTexUnitConfig = texUnitConfig; glUniform1ui(texUnitConfigLoc, texUnitConfig); } // TODO: Actually use this - float viewportWidth = f24::fromRaw(regs[PICAInternalRegs::ViewportWidth] & 0xffffff).toFloat32() * 2.0; - float viewportHeight = f24::fromRaw(regs[PICAInternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0; + float viewportWidth = f24::fromRaw(regs[PICA::InternalRegs::ViewportWidth] & 0xffffff).toFloat32() * 2.0; + float viewportHeight = f24::fromRaw(regs[PICA::InternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0; OpenGL::setViewport(viewportWidth, viewportHeight); // Note: The code below must execute after we've bound the colour buffer & its framebuffer @@ -429,8 +429,8 @@ void Renderer::bindDepthBuffer() { tex = depthBufferCache.add(sampleBuffer).texture.m_handle; } - if (PICADepthFmt::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?"); - auto attachment = depthBufferFormat == PICADepthFmt::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; + if (PICA::DepthFmt::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?"); + auto attachment = depthBufferFormat == PICA::DepthFmt::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0); } From 5f07f77c946c640640a8199286171ae64d6162e1 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sat, 17 Jun 2023 23:27:19 -0700 Subject: [PATCH 3/5] Move `hasStencil` to `regs.hpp` --- include/PICA/regs.hpp | 2 ++ include/renderer_gl/surfaces.hpp | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index c5da123a..657fb6f3 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -150,6 +150,8 @@ namespace PICA { Depth24Stencil8 = 3, }; + inline constexpr bool hasStencil(DepthFmt format) { return format == PICA::DepthFmt::Depth24Stencil8; } + // Size occupied by each pixel in bytes // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) diff --git a/include/renderer_gl/surfaces.hpp b/include/renderer_gl/surfaces.hpp index f6d5230d..7ff36c6d 100644 --- a/include/renderer_gl/surfaces.hpp +++ b/include/renderer_gl/surfaces.hpp @@ -95,10 +95,6 @@ struct DepthBuffer { range = Interval(loc, (u32)endLoc); } - bool hasStencil() { - return format == PICA::DepthFmt::Depth24Stencil8; - } - void allocate() { // Create texture for the FBO, setting up filters and the like // Reading back the current texture is slow, but allocate calls should be few and far between. From 134e16d8ea24987a8c5b5bc9d57d703f6998401f Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sun, 18 Jun 2023 00:10:01 -0700 Subject: [PATCH 4/5] Replace `Texture::Formats` with `PICA::ColorFmt` This enum was a duplicate of the PICA one. Now the PICA one is more complete. Migrate `textureFormatToString` to be next to the enums definition. --- include/PICA/regs.hpp | 47 ++++++++++++---- include/renderer_gl/textures.hpp | 31 ++--------- src/core/renderer_gl/renderer_gl.cpp | 2 +- src/core/renderer_gl/textures.cpp | 80 +++++++++++----------------- 4 files changed, 72 insertions(+), 88 deletions(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 657fb6f3..9a011cc4 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -131,16 +131,20 @@ namespace PICA { } enum class ColorFmt : u32 { - RGBA8 = 0, - BGR8 = 1, - RGB5A1 = 2, - RGB565 = 3, - RGBA4 = 4, - - // Technically selectable, but their function is unknown - Unknown5 = 5, - Unknown6 = 6, - Unknown7 = 7, + RGBA8 = 0x0, + RGB8 = 0x1, + RGBA5551 = 0x2, + RGB565 = 0x3, + RGBA4 = 0x4, + IA8 = 0x5, + RG8 = 0x6, + I8 = 0x7, + A8 = 0x8, + IA4 = 0x9, + I4 = 0xA, + A4 = 0xB, + ETC1 = 0xC, + ETC1A4 = 0xD, }; enum class DepthFmt : u32 { @@ -150,6 +154,27 @@ namespace PICA { Depth24Stencil8 = 3, }; + // Returns the string representation of a texture format + inline constexpr const char* textureFormatToString(ColorFmt fmt) { + switch (fmt) { + case ColorFmt::RGBA8: return "RGBA8"; + case ColorFmt::RGB8: return "RGB8"; + case ColorFmt::RGBA5551: return "RGBA5551"; + case ColorFmt::RGB565: return "RGB565"; + case ColorFmt::RGBA4: return "RGBA4"; + case ColorFmt::IA8: return "IA8"; + case ColorFmt::RG8: return "RG8"; + case ColorFmt::I8: return "I8"; + case ColorFmt::A8: return "A8"; + case ColorFmt::IA4: return "IA4"; + case ColorFmt::I4: return "I4"; + case ColorFmt::A4: return "A4"; + case ColorFmt::ETC1: return "ETC1"; + case ColorFmt::ETC1A4: return "ETC1A4"; + default: return "Unknown"; + } + } + inline constexpr bool hasStencil(DepthFmt format) { return format == PICA::DepthFmt::Depth24Stencil8; } // Size occupied by each pixel in bytes @@ -157,7 +182,7 @@ namespace PICA { // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) inline constexpr usize sizePerPixel(ColorFmt format) { switch (format) { - case ColorFmt::BGR8: return 3; + case ColorFmt::RGB8: return 3; case ColorFmt::RGBA8: return 4; default: return 2; } diff --git a/include/renderer_gl/textures.hpp b/include/renderer_gl/textures.hpp index 3cf7871c..4e54de2d 100644 --- a/include/renderer_gl/textures.hpp +++ b/include/renderer_gl/textures.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include "PICA/regs.hpp" #include "boost/icl/interval.hpp" #include "helpers.hpp" #include "opengl.hpp" @@ -9,28 +10,9 @@ template using Interval = boost::icl::right_open_interval; struct Texture { - enum class Formats : u32 { - RGBA8 = 0, - RGB8 = 1, - RGBA5551 = 2, - RGB565 = 3, - RGBA4 = 4, - IA8 = 5, - RG8 = 6, - I8 = 7, - A8 = 8, - IA4 = 9, - I4 = 10, - A4 = 11, - ETC1 = 12, - ETC1A4 = 13, - - Trash1 = 14, Trash2 = 15 // TODO: What are these? - }; - u32 location; u32 config; // Magnification/minification filter, wrapping configs, etc - Formats format; + PICA::ColorFmt format; OpenGL::uvec2 size; bool valid; @@ -41,7 +23,7 @@ struct Texture { Texture() : valid(false) {} - Texture(u32 loc, Formats format, u32 x, u32 y, u32 config, bool valid = true) + Texture(u32 loc, PICA::ColorFmt format, u32 x, u32 y, u32 config, bool valid = true) : location(loc), format(format), size({x, y}), config(config), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -62,7 +44,7 @@ struct Texture { void free(); u64 sizeInBytes(); - u32 decodeTexel(u32 u, u32 v, Formats fmt, const void* data); + u32 decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data); // Get the morton interleave offset of a texel based on its U and V values static u32 mortonInterleave(u32 u, u32 v); @@ -70,12 +52,9 @@ struct Texture { static u32 getSwizzledOffset(u32 u, u32 v, u32 width, u32 bytesPerPixel); static u32 getSwizzledOffset_4bpp(u32 u, u32 v, u32 width); - // Returns the string representation of a texture format - static std::string textureFormatToString(Formats fmt); - // Returns the format of this texture as a string std::string formatToString() { - return textureFormatToString(format); + return PICA::textureFormatToString(format); } // Returns the texel at coordinates (u, v) of an ETC1(A4) texture diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index ab93af73..06748708 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -322,7 +322,7 @@ void Renderer::drawVertices(PICA::PrimType primType, std::span ver const u32 addr = (regs[0x85] & 0x0FFFFFFF) << 3; const u32 format = regs[0x8E] & 0xF; - Texture targetTex(addr, static_cast(format), width, height, config); + Texture targetTex(addr, static_cast(format), width, height, config); OpenGL::Texture tex = getTexture(targetTex); tex.bind(); } diff --git a/src/core/renderer_gl/textures.cpp b/src/core/renderer_gl/textures.cpp index f59d0779..b82653d5 100644 --- a/src/core/renderer_gl/textures.cpp +++ b/src/core/renderer_gl/textures.cpp @@ -43,34 +43,34 @@ u64 Texture::sizeInBytes() { u64 pixelCount = u64(size.x()) * u64(size.y()); switch (format) { - case Formats::RGBA8: // 4 bytes per pixel + case PICA::ColorFmt::RGBA8: // 4 bytes per pixel return pixelCount * 4; - case Formats::RGB8: // 3 bytes per pixel + case PICA::ColorFmt::RGB8: // 3 bytes per pixel return pixelCount * 3; - case Formats::RGBA5551: // 2 bytes per pixel - case Formats::RGB565: - case Formats::RGBA4: - case Formats::RG8: - case Formats::IA8: + case PICA::ColorFmt::RGBA5551: // 2 bytes per pixel + case PICA::ColorFmt::RGB565: + case PICA::ColorFmt::RGBA4: + case PICA::ColorFmt::RG8: + case PICA::ColorFmt::IA8: return pixelCount * 2; - case Formats::A8: // 1 byte per pixel - case Formats::I8: - case Formats::IA4: + case PICA::ColorFmt::A8: // 1 byte per pixel + case PICA::ColorFmt::I8: + case PICA::ColorFmt::IA4: return pixelCount; - case Formats::I4: // 4 bits per pixel - case Formats::A4: + case PICA::ColorFmt::I4: // 4 bits per pixel + case PICA::ColorFmt::A4: return pixelCount / 2; - case Formats::ETC1: // Compressed formats - case Formats::ETC1A4: { + case PICA::ColorFmt::ETC1: // Compressed formats + case PICA::ColorFmt::ETC1A4: { // Number of 4x4 tiles const u64 tileCount = pixelCount / 16; // Tiles are 8 bytes each on ETC1 and 16 bytes each on ETC1A4 - const u64 tileSize = format == Formats::ETC1 ? 8 : 16; + const u64 tileSize = format == PICA::ColorFmt::ETC1 ? 8 : 16; return tileCount * tileSize; } @@ -111,9 +111,9 @@ u32 Texture::getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) { // Get the texel at position (u, v) // fmt: format of the texture // data: texture data of the texture -u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { +u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { switch (fmt) { - case Formats::RGBA4: { + case PICA::ColorFmt::RGBA4: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -126,7 +126,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case Formats::RGBA5551: { + case PICA::ColorFmt::RGBA5551: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -139,7 +139,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case Formats::RGB565: { + case PICA::ColorFmt::RGB565: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -151,7 +151,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case Formats::RG8: { + case PICA::ColorFmt::RG8: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); @@ -162,7 +162,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case Formats::RGB8: { + case PICA::ColorFmt::RGB8: { u32 offset = getSwizzledOffset(u, v, size.u(), 3); auto ptr = static_cast(data); @@ -173,7 +173,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case Formats::RGBA8: { + case PICA::ColorFmt::RGBA8: { u32 offset = getSwizzledOffset(u, v, size.u(), 4); auto ptr = static_cast(data); @@ -185,7 +185,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case Formats::IA4: { + case PICA::ColorFmt::IA4: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); @@ -197,7 +197,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case Formats::A4: { + case PICA::ColorFmt::A4: { u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); auto ptr = static_cast(data); @@ -209,7 +209,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (alpha << 24) | (0 << 16) | (0 << 8) | 0; } - case Formats::A8: { + case PICA::ColorFmt::A8: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); const u8 alpha = ptr[offset]; @@ -218,7 +218,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (alpha << 24) | (0 << 16) | (0 << 8) | 0; } - case Formats::I4: { + case PICA::ColorFmt::I4: { u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); auto ptr = static_cast(data); @@ -230,7 +230,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case Formats::I8: { + case PICA::ColorFmt::I8: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); const u8 intensity = ptr[offset]; @@ -239,7 +239,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case Formats::IA8: { + case PICA::ColorFmt::IA8: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); @@ -249,8 +249,8 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) { return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case Formats::ETC1: return getTexelETC(false, u, v, size.u(), data); - case Formats::ETC1A4: return getTexelETC(true, u, v, size.u(), data); + case PICA::ColorFmt::ETC1: return getTexelETC(false, u, v, size.u(), data); + case PICA::ColorFmt::ETC1A4: return getTexelETC(true, u, v, size.u(), data); default: Helpers::panic("[Texture::DecodeTexel] Unimplemented format = %d", static_cast(fmt)); @@ -271,24 +271,4 @@ void Texture::decodeTexture(const void* data) { texture.bind(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.u(), size.v(), GL_RGBA, GL_UNSIGNED_BYTE, decoded.data()); -} - -std::string Texture::textureFormatToString(Texture::Formats fmt) { - switch (fmt) { - case Formats::A4: return "A4"; - case Formats::A8: return "A8"; - case Formats::ETC1: return "ETC1"; - case Formats::ETC1A4: return "ETC1A4"; - case Formats::I4: return "I4"; - case Formats::I8: return "I8"; - case Formats::IA4: return "IA4"; - case Formats::IA8: return "IA8"; - case Formats::RG8: return "RG8"; - case Formats::RGB565: return "RGB565"; - case Formats::RGB8: return "RGB8"; - case Formats::RGBA4: return "RGBA4"; - case Formats::RGBA5551: return "RGBA5551"; - case Formats::RGBA8: return "RGBA8"; - default: return "Unknown"; - } } \ No newline at end of file From 6ee3f733351bc1b7f1c737eaccf57e31a3388849 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sun, 18 Jun 2023 08:13:17 -0700 Subject: [PATCH 5/5] Bisect `TextureFmt` and `ColorFmt` Makes framebuffer-formats unrepresentable from texture formats while allowing them to alias each other. Add utility functions as well that just re-use the `TextureFmt` ones. --- include/PICA/regs.hpp | 54 ++++++++++++++++--------- include/renderer_gl/renderer_gl.hpp | 2 +- include/renderer_gl/textures.hpp | 6 +-- src/core/renderer_gl/renderer_gl.cpp | 2 +- src/core/renderer_gl/textures.cpp | 60 ++++++++++++++-------------- 5 files changed, 70 insertions(+), 54 deletions(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 9a011cc4..7b726974 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -130,7 +130,7 @@ namespace PICA { }; } - enum class ColorFmt : u32 { + enum class TextureFmt : u32 { RGBA8 = 0x0, RGB8 = 0x1, RGBA5551 = 0x2, @@ -147,6 +147,14 @@ namespace PICA { ETC1A4 = 0xD, }; + enum class ColorFmt : u32 { + RGBA8 = 0x0, + RGB8 = 0x1, + RGBA5551 = 0x2, + RGB565 = 0x3, + RGBA4 = 0x4, + }; + enum class DepthFmt : u32 { Depth16 = 0, Unknown1 = 1, // Technically selectable, but function is unknown @@ -155,39 +163,47 @@ namespace PICA { }; // Returns the string representation of a texture format - inline constexpr const char* textureFormatToString(ColorFmt fmt) { + inline constexpr const char* textureFormatToString(TextureFmt fmt) { switch (fmt) { - case ColorFmt::RGBA8: return "RGBA8"; - case ColorFmt::RGB8: return "RGB8"; - case ColorFmt::RGBA5551: return "RGBA5551"; - case ColorFmt::RGB565: return "RGB565"; - case ColorFmt::RGBA4: return "RGBA4"; - case ColorFmt::IA8: return "IA8"; - case ColorFmt::RG8: return "RG8"; - case ColorFmt::I8: return "I8"; - case ColorFmt::A8: return "A8"; - case ColorFmt::IA4: return "IA4"; - case ColorFmt::I4: return "I4"; - case ColorFmt::A4: return "A4"; - case ColorFmt::ETC1: return "ETC1"; - case ColorFmt::ETC1A4: return "ETC1A4"; + case TextureFmt::RGBA8: return "RGBA8"; + case TextureFmt::RGB8: return "RGB8"; + case TextureFmt::RGBA5551: return "RGBA5551"; + case TextureFmt::RGB565: return "RGB565"; + case TextureFmt::RGBA4: return "RGBA4"; + case TextureFmt::IA8: return "IA8"; + case TextureFmt::RG8: return "RG8"; + case TextureFmt::I8: return "I8"; + case TextureFmt::A8: return "A8"; + case TextureFmt::IA4: return "IA4"; + case TextureFmt::I4: return "I4"; + case TextureFmt::A4: return "A4"; + case TextureFmt::ETC1: return "ETC1"; + case TextureFmt::ETC1A4: return "ETC1A4"; default: return "Unknown"; } } + inline constexpr const char* textureFormatToString(ColorFmt fmt) { + return textureFormatToString(static_cast(fmt)); + } + inline constexpr bool hasStencil(DepthFmt format) { return format == PICA::DepthFmt::Depth24Stencil8; } // Size occupied by each pixel in bytes // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) - inline constexpr usize sizePerPixel(ColorFmt format) { + inline constexpr usize sizePerPixel(TextureFmt format) { switch (format) { - case ColorFmt::RGB8: return 3; - case ColorFmt::RGBA8: return 4; + case TextureFmt::RGB8: return 3; + case TextureFmt::RGBA8: return 4; default: return 2; } } + inline constexpr usize sizePerPixel(ColorFmt format) { + return sizePerPixel(static_cast(format)); + } + inline constexpr usize sizePerPixel(DepthFmt format) { switch (format) { case DepthFmt::Depth16: return 2; diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 383fa484..a41cfe87 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -46,7 +46,7 @@ class Renderer { OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)' - u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer + u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer PICA::ColorFmt colourBufferFormat; // Format of the colours stored in the colour buffer // Same for the depth/stencil buffer diff --git a/include/renderer_gl/textures.hpp b/include/renderer_gl/textures.hpp index 4e54de2d..5469a59f 100644 --- a/include/renderer_gl/textures.hpp +++ b/include/renderer_gl/textures.hpp @@ -12,7 +12,7 @@ using Interval = boost::icl::right_open_interval; struct Texture { u32 location; u32 config; // Magnification/minification filter, wrapping configs, etc - PICA::ColorFmt format; + PICA::TextureFmt format; OpenGL::uvec2 size; bool valid; @@ -23,7 +23,7 @@ struct Texture { Texture() : valid(false) {} - Texture(u32 loc, PICA::ColorFmt format, u32 x, u32 y, u32 config, bool valid = true) + Texture(u32 loc, PICA::TextureFmt format, u32 x, u32 y, u32 config, bool valid = true) : location(loc), format(format), size({x, y}), config(config), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -44,7 +44,7 @@ struct Texture { void free(); u64 sizeInBytes(); - u32 decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data); + u32 decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data); // Get the morton interleave offset of a texel based on its U and V values static u32 mortonInterleave(u32 u, u32 v); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 06748708..e6297d86 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -322,7 +322,7 @@ void Renderer::drawVertices(PICA::PrimType primType, std::span ver const u32 addr = (regs[0x85] & 0x0FFFFFFF) << 3; const u32 format = regs[0x8E] & 0xF; - Texture targetTex(addr, static_cast(format), width, height, config); + Texture targetTex(addr, static_cast(format), width, height, config); OpenGL::Texture tex = getTexture(targetTex); tex.bind(); } diff --git a/src/core/renderer_gl/textures.cpp b/src/core/renderer_gl/textures.cpp index b82653d5..a806e1eb 100644 --- a/src/core/renderer_gl/textures.cpp +++ b/src/core/renderer_gl/textures.cpp @@ -43,34 +43,34 @@ u64 Texture::sizeInBytes() { u64 pixelCount = u64(size.x()) * u64(size.y()); switch (format) { - case PICA::ColorFmt::RGBA8: // 4 bytes per pixel + case PICA::TextureFmt::RGBA8: // 4 bytes per pixel return pixelCount * 4; - case PICA::ColorFmt::RGB8: // 3 bytes per pixel + case PICA::TextureFmt::RGB8: // 3 bytes per pixel return pixelCount * 3; - case PICA::ColorFmt::RGBA5551: // 2 bytes per pixel - case PICA::ColorFmt::RGB565: - case PICA::ColorFmt::RGBA4: - case PICA::ColorFmt::RG8: - case PICA::ColorFmt::IA8: + case PICA::TextureFmt::RGBA5551: // 2 bytes per pixel + case PICA::TextureFmt::RGB565: + case PICA::TextureFmt::RGBA4: + case PICA::TextureFmt::RG8: + case PICA::TextureFmt::IA8: return pixelCount * 2; - case PICA::ColorFmt::A8: // 1 byte per pixel - case PICA::ColorFmt::I8: - case PICA::ColorFmt::IA4: + case PICA::TextureFmt::A8: // 1 byte per pixel + case PICA::TextureFmt::I8: + case PICA::TextureFmt::IA4: return pixelCount; - case PICA::ColorFmt::I4: // 4 bits per pixel - case PICA::ColorFmt::A4: + case PICA::TextureFmt::I4: // 4 bits per pixel + case PICA::TextureFmt::A4: return pixelCount / 2; - case PICA::ColorFmt::ETC1: // Compressed formats - case PICA::ColorFmt::ETC1A4: { + case PICA::TextureFmt::ETC1: // Compressed formats + case PICA::TextureFmt::ETC1A4: { // Number of 4x4 tiles const u64 tileCount = pixelCount / 16; // Tiles are 8 bytes each on ETC1 and 16 bytes each on ETC1A4 - const u64 tileSize = format == PICA::ColorFmt::ETC1 ? 8 : 16; + const u64 tileSize = format == PICA::TextureFmt::ETC1 ? 8 : 16; return tileCount * tileSize; } @@ -111,9 +111,9 @@ u32 Texture::getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) { // Get the texel at position (u, v) // fmt: format of the texture // data: texture data of the texture -u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { +u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) { switch (fmt) { - case PICA::ColorFmt::RGBA4: { + case PICA::TextureFmt::RGBA4: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -126,7 +126,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGBA5551: { + case PICA::TextureFmt::RGBA5551: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -139,7 +139,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGB565: { + case PICA::TextureFmt::RGB565: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -151,7 +151,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RG8: { + case PICA::TextureFmt::RG8: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); @@ -162,7 +162,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGB8: { + case PICA::TextureFmt::RGB8: { u32 offset = getSwizzledOffset(u, v, size.u(), 3); auto ptr = static_cast(data); @@ -173,7 +173,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGBA8: { + case PICA::TextureFmt::RGBA8: { u32 offset = getSwizzledOffset(u, v, size.u(), 4); auto ptr = static_cast(data); @@ -185,7 +185,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::IA4: { + case PICA::TextureFmt::IA4: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); @@ -197,7 +197,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::A4: { + case PICA::TextureFmt::A4: { u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); auto ptr = static_cast(data); @@ -209,7 +209,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (0 << 16) | (0 << 8) | 0; } - case PICA::ColorFmt::A8: { + case PICA::TextureFmt::A8: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); const u8 alpha = ptr[offset]; @@ -218,7 +218,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (0 << 16) | (0 << 8) | 0; } - case PICA::ColorFmt::I4: { + case PICA::TextureFmt::I4: { u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); auto ptr = static_cast(data); @@ -230,7 +230,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::I8: { + case PICA::TextureFmt::I8: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); const u8 intensity = ptr[offset]; @@ -239,7 +239,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::IA8: { + case PICA::TextureFmt::IA8: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); @@ -249,8 +249,8 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::ETC1: return getTexelETC(false, u, v, size.u(), data); - case PICA::ColorFmt::ETC1A4: return getTexelETC(true, u, v, size.u(), data); + case PICA::TextureFmt::ETC1: return getTexelETC(false, u, v, size.u(), data); + case PICA::TextureFmt::ETC1A4: return getTexelETC(true, u, v, size.u(), data); default: Helpers::panic("[Texture::DecodeTexel] Unimplemented format = %d", static_cast(fmt));