[PICA] More textures. Upstream should also build now

This commit is contained in:
wheremyfoodat 2023-02-01 01:53:51 +02:00
parent 51130b295a
commit ccdab41c28
5 changed files with 66 additions and 36 deletions

View file

@ -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!");
}

View file

@ -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);

View file

@ -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];
}

View file

@ -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<Texture::Formats>(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<void*>(tex.location); // Get pointer to the texture data in 3DS memory
Texture& newTex = textureCache.add(tex);
newTex.decodeTexture(textureData);
return newTex.texture;
}
}

View file

@ -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<u8*>(data);
auto ptr = static_cast<const u8*>(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<u32> decoded;
decoded.reserve(size.u() * size.v());