Depth Buffer Layout

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Depth Buffer Layout

Post by holger »

This Codelet will generate two depth buffer dumps. The first contains pixels width z=x and the second one pixels with z=y. Compile using one of the demo Makefiles:

Code: Select all

#include <pspctrl.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#include <GLES/egl.h>
#include <GLES/gl.h>

#define EGLCHK&#40;x&#41; x
#define GLCHK&#40;x&#41; x


static const EGLint attrib_list &#91;&#93; = &#123;
	EGL_RED_SIZE, 8,
	EGL_GREEN_SIZE, 8,
	EGL_BLUE_SIZE, 8,
	EGL_ALPHA_SIZE, 8,
	EGL_DEPTH_SIZE, 16,
	EGL_NONE
&#125;;


struct clear_vertex &#123; short x, y, z; &#125;;

#include "../pspgl_internal.h"

static
void set_depth_pixel &#40;int x, int y, int z&#41;
&#123;
	struct pspgl_dlist *dlist = pspgl_curctx->dlist_current;
	struct clear_vertex *vbuf = pspgl_dlist_insert_space&#40;dlist, 2 * sizeof&#40;struct clear_vertex&#41;&#41;;

	vbuf&#91;0&#93;.x = x;
	vbuf&#91;0&#93;.y = y;
	vbuf&#91;0&#93;.z = z;

	vbuf&#91;1&#93;.x = x+1;
	vbuf&#91;1&#93;.y = y+1;
	vbuf&#91;1&#93;.z = z;

	/* enable clear mode */
	sendCommandi&#40;211, 1 | &#40;1 << 10&#41;&#41;;

	/* draw array */
	sendCommandi&#40;18, 0x800100&#41;;              /* xform&#58; 2D, vertex format&#58; RGB8888 &#40;uint32&#41;, xyz &#40;int16&#41; */
	sendCommandi&#40;16, &#40;&#40;&#40;unsigned long&#41; vbuf&#41; >> 8&#41; & 0xf0000&#41;; /* vertex array BASE */
	sendCommandi&#40;1, &#40;&#40;unsigned long&#41; vbuf&#41; & 0xffffff&#41;;        /* vertex array, Adress */
	sendCommandiUncached&#40;4, &#40;6 << 16&#41; | 2&#41;;			   /* sprite &#40;type 6&#41;, 2 vertices */

	/* leave clear mode */
	sendCommandi&#40;211, 0&#41;;
&#125;


int main&#40;int argc, char* argv&#91;&#93;&#41;
&#123;
	EGLDisplay dpy;
	EGLConfig config;
	EGLint num_configs;
	EGLContext ctx;
	EGLSurface surface;
	unsigned int x, y;

	/* pass NativeDisplay=0, we only have one screen... */
	EGLCHK&#40;dpy = eglGetDisplay&#40;0&#41;&#41;;
	EGLCHK&#40;eglInitialize&#40;dpy, NULL, NULL&#41;&#41;;
	EGLCHK&#40;eglChooseConfig&#40;dpy, attrib_list, &config, 1, &num_configs&#41;&#41;;
	EGLCHK&#40;ctx = eglCreateContext&#40;dpy, config, NULL, NULL&#41;&#41;;
	EGLCHK&#40;surface = eglCreateWindowSurface&#40;dpy, config, 0, NULL&#41;&#41;;
	EGLCHK&#40;eglMakeCurrent&#40;dpy, surface, surface, ctx&#41;&#41;;

