Skip to content

Commit

Permalink
gpu: added CLUT cache implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
JaCzekanski committed May 10, 2020
1 parent d35f1c6 commit 93580f3
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ spu.bin

.vs/
imgui.ini
/vram.png

todo.txt
config.json
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "texture_utils.h"
#include "color_depth.h"

ColorDepth bitsToDepth(int bits) {
switch (bits) {
Expand Down
17 changes: 17 additions & 0 deletions src/device/gpu/color_depth.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

enum class ColorDepth { NONE, BIT_4, BIT_8, BIT_16 };

ColorDepth bitsToDepth(int bits);

template <int bits>
constexpr ColorDepth bitsToDepth() {
if constexpr (bits == 4)
return ColorDepth::BIT_4;
else if constexpr (bits == 8)
return ColorDepth::BIT_8;
else if constexpr (bits == 16)
return ColorDepth::BIT_16;
else
return ColorDepth::NONE;
}
3 changes: 3 additions & 0 deletions src/device/gpu/gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ void GPU::reset() {
drawingOffsetY = 0;

gp0_e6._reg = 0;

clutCachePos = ivec2(-1, -1);
}

void GPU::drawTriangle(const primitive::Triangle& triangle) {
Expand Down Expand Up @@ -607,6 +609,7 @@ void GPU::writeGP0(uint32_t data) {
}
} else if (command == 0x01) {
// Clear Cache
clutCachePos = ivec2(-1, -1);
} else if (command == 0x02) {
// Fill rectangle
cmd = Command::FillRectangle;
Expand Down
6 changes: 6 additions & 0 deletions src/device/gpu/gpu.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <array>
#include <vector>
#include "color_depth.h"
#include "primitive.h"
#include "psx_color.h"
#include "registers.h"
Expand Down Expand Up @@ -98,6 +99,11 @@ class GPU {

std::array<uint16_t, VRAM_WIDTH * VRAM_HEIGHT> vram{};

// TODO: Serialize?
std::array<uint16_t, 256> clutCache{};
ivec2 clutCachePos{-1, -1};
ColorDepth clutCacheColorDepth = ColorDepth::NONE;

private:
// Hardware rendering
std::vector<Vertex> vertices;
Expand Down
4 changes: 3 additions & 1 deletion src/device/gpu/render/render_rectangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ INLINE void rasterizeRectangle(gpu::GPU* gpu, const primitive::Rect& rect) {
vStep = -1;
}

loadClutCacheIfRequired<bits>(gpu, rect.clut);

int x, y, u, v;
for (y = min.y, v = uv.y; y <= max.y; y++, v += vStep) {
for (x = min.x, u = uv.x; x <= max.x; x++, u += uStep) {
Expand All @@ -57,7 +59,7 @@ INLINE void rasterizeRectangle(gpu::GPU* gpu, const primitive::Rect& rect) {
c = PSXColor(rect.color.r, rect.color.g, rect.color.b);
} else {
const ivec2 texel = maskTexel(ivec2(u, v), textureWindow);
c = fetchTex<bits>(gpu, texel, rect.texpage, rect.clut);
c = fetchTex<bits>(gpu, texel, rect.texpage);
if (c.raw == 0x0000) continue;

if constexpr (isBlended) {
Expand Down
4 changes: 3 additions & 1 deletion src/device/gpu/render/render_triangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ void rasterizeTriangle(gpu::GPU* gpu, const primitive::Triangle& triangle) {
const int area = orient2d(pos[0], pos[1], pos[2]);
if (area == 0) return;

loadClutCacheIfRequired<bits>(gpu, triangle.clut);

ivec2 min( //
std::min({pos[0].x, pos[1].x, pos[2].x}), //
std::min({pos[0].y, pos[1].y, pos[2].y}) //
Expand Down Expand Up @@ -278,7 +280,7 @@ void rasterizeTriangle(gpu::GPU* gpu, const primitive::Triangle& triangle) {
} else {
const ivec2 uv(FROM_FP(attrib.u), FROM_FP(attrib.v));
const ivec2 texel = maskTexel(uv, textureWindow);
c = fetchTex<bits>(gpu, texel, triangle.texpage, triangle.clut);
c = fetchTex<bits>(gpu, texel, triangle.texpage);
if (c.raw == 0x0000) goto DONE;

if constexpr (isBlended) {
Expand Down
47 changes: 27 additions & 20 deletions src/device/gpu/render/texture_utils.h
Original file line number Diff line number Diff line change
@@ -1,48 +1,55 @@
#pragma once
#include "device/gpu/gpu.h"
#include "utils/macros.h"
#include "../color_depth.h"
#include "../primitive.h"

#define gpuVRAM ((uint16_t(*)[gpu::VRAM_WIDTH])gpu->vram.data())

enum class ColorDepth { NONE, BIT_4, BIT_8, BIT_16 };
template <ColorDepth bits>
void loadClutCacheIfRequired(gpu::GPU* gpu, ivec2 clut) {
// Only paletted textures should reload the color look-up table cache
if constexpr (bits != ColorDepth::BIT_4 && bits != ColorDepth::BIT_8) {
return;
}

bool textureFormatRequireReload = bits > gpu->clutCacheColorDepth;
bool clutPositionChanged = gpu->clutCachePos != clut;

ColorDepth bitsToDepth(int bits);
if (!textureFormatRequireReload && !clutPositionChanged) {
return;
}

gpu->clutCacheColorDepth = bits;
gpu->clutCachePos = clut;

template <int bits>
constexpr ColorDepth bitsToDepth() {
if constexpr (bits == 4)
return ColorDepth::BIT_4;
else if constexpr (bits == 8)
return ColorDepth::BIT_8;
else if constexpr (bits == 16)
return ColorDepth::BIT_16;
else
return ColorDepth::NONE;
constexpr int entries = (bits == ColorDepth::BIT_8) ? 256 : 16;
for (int i = 0; i < entries; i++) {
gpu->clutCache[i] = gpuVRAM[clut.y][clut.x + i];
}
}

namespace {
// Using unsigned vectors allows compiler to generate slightly faster division code
INLINE uint16_t tex4bit(gpu::GPU* gpu, ivec2 tex, ivec2 texPage, ivec2 clut) {
INLINE uint16_t tex4bit(gpu::GPU* gpu, ivec2 tex, ivec2 texPage) {
uint16_t index = gpuVRAM[(texPage.y + tex.y) & 511][(texPage.x + tex.x / 4) & 1023];
uint8_t entry = (index >> ((tex.x & 3) * 4)) & 0xf;
return gpuVRAM[clut.y][clut.x + entry];
return gpu->clutCache[entry];
}

INLINE uint16_t tex8bit(gpu::GPU* gpu, ivec2 tex, ivec2 texPage, ivec2 clut) {
INLINE uint16_t tex8bit(gpu::GPU* gpu, ivec2 tex, ivec2 texPage) {
uint16_t index = gpuVRAM[(texPage.y + tex.y) & 511][(texPage.x + tex.x / 2) & 1023];
uint8_t entry = (index >> ((tex.x & 1) * 8)) & 0xff;
return gpuVRAM[clut.y][clut.x + entry];
return gpu->clutCache[entry];
}

INLINE uint16_t tex16bit(gpu::GPU* gpu, ivec2 tex, ivec2 texPage) { return gpuVRAM[(texPage.y + tex.y) & 511][(texPage.x + tex.x) & 1023]; }

template <ColorDepth bits>
INLINE PSXColor fetchTex(gpu::GPU* gpu, ivec2 texel, const ivec2 texPage, const ivec2 clut) {
INLINE PSXColor fetchTex(gpu::GPU* gpu, ivec2 texel, const ivec2 texPage) {
if constexpr (bits == ColorDepth::BIT_4) {
return tex4bit(gpu, texel, texPage, clut);
return tex4bit(gpu, texel, texPage);
} else if constexpr (bits == ColorDepth::BIT_8) {
return tex8bit(gpu, texel, texPage, clut);
return tex8bit(gpu, texel, texPage);
} else if constexpr (bits == ColorDepth::BIT_16) {
return tex16bit(gpu, texel, texPage);
} else {
Expand Down
6 changes: 6 additions & 0 deletions src/utils/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ struct ivec2 {

ivec2 operator-(const ivec2& b) const { return {x - b.x, y - b.y}; }
ivec2 operator+(const ivec2& b) const { return {x + b.x, y + b.y}; }
bool operator==(const ivec2& b) const { return x == b.x && y == b.y; }
bool operator!=(const ivec2& b) const { return x != b.x || y != b.y; }
};

struct ivec3 {
Expand All @@ -15,6 +17,8 @@ struct ivec3 {

ivec3 operator-(const ivec3& b) const { return {x - b.x, y - b.y, z - b.z}; }
ivec3 operator+(const ivec3& b) const { return {x + b.x, y + b.y, z - b.z}; }
bool operator==(const ivec3& b) const { return x == b.x && y == b.y && z == b.z; }
bool operator!=(const ivec3& b) const { return x != b.x || y != b.y || z != b.z; }
};

struct vec2 {
Expand All @@ -27,6 +31,8 @@ struct vec2 {
vec2 operator+(const vec2& b) const { return {x + b.x, y + b.y}; }
vec2 operator*(const float b) const { return {x * b, y * b}; }
vec2 operator/(const float b) const { return {x / b, y / b}; }
bool operator==(const vec2& b) const { return x == b.x && y == b.y; }
bool operator!=(const vec2& b) const { return x != b.x || y != b.y; }

float length() const;
static vec2 normalize(const vec2& v);
Expand Down

0 comments on commit 93580f3

Please sign in to comment.