diff --git a/include/renderer_gl/surface_cache.hpp b/include/renderer_gl/surface_cache.hpp index 4980c1a4..97a6d05e 100644 --- a/include/renderer_gl/surface_cache.hpp +++ b/include/renderer_gl/surface_cache.hpp @@ -41,7 +41,7 @@ public: } // Adds a surface object to the cache and returns it - SurfaceType add(const SurfaceType& surface) { + SurfaceType& add(const SurfaceType& surface) { if (size >= capacity) { Helpers::panic("Surface cache full! Add emptying!"); } diff --git a/include/renderer_gl/textures.hpp b/include/renderer_gl/textures.hpp index e6ebaecf..955c7cc3 100644 --- a/include/renderer_gl/textures.hpp +++ b/include/renderer_gl/textures.hpp @@ -55,11 +55,11 @@ struct Texture { } void allocate(); - void decodeTexture(void* data); + void decodeTexture(const void* data); void free(); u64 sizeInBytes(); - u32 decodeTexel(u32 u, u32 v, Formats fmt, void* data); + u32 decodeTexel(u32 u, u32 v, Formats 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/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index 632ee75a..a8da36b7 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -5,7 +5,7 @@ using namespace Floats; -GPU::GPU(Memory& mem) : mem(mem), renderer(regs) { +GPU::GPU(Memory& mem) : mem(mem), renderer(*this, regs) { vram = new u8[vramSize]; } diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 48c66ad4..eafc7284 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -1,5 +1,6 @@ #include "renderer_gl/renderer_gl.hpp" #include "PICA/float_types.hpp" +#include "PICA/gpu.hpp" #include "PICA/regs.hpp" using namespace Floats; @@ -108,6 +109,7 @@ const char* displayFragmentShader = R"( void Renderer::reset() { depthBufferCache.reset(); colourBufferCache.reset(); + textureCache.reset(); // Init the colour/depth buffer settings to some random defaults on reset colourBufferLoc = 0; @@ -183,6 +185,16 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c //if (depthScale.toFloat32() != -1.0 || depthOffset.toFloat32() != 0.0) // Helpers::panic("TODO: Implement depth scale/offset. Remove the depth *= -1.0 from vertex shader"); + if (regs[0x80] & 1) { + u32 dim = regs[0x82]; + u32 height = dim & 0x7ff; + u32 width = (dim >> 16) & 0x7ff; + u32 addr = (regs[0x85] & 0x0FFFFFFF) << 3; + u32 format = regs[0x8E] & 0xF; + + Texture targetTex(addr, static_cast(format), width, height); + OpenGL::Texture tex = getTexture(targetTex); + } // TODO: Actually use this float viewportWidth = f24::fromRaw(regs[PICAInternalRegs::ViewportWidth] & 0xffffff).toFloat32() * 2.0; @@ -259,4 +271,19 @@ OpenGL::Framebuffer Renderer::getColourFBO() { } else { return colourBufferCache.add(sampleBuffer).fbo; } +} + +OpenGL::Texture Renderer::getTexture(Texture& tex) { + // Similar logic as the getColourFBO/getDepthBuffer functions + auto buffer = textureCache.find(tex); + + if (buffer.has_value()) { + return buffer.value().get().texture; + } else { + const void* textureData = gpu.getPointerPhys(tex.location); // Get pointer to the texture data in 3DS memory + Texture& newTex = textureCache.add(tex); + newTex.decodeTexture(textureData); + + return newTex.texture; + } } \ No newline at end of file diff --git a/src/core/renderer_gl/textures.cpp b/src/core/renderer_gl/textures.cpp index 30dd71b8..dc1ae6aa 100644 --- a/src/core/renderer_gl/textures.cpp +++ b/src/core/renderer_gl/textures.cpp @@ -2,7 +2,7 @@ #include "colour.hpp" void Texture::allocate() { - Helpers::panic("Tried to allocate texture"); + printf("Tried to allocate texture\n"); } void Texture::free() { @@ -16,40 +16,40 @@ u64 Texture::sizeInBytes() { u64 pixelCount = u64(size.x()) * u64(size.y()); switch (format) { - case Formats::RGBA8: // 4 bytes per pixel - return pixelCount * 4; + case Formats::RGBA8: // 4 bytes per pixel + return pixelCount * 4; - case Formats::RGB8: // 3 bytes per pixel - return pixelCount * 3; + case Formats::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: - return pixelCount * 2; + case Formats::RGBA5551: // 2 bytes per pixel + case Formats::RGB565: + case Formats::RGBA4: + case Formats::RG8: + case Formats::IA8: + return pixelCount * 2; - case Formats::A8: // 1 byte per pixel - case Formats::I8: - case Formats::IA4: - return pixelCount; + case Formats::A8: // 1 byte per pixel + case Formats::I8: + case Formats::IA4: + return pixelCount; - case Formats::I4: // 4 bits per pixel - case Formats::A4: - return pixelCount / 2; + case Formats::I4: // 4 bits per pixel + case Formats::A4: + return pixelCount / 2; - case Formats::ETC1: // Compressed formats - case Formats::ETC1A4: { - // Number of 8x8 tiles - const u64 tileCount = pixelCount / 64; - // Each 8x8 consists of 4 4x4 tiles, which are 8 bytes each on ETC1 and 16 bytes each on ETC1A4 - const u64 tileSize = 4 * (format == Formats::ETC1 ? 8 : 16); - return tileCount * tileSize; - } + case Formats::ETC1: // Compressed formats + case Formats::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; + return tileCount * tileSize; + } - default: - Helpers::panic("[PICA] Attempted to get size of invalid texture type"); - } + default: + Helpers::panic("[PICA] Attempted to get size of invalid texture type"); + } } // u and v are the UVs of the relevant texel @@ -73,11 +73,14 @@ u32 Texture::getSwizzledOffset(u32 u, u32 v, u32 width, u32 bytesPerPixel) { return offset * bytesPerPixel; } -u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, void* data) { +// 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) { switch (fmt) { case Formats::RGBA4: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); - u8* ptr = static_cast(data); + auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); u8 alpha = Colour::convert4To8Bit(texel & 0xf); @@ -93,7 +96,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, void* data) { } } -void Texture::decodeTexture(void* data) { +void Texture::decodeTexture(const void* data) { std::vector decoded; decoded.reserve(size.u() * size.v());