/* swap bytes so that they look in order in the hex-editor... */
#define swap16&#40;val&#41; &#40;&#40;&#40;unsigned&#41; val << 8&#41; | &#40;&#40;unsigned&#41; val >> 8&#41;&#41;

	for &#40;y=0; y<272-1; y++&#41; &#123;
		for &#40;x=0; x<480-1; x++&#41; &#123;
			set_depth_pixel&#40;x, y, swap16&#40;x&#41;&#41;;
			GLCHK&#40;glFinish&#40;&#41;&#41;;
		&#125;
	&#125;

	__pspgl_vram_dump&#40;&#41;;

	for &#40;y=0; y<272-1; y++&#41; &#123;
		for &#40;x=0; x<480-1; x++&#41; &#123;
			set_depth_pixel&#40;x, y, swap16&#40;y&#41;&#41;;
			GLCHK&#40;glFinish&#40;&#41;&#41;;
		&#125;
	&#125;

	__pspgl_vram_dump&#40;&#41;;

	EGLCHK&#40;eglTerminate&#40;dpy&#41;&#41;;
	return 0;
&#125;

Isolate the two depth buffer dumps into seperate files and watch the hexdump:

Code: Select all

$ dd if=/Volumes/PSP/pspgl.ge of=/tmp/depthmap-x bs=1 count=278528 skip=1114128
$ dd if=/Volumes/PSP/pspgl.ge of=/tmp/depthmap-y bs=1 count=278528 skip=3211296
$ hexdump -v /tmp/depthmap-x | less
$ hexdump -v /tmp/depthmap-y | less


The depth buffer seems to be laid out like this:

vertical y rows are sorted 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x18, 0x1a, ... , 0x1f, 0x10, 0x11, ... , 0x16, 0x17, ...

horizontal x pixels are sorted in 16-pixel-blocks (32 bytes), beginning in this order: 16-31, 272-287, 0-15, 256-271, 48-63, 304-319, 32-47, 288-303, 80-95, 336-351, 64-79, ...

This may look confusing on a first look, but if we consider byte-swapped address lines and the power-of-two requirement it seems logical.

This codelet does xy-to-adress-in-depthbuffer conversion:

Code: Select all

/* compile using&#58; gcc -Wall -g -O0 -o xy2adr xy2adr.c */
#include <stdio.h>
#include <stdlib.h>

int main &#40;int argc, char **argv&#41;
&#123;
	int x = strtol&#40;argv&#91;1&#93;, NULL, 0&#41;;
	int y = strtol&#40;argv&#91;2&#93;, NULL, 0&#41;;
	int adr;

	adr = &#40;2*512&#41; * &#40;y ^ 8&#41;;
	adr |= &#40;x >> 3&#41; & 0x20;
	adr |= &#40;&#40;x & 0xf0&#41; << 2&#41; ^ 0x40;
	adr |= &#40;x & 0xf&#41; << 1;

	printf&#40;" adr 0x%08x&#58; x = %d/0x%04x, y = %d/0x%04x\n", adr, x, x, y, y&#41;;

	return 0;
&#125;


This one the other way round:

Code: Select all

/* compile using&#58; gcc -Wall -g -O0 -o adr2xy adr2xy.c */
#include <stdio.h>
#include <stdlib.h>

int main &#40;int argc, char **argv&#41;
&#123;
	int adr = strtol&#40;argv&#91;1&#93;, NULL, 0&#41;;
	int x, y;

	y = &#40;adr >> 10&#41; ^ 8;
	x =  &#40;adr & 0x20&#41; << 3;
	x |= &#40;&#40;adr >> 2&#41; & 0xf0&#41; ^ 0x10;
	x |= &#40;adr >> 1&#41; & 0xf;

	printf&#40;" adr 0x%08x&#58; x = %d/0x%04x, y = %d/0x%04x\n", adr, x, x, y, y&#41;;

	return 0;
&#125;

In a real project one probably wants to use tight loops for reordering, but with this information it should be possible to implement depth-buffer based shadow effects and the like.
ector
Posts: 195
Joined: Thu May 12, 2005 10:22 pm

Post by ector »

Nice one!
Excellent for lens flares ;)

These functions belong in the SDK, imho.
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Post by jsgf »

This is very close to the swizzled texture arrangement, isn't it?
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Post by holger »

not really... swizzled (or tiled) textures are optimized for local access and better use of texture cache for small triangles, I can't see much advantage in the depth buffer ordering... anybody else?
Post Reply