mirror of
https://github.com/jndean/IPUDOOM.git
synced 2026-06-09 14:12:07 +00:00
Full perspective-correct texturing of visplanes (floors and ceilings)! Flat lighting for now.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "ipu_utils.h"
|
||||
|
||||
|
||||
extern int numtextures;
|
||||
|
||||
extern int* texturewidthmask;
|
||||
extern fixed_t* textureheight;
|
||||
|
||||
|
||||
+15
-8
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user