Add Helpers:{getBits,getBit}

`constexpr` functions for extractint bitfields that lends itself a bit
better to emitting instructions like `bextr` on x86 or `ubfx` on arm64.
And may subjectively make things a bit more readable.
"Extract `5` bits" rather than `& 0x1F`.
This commit is contained in:
Wunkolo 2023-06-09 21:28:46 -07:00
parent c7e3343974
commit 2c94d0d683
9 changed files with 180 additions and 147 deletions

View file

@ -3,6 +3,8 @@
#include "renderer_gl/renderer_gl.hpp"
#include "renderer_gl/textures.hpp"
using namespace Helpers;
static constexpr u32 signExtend3To32(u32 val) {
return (u32)(s32(val) << 29 >> 29);
}
@ -58,14 +60,14 @@ u32 Texture::decodeETC(u32 alpha, u32 u, u32 v, u64 colourData) {
};
// Parse colour data for 4x4 block
const u32 subindices = colourData & 0xffff;
const u32 negationFlags = (colourData >> 16) & 0xffff;
const bool flip = (colourData >> 32) & 1;
const bool diffMode = (colourData >> 33) & 1;
const u32 subindices = getBits<0, 16>(colourData);
const u32 negationFlags = getBits<16, 16>(colourData);
const bool flip = getBit<32>(colourData);
const bool diffMode = getBit<33>(colourData);
// Note: index1 is indeed stored on the higher bits, with index2 in the lower bits
const u32 tableIndex1 = (colourData >> 37) & 7;
const u32 tableIndex2 = (colourData >> 34) & 7;
const u32 tableIndex1 = getBits<37, 3>(colourData);
const u32 tableIndex2 = getBits<34, 3>(colourData);
const u32 texelIndex = u * 4 + v; // Index of the texel in the block
if (flip)
@ -73,14 +75,14 @@ u32 Texture::decodeETC(u32 alpha, u32 u, u32 v, u64 colourData) {
s32 r, g, b;
if (diffMode) {
r = (colourData >> 59) & 0x1f;
g = (colourData >> 51) & 0x1f;
b = (colourData >> 43) & 0x1f;
r = getBits<59, 5>(colourData);
g = getBits<51, 5>(colourData);
b = getBits<43, 5>(colourData);
if (u >= 2) {
r += signExtend3To32((colourData >> 56) & 0x7);
g += signExtend3To32((colourData >> 48) & 0x7);
b += signExtend3To32((colourData >> 40) & 0x7);
r += signExtend3To32(getBits<56, 3>(colourData));
g += signExtend3To32(getBits<48, 3>(colourData));
b += signExtend3To32(getBits<40, 3>(colourData));
}
// Expand from 5 to 8 bits per channel
@ -89,13 +91,13 @@ u32 Texture::decodeETC(u32 alpha, u32 u, u32 v, u64 colourData) {
b = Colour::convert5To8Bit(b);
} else {
if (u < 2) {
r = (colourData >> 60) & 0xf;
g = (colourData >> 52) & 0xf;
b = (colourData >> 44) & 0xf;
r = getBits<60, 4>(colourData);
g = getBits<52, 4>(colourData);
b = getBits<44, 4>(colourData);
} else {
r = (colourData >> 56) & 0xf;
g = (colourData >> 48) & 0xf;
b = (colourData >> 40) & 0xf;
r = getBits<56, 4>(colourData);
g = getBits<48, 4>(colourData);
b = getBits<40, 4>(colourData);
}
// Expand from 4 to 8 bits per channel

View file

@ -4,6 +4,7 @@
#include "PICA/regs.hpp"
using namespace Floats;
using namespace Helpers;
// This is all hacked up to display our first triangle
@ -243,19 +244,19 @@ void Renderer::setupBlending() {
// Get blending equations
const u32 blendControl = regs[PICAInternalRegs::BlendFunc];
const u32 rgbEquation = blendControl & 0x7;
const u32 alphaEquation = (blendControl >> 8) & 0x7;
const u32 alphaEquation = getBits<8, 3>(blendControl);
// Get blending functions
const u32 rgbSourceFunc = (blendControl >> 16) & 0xf;
const u32 rgbDestFunc = (blendControl >> 20) & 0xf;
const u32 alphaSourceFunc = (blendControl >> 24) & 0xf;
const u32 alphaDestFunc = (blendControl >> 28) & 0xf;
const u32 rgbSourceFunc = getBits<16, 4>(blendControl);
const u32 rgbDestFunc = getBits<20, 4>(blendControl);
const u32 alphaSourceFunc = getBits<24, 4>(blendControl);
const u32 alphaDestFunc = getBits<28, 4>(blendControl);
const u32 constantColor = regs[PICAInternalRegs::BlendColour];
const u32 r = constantColor & 0xff;
const u32 g = (constantColor >> 8) & 0xff;
const u32 b = (constantColor >> 16) & 0xff;
const u32 a = (constantColor >> 24) & 0xff;
const u32 g = getBits<8, 8>(constantColor);
const u32 b = getBits<16, 8>(constantColor);
const u32 a = getBits<24, 8>(constantColor);
OpenGL::setBlendColor(float(r) / 255.f, float(g) / 255.f, float(b) / 255.f, float(a) / 255.f);
// Translate equations and funcs to their GL equivalents and set them
@ -278,9 +279,9 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c
const u32 depthControl = regs[PICAInternalRegs::DepthAndColorMask];
const bool depthEnable = depthControl & 1;
const bool depthWriteEnable = (depthControl >> 12) & 1;
const int depthFunc = (depthControl >> 4) & 7;
const int colourMask = (depthControl >> 8) & 0xf;
const bool depthWriteEnable = getBit<12>(depthControl);
const int depthFunc = getBits<4, 3>(depthControl);
const int colourMask = getBits<8, 4>(depthControl);
glColorMask(colourMask & 1, colourMask & 2, colourMask & 4, colourMask & 8);
static constexpr std::array<GLenum, 8> depthModes = {
@ -312,7 +313,7 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c
const u32 dim = regs[0x82];
const u32 config = regs[0x83];
const u32 height = dim & 0x7ff;
const u32 width = (dim >> 16) & 0x7ff;
const u32 width = getBits<16, 11>(dim);
const u32 addr = (regs[0x85] & 0x0FFFFFFF) << 3;
const u32 format = regs[0x8E] & 0xF;
@ -379,9 +380,9 @@ void Renderer::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 cont
return;
log("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control);
const float r = float((value >> 24) & 0xff) / 255.0;
const float g = float((value >> 16) & 0xff) / 255.0;
const float b = float((value >> 8) & 0xff) / 255.0;
const float r = float(getBits<24, 8>(value)) / 255.0;
const float g = float(getBits<16, 8>(value)) / 255.0;
const float b = float(getBits<8, 8>(value)) / 255.0;
const float a = float(value & 0xff) / 255.0;
if (startAddress == topScreenBuffer) {

View file

@ -2,6 +2,8 @@
#include "colour.hpp"
#include <array>
using namespace Helpers;
void Texture::allocate() {
glGenTextures(1, &texture.m_handle);
texture.create(size.u(), size.v(), GL_RGBA8);
@ -21,8 +23,8 @@ void Texture::setNewConfig(u32 cfg) {
const auto magFilter = (cfg & 0x2) != 0 ? OpenGL::Linear : OpenGL::Nearest;
const auto minFilter = (cfg & 0x4) != 0 ? OpenGL::Linear : OpenGL::Nearest;
const auto wrapT = wrappingModes[(cfg >> 8) & 0x7];
const auto wrapS = wrappingModes[(cfg >> 12) & 0x7];
const auto wrapT = wrappingModes[getBits<8, 3>(cfg)];
const auto wrapS = wrappingModes[getBits<12, 3>(cfg)];
texture.setMinFilter(minFilter);
texture.setMagFilter(magFilter);
@ -116,10 +118,10 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
auto ptr = static_cast<const u8*>(data);
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
u8 alpha = Colour::convert4To8Bit(texel & 0xf);
u8 b = Colour::convert4To8Bit((texel >> 4) & 0xf);
u8 g = Colour::convert4To8Bit((texel >> 8) & 0xf);
u8 r = Colour::convert4To8Bit((texel >> 12) & 0xf);
u8 alpha = Colour::convert4To8Bit(getBits<0, 4>(texel));
u8 b = Colour::convert4To8Bit(getBits<4, 4>(texel));
u8 g = Colour::convert4To8Bit(getBits<8, 4>(texel));
u8 r = Colour::convert4To8Bit(getBits<12, 4>(texel));
return (alpha << 24) | (b << 16) | (g << 8) | r;
}
@ -129,10 +131,10 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
auto ptr = static_cast<const u8*>(data);
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
u8 alpha = (texel & 1) ? 0xff : 0;
u8 b = Colour::convert5To8Bit((texel >> 1) & 0x1f);
u8 g = Colour::convert5To8Bit((texel >> 6) & 0x1f);
u8 r = Colour::convert5To8Bit((texel >> 11) & 0x1f);
u8 alpha = getBit<0>(texel) ? 0xff : 0;
u8 b = Colour::convert5To8Bit(getBits<1, 5>(texel));
u8 g = Colour::convert5To8Bit(getBits<6, 5>(texel));
u8 r = Colour::convert5To8Bit(getBits<11, 5>(texel));
return (alpha << 24) | (b << 16) | (g << 8) | r;
}
@ -142,9 +144,9 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
auto ptr = static_cast<const u8*>(data);
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
u8 b = Colour::convert5To8Bit(texel & 0x1f);
u8 g = Colour::convert6To8Bit((texel >> 5) & 0x3f);
u8 r = Colour::convert5To8Bit((texel >> 11) & 0x1f);
u8 b = Colour::convert5To8Bit(getBits<0, 5>(texel));
u8 g = Colour::convert6To8Bit(getBits<5, 6>(texel));
u8 r = Colour::convert5To8Bit(getBits<11, 5>(texel));
return (0xff << 24) | (b << 16) | (g << 8) | r;
}
@ -201,7 +203,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
// For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates
u8 alpha = ptr[offset] >> ((u % 2) ? 4 : 0);
alpha = Colour::convert4To8Bit(alpha & 0xf);
alpha = Colour::convert4To8Bit(getBits<0, 4>(alpha));
// A8 sets RGB to 0
return (alpha << 24) | (0 << 16) | (0 << 8) | 0;
@ -222,7 +224,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
// For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates
u8 intensity = ptr[offset] >> ((u % 2) ? 4 : 0);
intensity = Colour::convert4To8Bit(intensity & 0xf);
intensity = Colour::convert4To8Bit(getBits<0, 4>(intensity));
// Intensity formats just copy the intensity value to every colour channel
return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity;