Skip to content

Commit

Permalink
VRAM copy overlap test
Browse files Browse the repository at this point in the history
  • Loading branch information
JaCzekanski committed Dec 17, 2019
1 parent 42352ae commit 584a831
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 17 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ IMAGES = common \
gpu/texture-overflow \
gpu/mask-bit \
gpu/gp0-e1 \
gpu/vram-to-vram-overlap \
gte-fuzz \
spu/test \
spu/stereo \
Expand Down
34 changes: 18 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@ Collection of PlayStation 1 tests for emulator development and hardware verifica

## Tests

Name | Description
---------------------|------------
gpu/bandwidth | Measure GPU/VRAM bandwidth
gpu/benchmark | Simple GPU test to benchmark rasteriser
gpu/quad | Semi-transparent polygon commands - for testing fill rules and transparency handling
gpu/transparency | Draws rectangles with 4 semi-transparent blending modes
gpu/triangle | Draws Gouroud shaded equilateral triangle
gpu/lines | Draws lines using different modes - for verifying Bresenham implementation, color blending, polyline handling
gpu/rectangles | Draws all combinations of Rectangle commands
gpu/texture-overflow | Draws textured rectangle with UV overflowing VRAM width
gpu/mask-bit | Check Mask bit behavior during VRAM copy operations
gpu/gp0-e1 | Check if GP0_E1, GPUSTAT and polygon render uses the same register internally
gte-fuzz | Executes GTE opcodes with random parameters, can be used to verify against real console
spu/test | Check SPU behavior (data is lost randomly on 32bit access, ok on 16bit)
spu/stereo | Play samples on first two voices
timers | Run Timer0,1,2 using various clock sources and sync modes and time them using busy loops and vblank interrupt
Name | Description
-------------------------|------------
gpu/bandwidth | Measure GPU/VRAM bandwidth
gpu/benchmark | Simple GPU test to benchmark rasteriser
gpu/quad | Semi-transparent polygon commands - for testing fill rules and transparency handling
gpu/transparency | Draws rectangles with 4 semi-transparent blending modes
gpu/triangle | Draws Gouroud shaded equilateral triangle
gpu/lines | Draws lines using different modes - for verifying Bresenham implementation, color blending, polyline handling
gpu/rectangles | Draws all combinations of Rectangle commands
gpu/texture-overflow | Draws textured rectangle with UV overflowing VRAM width
gpu/mask-bit | Check Mask bit behavior during VRAM copy operations
gpu/gp0-e1 | Check if GP0_E1, GPUSTAT and polygon render uses the same register internally
gpu/vram-to-vram-overlap | Test GP0(80) VRAM-VRAM copy behaviour in overlapping rects
gte-fuzz | Executes GTE opcodes with random parameters, can be used to verify against real console
spu/test | Check SPU behavior (data is lost randomly on 32bit access, ok on 16bit)
spu/stereo | Play samples on first two voices
timers | Run Timer0,1,2 using various clock sources and sync modes and time them using busy loops and vblank interrupt

Note: Make sure your PS-EXE loaded does set default value for Stack Pointer - these .exes has SP set to 0.

Expand All @@ -39,6 +40,7 @@ diffvram | Diff two images and write diff png if image contents aren
<img src="gpu/transparency/vram.png" height="256">
<img src="gpu/rectangles/vram.png" height="256">
<img src="gpu/texture-overflow/vram.png" height="256">
<img src="gpu/vram-to-vram-overlap/vram.png" height="256">

## Build

Expand Down
18 changes: 17 additions & 1 deletion common/gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ DRAWENV draw;

void setResolution(int w, int h) {
SetDefDispEnv(&disp, 0, 0, w, h);
SetDefDrawEnv(&draw, 0, 0, w, h);
SetDefDrawEnv(&draw, 0, 0, 1024, 512);

PutDispEnv(&disp);
PutDrawEnv(&draw);
Expand Down Expand Up @@ -106,3 +106,19 @@ uint32_t vramGet(int x, int y) {

return readGPU();
}

void vramToVramCopy(int srcX, int srcY, int dstX, int dstY, int w, int h)
{
VRAM2VRAM buf = {0};
setcode(&buf, 0x80); // VRAM -> VRAM
setlen(&buf, 4);

buf.x0 = srcX;
buf.y0 = srcY;
buf.x1 = dstX;
buf.y1 = dstY;
buf.w = w;
buf.h = h;

DrawPrim(&buf);
}
1 change: 1 addition & 0 deletions common/gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void writeGP1(uint8_t cmd, uint32_t data);
uint32_t readGPU();
void vramPut(int x, int y, uint16_t pixel);
uint32_t vramGet(int x, int y);
void vramToVramCopy(int srcX, int srcY, int dstX, int dstY, int w, int h);

#ifdef __cplusplus
}
Expand Down
3 changes: 3 additions & 0 deletions gpu/vram-to-vram-overlap/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include ../../common-test.mk

TARGET = vram-to-vram-overlap.elf
67 changes: 67 additions & 0 deletions gpu/vram-to-vram-overlap/font.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <common.h>
#include <psxetc.h>
#include <string.h>

const int fontPosX = 960;
const int fontPosY = 0;

int fontCharX = 0;
int fontCharY = 0;

// TODO: refactor font handling to use SDK functions
void FntInit() {
FntLoad(fontPosX, fontPosY);
}

void FntPos(int x, int y) {
fontCharX = x;
fontCharY = y;
}

void FntChar(char c) {
if (c == '\n') {
fontCharX = 0;
fontCharY += 8;
return;
}
if (c >= ' ') {
DR_TPAGE e;
unsigned short texpage = getTPage(/* bits */ 0, /* semi transparency */ 0, fontPosX, fontPosY);
setDrawTPage(&e, /* Drawing to display area */ 1, /* dithering */ 1, texpage);
DrawPrim(&e);

if (c >= 96) {
c &= ~(1<<5); // To lower
}
char pos = c - 33;
int u = pos%16;
int v = pos/16;

SPRT_8 t;
setSprt8(&t);
setXY0(&t, fontCharX, fontCharY);
setUV0(&t, u*8, v*8);
setClut(&t, fontPosX, 32);
setRGB0(&t, 255, 255, 255);

DrawPrim(&t);
}

fontCharX += 8;
if (fontCharX > 1024) {
fontCharX = 0;
fontCharY += 8;
}
}

void FntPrintf(const char* format, ...) {
char buffer[256];
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);

int len = strlen(buffer);
for (int i = 0; i<len; i++) FntChar(buffer[i]);

va_end(args);
}
14 changes: 14 additions & 0 deletions gpu/vram-to-vram-overlap/font.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

void FntInit();
void FntPos(int x, int y);
void FntChar(char c);
void FntPrintf(const char* format, ...);

#ifdef __cplusplus
}
#endif
137 changes: 137 additions & 0 deletions gpu/vram-to-vram-overlap/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include <common.h>
#include "font.h"

// 24 bit to 15 bit value
constexpr uint16_t rgb(uint8_t r, uint8_t g, uint8_t b) {
uint16_t c = 0;
c |= ((r >> 3) & 0x1f);
c |= ((g >> 3) & 0x1f) << 5;
c |= ((b >> 3) & 0x1f) << 10;
return c;
}

constexpr uint16_t randomColor(int c) {
rgb(64+(c*432)%192, 64+(c*127)%192, 64+(c*941)%192);
}

// Write sizexsize rect to vram
void writeRect(int dstX, int dstY, int size) {
for (int y = 0; y<size; y++) {
for (int x = 0; x<size; x++) {
vramPut(dstX + x, dstY + y, randomColor(y * 32 + x));
}
}
}

void line(int sx, int sy, int ex, int ey) {
LINE_F2 l;
setLineF2(&l);
setRGB0(&l, 255, 255, 255);

l.x0 = sx;
l.y0 = sy;
l.x1 = ex;
l.y1 = ey;

DrawPrim(&l);
}

constexpr int SIZES = 6 + 3;
constexpr int sizes[SIZES] = {
2, 8, 15, 16, 31, 32,
32, // x + 1
32, // y + 1
32, // x + 1, y + 1
};

const int COLS = 10;
const int CELL_SIZE = 48;
const int MARGIN = 4;

void drawDebugInfo() {
// Draw grid, vertical lines
for (int size = 0; size < SIZES + 1; size++) {
line(
0, size * CELL_SIZE,
CELL_SIZE * COLS, size * CELL_SIZE
);
}
// Horizontal
for (int i = 0; i<COLS + 1; i++) {
line(
i * CELL_SIZE, 0,
i * CELL_SIZE, SIZES * CELL_SIZE
);
}

// Labels
for (int testCase = 0; testCase < SIZES; testCase++) {
for (int i = 0; i<COLS; i++) {
if (i == 0) {
FntPos(i * CELL_SIZE + 4, testCase * CELL_SIZE + 12);
FntPrintf("BLOCK\n\n %2d\n ", sizes[testCase]);
if (testCase == 6) FntPrintf("x+1");
if (testCase == 7) FntPrintf("y+1");
if (testCase == 8) FntPrintf("xy+1");
} else {
int x = (i-1)%3 - 1;
int y = (i-1)/3 - 1;
FntPos(i * CELL_SIZE + 4, (testCase + 1) * CELL_SIZE - 10);
FntPrintf("%2d:%d", x, y);
}
}
}
}

#define DRAW_DEBUG

int main() {
initVideo(320, 240);
printf("\ngpu/vram-to-vram-overlap\n");

setMaskBitSetting(false, false);
clearScreen();

#ifdef DRAW_DEBUG
FntInit();
drawDebugInfo();
#endif

// Draw test data
for (int testCase = 0; testCase < SIZES; testCase++) {
for (int i = 1; i<COLS; i++) {
writeRect(i * CELL_SIZE + MARGIN, testCase * CELL_SIZE + MARGIN, sizes[testCase]);
writeGP0(1, 0);
}
}

// Run test itself - copy data in different configurations
for (int testCase = 0; testCase < SIZES; testCase++) {
int size = sizes[testCase];
int xOffset = 0;
int yOffset = 0;

if (testCase == 6) {xOffset += 1;}
if (testCase == 7) {yOffset += 1;}
if (testCase == 8) {xOffset += 1; yOffset += 1;}

int i = 1;
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
int srcX = xOffset + i * CELL_SIZE + MARGIN;
int srcY = yOffset + testCase * CELL_SIZE + MARGIN;
int dstX = xOffset + i * CELL_SIZE + MARGIN + x;
int dstY = yOffset + testCase * CELL_SIZE + MARGIN + y;

vramToVramCopy(srcX, srcY, dstX, dstY, size, size);
writeGP0(1, 0);
i++;
}
}
}

for (;;) {
VSync(0);
}
return 0;
}
Binary file added gpu/vram-to-vram-overlap/vram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 584a831

Please sign in to comment.