Full perspective-correct texturing of visplanes (floors and ceilings)! Flat lighting for now.

This commit is contained in:
jndean
2023-11-28 23:27:49 +00:00
parent 80db96a9be
commit 60f450c57b
6 changed files with 92 additions and 38 deletions
+2 -1
View File
@@ -4,13 +4,14 @@
- Fixed precision int math
- 64-bit int division
- wasn't supported in the supervisor context, drop into a worker thread for each individual division, do double division
- Avoid recursive algorithms, e.g. make a non-recursive BSP
- Avoid recursive algorithms, e.g. make a non-recursive Binary Space Partitioning algorithm
- Split column rendering over 32 tiles
- Memory
- Save 50-60k of lookup tabes for transcendentals by using float functions
- Store textures on other tiles, JIT-fetch as needed (by live patching exchange programs to select a tile)
- Can call exchanges from deep in the call stack, don't need to exit the vertex
- Texture tiles also do colour mapping to create shadow effects (light dropoff)
- Render tiles issue dummy requests after finishing to allow unfinished tiles to keep syncing
+71 -28
View File
@@ -104,33 +104,64 @@ void IPU_R_FulfilColumnRequest(unsigned* progBuf, unsigned char* textureBuf, uns
auto sendProgram = &progBuf[progBuf[1]];
auto aggrProgram = &progBuf[progBuf[2]];
// int noise = 0;
// !! TMP !! need seperate send buffer for lightscaled output to be sent from, currently use end of textureBuf
pixel_t* sendBuf = &textureBuf[IPUTEXTURETILEBUFSIZE - (IPUTEXTURECACHELINESIZE * sizeof(int))];
IPUTextureRequest_t* incomingRequest = (IPUTextureRequest_t*) textureBuf; // Err...? Overwriting texture? replace this with sendBuf?
while (1) {
// Receive a request
XCOM_Execute(recvProgram, NULL, incomingRequest);
XCOM_Execute(recvProgram, NULL, textureBuf);
unsigned textureNum = incomingRequest->texture;
// Check for dummy request
if (textureNum != 0xffffffff) {
// Unpack received data
unsigned textureNum = ((IPUTextureRequest_t*) textureBuf)->texture;
unsigned lightNum = ((IPUTextureRequest_t*) textureBuf)->colRequest.lightNum;
unsigned columnOffset = ((IPUTextureRequest_t*) textureBuf)->colRequest.columnOffset;
unsigned lightScale = ((IPUTextureRequest_t*) textureBuf)->colRequest.lightScale;
// TMP: need seperate send buffer for lightscaled output to be sent from, currently use start of textureBuf
pixel_t* sendBuf = &textureBuf[IPUTEXTURETILEBUFSIZE - (IPUTEXTURECACHELINESIZE * sizeof(int))];
unsigned isSpanRequest = textureNum & IPUTEXREQUESTISSPAN;
textureNum ^= isSpanRequest; // Actual texture number
if (textureNum != 0xffffffff &&
textureNum >= tileLocalTextureRange[0] &&
textureNum < tileLocalTextureRange[1]) {
byte* src = &textureBuf[tileLocalTextureOffsets[textureNum] + columnOffset];
pixel_t* dc_colourmap = scalelight_TT[lightNum][lightScale];
for (int i = 0; i < IPUTEXTURECACHELINESIZE * sizeof(int); ++i) {
sendBuf[i] = dc_colourmap[src[i]];
// Check if the texture lives on this tile
if (textureNum >= tileLocalTextureRange[0] &&
textureNum < tileLocalTextureRange[1]) {
// Find the start of the texture
byte* texture = &textureBuf[tileLocalTextureOffsets[textureNum]];
if (isSpanRequest) {
// Is a Span request (batch)
pixel_t *dest = sendBuf;
for (int i = 0; i < incomingRequest->numSpanRequests; ++i) {
IPUSpanRequest_t* req = &incomingRequest->spanRequests[i];
unsigned position = req->position;
unsigned step = req->step;
unsigned count = req->count;
do {
unsigned ytemp = (position >> 4) & 0x0fc0;
unsigned xtemp = (position >> 26);
int spot = xtemp | ytemp;
*dest++ = texture[spot]; // LATER: ds_colormap[texture[spot]];
position += step;
} while (count--);
}
} else {
// Is a Column request
unsigned lightNum = incomingRequest->colRequest.lightNum;
unsigned columnOffset = incomingRequest->colRequest.columnOffset;
unsigned lightScale = incomingRequest->colRequest.lightScale;
byte* src = &texture[columnOffset];
pixel_t* dc_colourmap = scalelight_TT[lightNum][lightScale];
for (int i = 0; i < IPUTEXTURECACHELINESIZE * sizeof(int); ++i) {
sendBuf[i] = dc_colourmap[src[i]];
}
}
}
}
// Send response to request
XCOM_Execute(sendProgram, sendBuf, NULL);
// Find out if we're done
XCOM_Execute(aggrProgram, NULL, commsBuf);
if (commsBuf[0])
return;
@@ -215,12 +246,21 @@ void IPU_R_InitColumnRequester(unsigned* progBuf, int progBufSize) {
static
__SUPER__
byte* renderTileExchange(int textureSourceTile) {
byte* renderTileExchange(int textureNum) {
// progBuff starts with a program directory
auto requestProg = &tileLocalProgBuf[tileLocalProgBuf[0]];
auto receiveProg = &tileLocalProgBuf[tileLocalProgBuf[1]];
auto aggregateProg = &tileLocalProgBuf[tileLocalProgBuf[2]];
// Figure out which texture tile is going to respond
int textureSourceTile;
for (textureSourceTile = 0; textureSourceTile < IPUTEXTURETILESPERRENDERTILE; ++textureSourceTile) {
if (textureNum >= tileLocalTextureRange[textureSourceTile] &&
textureNum < tileLocalTextureRange[textureSourceTile + 1]) {
break;
}
}
// Request will be populated by the caller, but we follow it up by setting the 'done' flag to 0
IPUTextureRequest_t *request = (IPUTextureRequest_t*) tileLocalTextureBuf;
*((unsigned*) &request[1]) = 0; // The Done Flag
@@ -265,16 +305,19 @@ byte* IPU_R_RequestColumn(int texture, int column) {
request->colRequest.lightNum = lightnum;
request->colRequest.lightScale = walllightindex;
// Figure out which texture tile is going to respond
int textureSourceTile;
for (textureSourceTile = 0; textureSourceTile < IPUTEXTURETILESPERRENDERTILE; ++textureSourceTile) {
if (texture >= tileLocalTextureRange[textureSourceTile] &&
texture < tileLocalTextureRange[textureSourceTile + 1]) {
break;
}
}
return renderTileExchange(texture);
}
return renderTileExchange(textureSourceTile);
extern "C"
__SUPER__
byte* IPU_R_RequestSpanBatch(IPUTextureRequest_t *requestBatch) {
// Populate buffer with data to be exchanged
IPUTextureRequest_t* sendBuf = (IPUTextureRequest_t*) tileLocalTextureBuf;
memcpy(sendBuf, requestBatch, sizeof(*requestBatch));
sendBuf->texture |= IPUTEXREQUESTISSPAN; // Flag saying this is a span request not a col request
return renderTileExchange(requestBatch->texture);
}
+1
View File
@@ -52,6 +52,7 @@ __SUPER__ void IPU_R_InitColumnRequester(unsigned* progBuf, int progBufSize);
__SUPER__ void IPU_R_InitSansTile(unsigned* progBuf, int progBufSize);
__SUPER__ byte* IPU_R_RequestColumn(int texture, int column);
__SUPER__ byte* IPU_R_RequestSpanBatch(IPUTextureRequest_t *requestBatch);
__SUPER__ void IPU_R_FulfilColumnRequest(unsigned* progBuf, unsigned char* textureBuf, unsigned* commsBuf);
__SUPER__ void IPU_R_Sans(unsigned* progBuf, unsigned* commsBuf);
__SUPER__ void IPU_R_RenderTileDone(void);
+2
View File
@@ -26,6 +26,8 @@
#include "ipu_utils.h"
extern int numtextures;
extern int* texturewidthmask;
extern fixed_t* textureheight;
+15 -8
View File
@@ -585,31 +585,29 @@ void R_DrawSpan(void) {
static IPUTextureRequest_t requestBatch;
static pixel_t* spanDests[IPUMAXSPANREQUESTBATCHSIZE];
static int spanBatchTotalCount = 0;
__SUPER__
void IPURequest_R_DrawSpan_FulfillBatch(void) {
IPUTextureRequest_t* requestBuf = (IPUTextureRequest_t*) tileLocalTextureBuf;
memcpy(requestBuf, &requestBatch, sizeof(requestBatch));
requestBuf->texture |= IPUTEXREQUESTISSPAN;
pixel_t* src = IPU_R_RequestSpanBatch(&requestBatch);
// TMP: Fill the span with fixed colour
for (int i = 0; i < requestBatch.numSpanRequests; ++i) {
IPUSpanRequest_t* spanRequest = &requestBatch.spanRequests[i];
pixel_t* dest = spanDests[i];
for (int i = 0; i <= spanRequest->count; i++) {
*dest++ = 20;
*dest++ = *src++; //requestBatch.texture % 256;
}
}
spanBatchTotalCount = 0;
requestBatch.numSpanRequests = 0;
}
// The render-tile side of the span requesting system
__SUPER__
void IPURequest_R_DrawSpan(void) {
unsigned int position, step;
pixel_t *dest;
int count;
if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH ||
(unsigned)ds_y > SCREENHEIGHT) {
@@ -621,16 +619,25 @@ void IPURequest_R_DrawSpan(void) {
IPURequest_R_DrawSpan_FulfillBatch();
}
requestBatch.texture = flatnum;
// The response is fixed size, so send the existing batch if there's
// no space to fulfil the next request
int count = ds_x2 - ds_x1;
if (spanBatchTotalCount + count > IPUTEXTURECACHELINESIZE * sizeof(int)) {
IPURequest_R_DrawSpan_FulfillBatch();
}
IPUSpanRequest_t* spanRequest = &requestBatch.spanRequests[requestBatch.numSpanRequests];
spanRequest->position = ((ds_xfrac << 10) & 0xffff0000) | ((ds_yfrac >> 6) & 0x0000ffff);
spanRequest->step = ((ds_xstep << 10) & 0xffff0000) | ((ds_ystep >> 6) & 0x0000ffff);
spanRequest->count = ds_x2 - ds_x1;
spanRequest->count = count;
spanRequest->lightNum = lightnum;
spanDests[requestBatch.numSpanRequests] = ylookup[ds_y] + columnofs[ds_x1];
spanBatchTotalCount += count;
requestBatch.numSpanRequests += 1;
if (requestBatch.numSpanRequests >= IPUMAXSPANREQUESTBATCHSIZE) {
IPURequest_R_DrawSpan_FulfillBatch();
}
+1 -1
View File
@@ -379,7 +379,7 @@ void R_DrawPlanes(void) {
}
// JOSEF: Don't load lump, just record flatnum to send over exchange later
flatnum = pl->picnum; // LATER: flattranslation[pl->picnum];
flatnum = numtextures + pl->picnum; // LATER: numtextures + flattranslation[pl->picnum];
// regular flat
// lumpnum = firstflat + flattranslation[pl->picnum];
// ds_source = W_CacheLumpNum(lumpnum, PU_STATIC);