Start multithreading mesh render
This commit is contained in:
parent
079e19b58b
commit
630522f8a3
@ -11,7 +11,7 @@
|
||||
PlatformFlags globalDTRPlatformFlags;
|
||||
|
||||
// #include <algorithm>
|
||||
void CompAssignment(DTRRenderBuffer *const renderBuffer, PlatformInput *const input,
|
||||
void CompAssignment(DTRRenderContext renderContext, PlatformInput *const input,
|
||||
PlatformMemory *const memory)
|
||||
{
|
||||
#if 1
|
||||
@ -835,11 +835,11 @@ void CompAssignment(DTRRenderBuffer *const renderBuffer, PlatformInput *const in
|
||||
#if 1
|
||||
char pText[32] = {};
|
||||
Dqn_sprintf(pText, "(%1.0f, %1.0f)", origP.x, origP.y);
|
||||
DTRRender_Text(renderBuffer, state->font,
|
||||
DTRRender_Text(renderContext, state->font,
|
||||
DqnV2_2f(p.x + radius.x + 5, p.y - (state->font.sizeInPt * 0.40f)), pText,
|
||||
textColor);
|
||||
#endif
|
||||
DTRRender_Rectangle(renderBuffer, p - radius, p + radius, pColor);
|
||||
DTRRender_Rectangle(renderContext, p - radius, p + radius, pColor);
|
||||
}
|
||||
|
||||
DqnV2 halfRadius = radius * 0.5f;
|
||||
@ -851,10 +851,10 @@ void CompAssignment(DTRRenderBuffer *const renderBuffer, PlatformInput *const in
|
||||
|
||||
char pText[32] = {};
|
||||
Dqn_sprintf(pText, "(%1.0f, %1.0f)", origP.x, origP.y);
|
||||
DTRRender_Text(renderBuffer, state->font,
|
||||
DTRRender_Text(renderContext, state->font,
|
||||
DqnV2_2f(p.x + radius.x + 5, p.y - (state->font.sizeInPt * 0.40f)), pText,
|
||||
textColor);
|
||||
DTRRender_Rectangle(renderBuffer, p - radius, p + radius, pColor);
|
||||
DTRRender_Rectangle(renderContext, p - radius, p + radius, pColor);
|
||||
|
||||
if (i + 1 <= skyPIndex && i > 0)
|
||||
{
|
||||
@ -863,7 +863,7 @@ void CompAssignment(DTRRenderBuffer *const renderBuffer, PlatformInput *const in
|
||||
|
||||
DqnV2 pMid = p + halfRadius;
|
||||
DqnV2 prevPMid = prevP + halfRadius;
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(prevPMid), DqnV2i_V2(pMid),
|
||||
DTRRender_Line(renderContext, DqnV2i_V2(prevPMid), DqnV2i_V2(pMid),
|
||||
DqnV4_4f(255, 0, 0, 255));
|
||||
}
|
||||
}
|
||||
@ -895,10 +895,25 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
|
||||
state = (DTRState *)memory->context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Init Memory Stacks
|
||||
// Init
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
DqnMemStack *const assetStack = &memory->assetStack;
|
||||
DqnMemStack *const tempStack = &memory->tempStack;
|
||||
state->zDepthLock = input->api.LockInit(&memory->mainStack);
|
||||
if (state->zDepthLock)
|
||||
{
|
||||
state->blitLock = input->api.LockInit(&memory->mainStack);
|
||||
if (!state->blitLock)
|
||||
{
|
||||
// TODO(doyle): Not enough memory die gracefully
|
||||
DQN_ASSERT(DQN_INVALID_CODE_PATH);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(doyle): Not enough memory die gracefully
|
||||
DQN_ASSERT(DQN_INVALID_CODE_PATH);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Init Assets
|
||||
@ -952,6 +967,8 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
|
||||
renderBuffer.height = platformRenderBuffer->height;
|
||||
renderBuffer.bytesPerPixel = platformRenderBuffer->bytesPerPixel;
|
||||
renderBuffer.memory = (u8 *)platformRenderBuffer->memory;
|
||||
renderBuffer.zDepthLock = state->zDepthLock;
|
||||
renderBuffer.blitLock = state->blitLock;
|
||||
|
||||
u32 zBufferSize = platformRenderBuffer->width * platformRenderBuffer->height;
|
||||
renderBuffer.zBuffer = (f32 *)DqnMemStack_Push(&memory->tempStack,
|
||||
@ -959,10 +976,15 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
|
||||
|
||||
for (u32 i = 0; i < zBufferSize; i++)
|
||||
renderBuffer.zBuffer[i] = DQN_F32_MIN;
|
||||
|
||||
DTRRenderContext renderContext = {};
|
||||
renderContext.renderBuffer = &renderBuffer;
|
||||
renderContext.tempStack = &memory->tempStack;
|
||||
renderContext.api = &input->api;
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Update and Render
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
DTRRender_Clear(&renderBuffer, DqnV3_3f(0.5f, 0.0f, 1.0f));
|
||||
DTRRender_Clear(renderContext, DqnV3_3f(0.5f, 0.0f, 1.0f));
|
||||
|
||||
#if 1
|
||||
DqnV4 colorRed = DqnV4_4f(0.8f, 0, 0, 1);
|
||||
@ -991,12 +1013,12 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
|
||||
DTRDebug_BeginCycleCount("DTR_Update_RenderPrimitiveTriangles",
|
||||
DTRDebugCycleCount_DTR_Update_RenderPrimitiveTriangles);
|
||||
|
||||
DTRRender_Triangle(&renderBuffer, t0[0], t0[1], t0[2], colorRed);
|
||||
DTRRender_Triangle(&renderBuffer, t1[0], t1[1], t1[2], colorRed);
|
||||
DTRRender_Triangle(&renderBuffer, t3[0], t3[1], t3[2], colorRed, rotatingXform);
|
||||
DTRRender_Triangle(&renderBuffer, t2[0], t2[1], t2[2], colorRed);
|
||||
DTRRender_Triangle(&renderBuffer, t4[0], t4[1], t4[2], colorRed);
|
||||
DTRRender_Triangle(&renderBuffer, t5[0], t5[1], t5[2], colorRed);
|
||||
DTRRender_Triangle(renderContext, t0[0], t0[1], t0[2], colorRed);
|
||||
DTRRender_Triangle(renderContext, t1[0], t1[1], t1[2], colorRed);
|
||||
DTRRender_Triangle(renderContext, t3[0], t3[1], t3[2], colorRed, rotatingXform);
|
||||
DTRRender_Triangle(renderContext, t2[0], t2[1], t2[2], colorRed);
|
||||
DTRRender_Triangle(renderContext, t4[0], t4[1], t4[2], colorRed);
|
||||
DTRRender_Triangle(renderContext, t5[0], t5[1], t5[2], colorRed);
|
||||
DTRDebug_EndCycleCount(DTRDebugCycleCount_DTR_Update_RenderPrimitiveTriangles);
|
||||
}
|
||||
|
||||
@ -1033,8 +1055,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
|
||||
lighting.vector = LIGHT;
|
||||
lighting.color = DqnV4_4f(1, 1, 1, 1);
|
||||
|
||||
DTRRender_Mesh(&renderBuffer, &memory->tempStack, &input->api, input->jobQueue,
|
||||
mesh, lighting, modelP, transform);
|
||||
DTRRender_Mesh(renderContext, input->jobQueue, mesh, lighting, modelP, transform);
|
||||
DTRDebug_EndCycleCount(DTRDebugCycleCount_DTR_Update_RenderModel);
|
||||
}
|
||||
}
|
||||
@ -1045,7 +1066,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
|
||||
DTRRenderTransform transform = DTRRender_DefaultTransform();
|
||||
transform.rotation = rotation + 45;
|
||||
|
||||
DTRRender_Rectangle(&renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 100.0f),
|
||||
DTRRender_Rectangle(renderContext, DqnV2_1f(300.0f), DqnV2_1f(300 + 100.0f),
|
||||
DqnV4_4f(0, 1.0f, 1.0f, 1.0f), transform);
|
||||
}
|
||||
|
||||
@ -1061,14 +1082,14 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
|
||||
f32 cAngle = (f32)input->timeNowInS;
|
||||
DqnV4 color = DqnV4_4f(0.5f + 0.5f * sinf(cAngle), 0.5f + 0.5f * sinf(2.9f * cAngle),
|
||||
0.5f + 0.5f * cosf(10.0f * cAngle), 1.0f);
|
||||
DTRRender_Bitmap(&renderBuffer, &state->bitmap, bitmapP, transform, color);
|
||||
DTRRender_Bitmap(renderContext, &state->bitmap, bitmapP, transform, color);
|
||||
}
|
||||
|
||||
#else
|
||||
// CompAssignment(renderBuffer, input, memory);
|
||||
#endif
|
||||
DTRDebug_EndCycleCount(DTRDebugCycleCount_DTR_Update);
|
||||
DTRDebug_Update(state, &renderBuffer, input, memory);
|
||||
DTRDebug_Update(state, renderContext, input, memory);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -13,6 +13,9 @@ typedef struct DTRState
|
||||
DTRFont font;
|
||||
DTRBitmap bitmap;
|
||||
DTRMesh mesh;
|
||||
|
||||
struct PlatformLock *zDepthLock;
|
||||
struct PlatformLock *blitLock;
|
||||
} DTRState;
|
||||
|
||||
extern PlatformFlags globalDTRPlatformFlags;
|
||||
|
@ -118,7 +118,7 @@ void DTRDebug_PushText(const char *const formatStr, ...)
|
||||
if (DTR_DEBUG)
|
||||
{
|
||||
DTRDebug *const debug = &globalDebug;
|
||||
if (!debug->renderBuffer) return;
|
||||
if (!debug->renderContext->renderBuffer) return;
|
||||
|
||||
char str[1024] = {};
|
||||
|
||||
@ -130,7 +130,7 @@ void DTRDebug_PushText(const char *const formatStr, ...)
|
||||
}
|
||||
va_end(argList);
|
||||
|
||||
DTRRender_Text(debug->renderBuffer, *debug->font, debug->displayP, str,
|
||||
DTRRender_Text(*debug->renderContext, *debug->font, debug->displayP, str,
|
||||
debug->displayColor);
|
||||
debug->displayP.y += globalDebug.displayYOffset;
|
||||
}
|
||||
@ -199,25 +199,25 @@ FILE_SCOPE void PushMemStackText(const char *const name, const DqnMemStack *cons
|
||||
Dqn_sprintf(str, "%s: %d block(s): %_$lld/%_$lld: wasted: %_$lld", name, numBlocks,
|
||||
totalUsed, totalSize, totalWastedKb);
|
||||
|
||||
DTRRender_Text(globalDebug.renderBuffer, *globalDebug.font,
|
||||
DTRRender_Text(*globalDebug.renderContext, *globalDebug.font,
|
||||
globalDebug.displayP, str, globalDebug.displayColor);
|
||||
globalDebug.displayP.y += globalDebug.displayYOffset;
|
||||
}
|
||||
}
|
||||
|
||||
void DTRDebug_Update(DTRState *const state,
|
||||
DTRRenderBuffer *const renderBuffer,
|
||||
DTRRenderContext renderContext,
|
||||
PlatformInput *const input, PlatformMemory *const memory)
|
||||
{
|
||||
if (DTR_DEBUG)
|
||||
{
|
||||
DTRDebug *const debug = &globalDebug;
|
||||
|
||||
debug->renderBuffer = renderBuffer;
|
||||
debug->renderContext = &renderContext;
|
||||
debug->input = input;
|
||||
debug->font = &state->font;
|
||||
debug->displayColor = DqnV4_4f(1, 1, 1, 1);
|
||||
if (debug->font->bitmap && debug->renderBuffer)
|
||||
if (debug->font->bitmap && debug->renderContext)
|
||||
{
|
||||
debug->displayYOffset = -(i32)(state->font.sizeInPt + 0.5f);
|
||||
DQN_ASSERT(globalDebug.displayYOffset < 0);
|
||||
@ -270,7 +270,7 @@ void DTRDebug_Update(DTRState *const state,
|
||||
// End Debug Update
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
debug->displayP =
|
||||
DqnV2_2i(0, debug->renderBuffer->height + globalDebug.displayYOffset);
|
||||
DqnV2_2i(0, debug->renderContext->renderBuffer->height + globalDebug.displayYOffset);
|
||||
|
||||
for (i32 i = 0; i < DQN_ARRAY_COUNT(debug->counter); i++)
|
||||
debug->counter[i] = 0;
|
||||
|
@ -89,7 +89,7 @@ typedef struct DTRDebugCycles
|
||||
typedef struct DTRDebug
|
||||
{
|
||||
struct DTRFont *font;
|
||||
struct DTRRenderBuffer *renderBuffer;
|
||||
struct DTRRenderContext *renderContext;
|
||||
struct PlatformInput *input;
|
||||
DqnMemStack memStack;
|
||||
|
||||
|
@ -52,6 +52,16 @@ typedef struct PlatformJob
|
||||
typedef bool PlatformAPI_QueueAddJob (PlatformJobQueue *const queue, const PlatformJob job);
|
||||
typedef bool PlatformAPI_QueueTryExecuteNextJob(PlatformJobQueue *const queue);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Platform Locks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct PlatformLock PlatformLock;
|
||||
|
||||
typedef PlatformLock *PlatformAPI_LockInit (DqnMemStack *const stack);
|
||||
typedef void PlatformAPI_LockAcquire(PlatformLock *const lock);
|
||||
typedef void PlatformAPI_LockRelease(PlatformLock *const lock);
|
||||
typedef void PlatformAPI_LockDelete (PlatformLock *const lock);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Platform API for Game to Use
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -65,6 +75,11 @@ typedef struct PlatformAPI
|
||||
|
||||
PlatformAPI_QueueAddJob *QueueAddJob;
|
||||
PlatformAPI_QueueTryExecuteNextJob *QueueTryExecuteNextJob;
|
||||
|
||||
PlatformAPI_LockInit *LockInit;
|
||||
PlatformAPI_LockAcquire *LockAcquire;
|
||||
PlatformAPI_LockRelease *LockRelease;
|
||||
PlatformAPI_LockDelete *LockDelete;
|
||||
} PlatformAPI;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -121,9 +121,10 @@ inline DqnV4 DTRRender_PreMultiplyAlphaSRGB1WithLinearConversion(DqnV4 color)
|
||||
}
|
||||
|
||||
// IMPORTANT(doyle): Color is expected to be premultiplied already
|
||||
FILE_SCOPE inline void SetPixel(DTRRenderBuffer *const renderBuffer, const i32 x, const i32 y,
|
||||
FILE_SCOPE inline void SetPixel(DTRRenderContext context, const i32 x, const i32 y,
|
||||
DqnV4 color, const enum ColorSpace colorSpace = ColorSpace_SRGB)
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
if (!renderBuffer) return;
|
||||
if (x < 0 || x > (renderBuffer->width - 1)) return;
|
||||
if (y < 0 || y > (renderBuffer->height - 1)) return;
|
||||
@ -189,14 +190,17 @@ FILE_SCOPE inline void SetPixel(DTRRenderBuffer *const renderBuffer, const i32 x
|
||||
DTRDebug_CounterIncrement(DTRDebugCounter_SetPixels);
|
||||
}
|
||||
|
||||
void DTRRender_Text(DTRRenderBuffer *const renderBuffer,
|
||||
void DTRRender_Text(DTRRenderContext context,
|
||||
const DTRFont font, DqnV2 pos, const char *const text,
|
||||
DqnV4 color, i32 len)
|
||||
{
|
||||
if (!text) return;
|
||||
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
if (!font.bitmap || !font.atlas || !renderBuffer) return;
|
||||
DTR_DEBUG_EP_TIMED_FUNCTION();
|
||||
|
||||
|
||||
if (len == -1) len = Dqn_strlen(text);
|
||||
|
||||
i32 index = 0;
|
||||
@ -262,7 +266,7 @@ void DTRRender_Text(DTRRenderBuffer *const renderBuffer,
|
||||
|
||||
i32 actualX = (i32)(screenRect.min.x + x);
|
||||
i32 actualY = (i32)(screenRect.min.y + y - fontHeightOffset);
|
||||
SetPixel(renderBuffer, actualX, actualY, resultColor, ColorSpace_Linear);
|
||||
SetPixel(context, actualX, actualY, resultColor, ColorSpace_Linear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,9 +291,10 @@ FILE_SCOPE void TransformPoints(const DqnV2 origin, DqnV2 *const pList,
|
||||
}
|
||||
}
|
||||
|
||||
void DTRRender_Line(DTRRenderBuffer *const renderBuffer, DqnV2i a,
|
||||
void DTRRender_Line(DTRRenderContext context, DqnV2i a,
|
||||
DqnV2i b, DqnV4 color)
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
if (!renderBuffer) return;
|
||||
DTR_DEBUG_EP_TIMED_FUNCTION();
|
||||
|
||||
@ -339,7 +344,7 @@ void DTRRender_Line(DTRRenderBuffer *const renderBuffer, DqnV2i a,
|
||||
for (i32 iterateX = 0; iterateX < numIterations; iterateX++)
|
||||
{
|
||||
newX = a.x + iterateX;
|
||||
SetPixel(renderBuffer, *plotX, *plotY, color, ColorSpace_Linear);
|
||||
SetPixel(context, *plotX, *plotY, color, ColorSpace_Linear);
|
||||
|
||||
distAccumulator += distFromPixelOrigin;
|
||||
if (distAccumulator > run)
|
||||
@ -407,10 +412,13 @@ FILE_SCOPE DqnRect GetBoundingBox(const DqnV2 *const pList, const i32 numP)
|
||||
return result;
|
||||
}
|
||||
|
||||
void DTRRender_Rectangle(DTRRenderBuffer *const renderBuffer, DqnV2 min, DqnV2 max,
|
||||
void DTRRender_Rectangle(DTRRenderContext context, DqnV2 min, DqnV2 max,
|
||||
DqnV4 color, const DTRRenderTransform transform)
|
||||
{
|
||||
DTR_DEBUG_EP_TIMED_FUNCTION();
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
if (!renderBuffer) return;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Transform vertexes
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -461,7 +469,7 @@ void DTRRender_Rectangle(DTRRenderBuffer *const renderBuffer, DqnV2 min, DqnV2 m
|
||||
}
|
||||
}
|
||||
|
||||
if (pIsInside) SetPixel(renderBuffer, bufferX, bufferY, color, ColorSpace_Linear);
|
||||
if (pIsInside) SetPixel(context, bufferX, bufferY, color, ColorSpace_Linear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -473,7 +481,7 @@ void DTRRender_Rectangle(DTRRenderBuffer *const renderBuffer, DqnV2 min, DqnV2 m
|
||||
for (i32 x = 0; x < clippedSize.w; x++)
|
||||
{
|
||||
i32 bufferX = (i32)clippedRect.min.x + x;
|
||||
SetPixel(renderBuffer, bufferX, bufferY, color, ColorSpace_Linear);
|
||||
SetPixel(context, bufferX, bufferY, color, ColorSpace_Linear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -485,20 +493,20 @@ void DTRRender_Rectangle(DTRRenderBuffer *const renderBuffer, DqnV2 min, DqnV2 m
|
||||
{
|
||||
// Draw Bounding box
|
||||
{
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(min.x, min.y), DqnV2i_2f(min.x, max.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(min.x, max.y), DqnV2i_2f(max.x, max.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(max.x, max.y), DqnV2i_2f(max.x, min.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(max.x, min.y), DqnV2i_2f(min.x, min.y), color);
|
||||
DTRRender_Line(context, DqnV2i_2f(min.x, min.y), DqnV2i_2f(min.x, max.y), color);
|
||||
DTRRender_Line(context, DqnV2i_2f(min.x, max.y), DqnV2i_2f(max.x, max.y), color);
|
||||
DTRRender_Line(context, DqnV2i_2f(max.x, max.y), DqnV2i_2f(max.x, min.y), color);
|
||||
DTRRender_Line(context, DqnV2i_2f(max.x, min.y), DqnV2i_2f(min.x, min.y), color);
|
||||
}
|
||||
|
||||
// Draw rotating outline
|
||||
if (transform.rotation > 0)
|
||||
{
|
||||
DqnV4 green = DqnV4_4f(0, 1, 0, 1);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[0]), DqnV2i_V2(pList[1]), green);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[1]), DqnV2i_V2(pList[2]), green);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[2]), DqnV2i_V2(pList[3]), green);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[3]), DqnV2i_V2(pList[0]), green);
|
||||
DTRRender_Line(context, DqnV2i_V2(pList[0]), DqnV2i_V2(pList[1]), green);
|
||||
DTRRender_Line(context, DqnV2i_V2(pList[1]), DqnV2i_V2(pList[2]), green);
|
||||
DTRRender_Line(context, DqnV2i_V2(pList[2]), DqnV2i_V2(pList[3]), green);
|
||||
DTRRender_Line(context, DqnV2i_V2(pList[3]), DqnV2i_V2(pList[0]), green);
|
||||
}
|
||||
|
||||
}
|
||||
@ -609,10 +617,12 @@ FILE_SCOPE inline DqnV2 Get2DOriginFromTransformAnchor(const DqnV2 p1, const Dqn
|
||||
}
|
||||
|
||||
// color: _mm_set_ps(a, b, g, r) ie. 0=r, 1=g, 2=b, 3=a
|
||||
FILE_SCOPE inline void SIMDSetPixel(DTRRenderBuffer *const renderBuffer, const i32 x, const i32 y,
|
||||
FILE_SCOPE inline void SIMDSetPixel(DTRRenderContext context, const i32 x, const i32 y,
|
||||
__m128 color,
|
||||
const enum ColorSpace colorSpace = ColorSpace_SRGB)
|
||||
{
|
||||
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
if (!renderBuffer) return;
|
||||
if (x < 0 || x > (renderBuffer->width - 1)) return;
|
||||
if (y < 0 || y > (renderBuffer->height - 1)) return;
|
||||
@ -631,6 +641,7 @@ FILE_SCOPE inline void SIMDSetPixel(DTRRenderBuffer *const renderBuffer, const i
|
||||
if (needGammaFix) color = SIMDSRGB1ToLinearSpace(color);
|
||||
|
||||
// Format: u32 == (XX, RR, GG, BB)
|
||||
context.api->LockAcquire(renderBuffer->blitLock);
|
||||
u32 srcPixel = bitmapPtr[x + (y * pitchInU32)];
|
||||
__m128 src = _mm_set_ps(0,
|
||||
(f32)((srcPixel >> 0) & 0xFF),
|
||||
@ -658,6 +669,7 @@ FILE_SCOPE inline void SIMDSetPixel(DTRRenderBuffer *const renderBuffer, const i
|
||||
(u32)(destG) << 8 |
|
||||
(u32)(destB) << 0;
|
||||
bitmapPtr[x + (y * pitchInU32)] = pixel;
|
||||
context.api->LockRelease(renderBuffer->blitLock);
|
||||
|
||||
DTRDebug_CounterIncrement(DTRDebugCounter_SetPixels);
|
||||
}
|
||||
@ -708,7 +720,7 @@ FILE_SCOPE __m128 SIMDSampleTextureForTriangle(const DTRBitmap *const texture, c
|
||||
// IMPORTANT: Debug Markers can _NOT_ be used in primitive rendering functions,
|
||||
// ie. any render function that is used in this call because it'll call into
|
||||
// itself infinitely.
|
||||
FILE_SCOPE void DebugRenderMarkers(DTRRenderBuffer *const renderBuffer, const DqnV2 *const pList,
|
||||
FILE_SCOPE void DebugRenderMarkers(DTRRenderContext context, const DqnV2 *const pList,
|
||||
const i32 pListSize, const DTRRenderTransform transform,
|
||||
bool drawBoundingBox, bool drawBasis, bool drawVertexMarkers)
|
||||
{
|
||||
@ -725,10 +737,10 @@ FILE_SCOPE void DebugRenderMarkers(DTRRenderBuffer *const renderBuffer, const Dq
|
||||
{
|
||||
DqnRect bounds = GetBoundingBox(pList, pListSize);
|
||||
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(bounds.min.x, bounds.min.y), DqnV2i_2f(bounds.min.x, bounds.max.y), red);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(bounds.min.x, bounds.max.y), DqnV2i_2f(bounds.max.x, bounds.max.y), red);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(bounds.max.x, bounds.max.y), DqnV2i_2f(bounds.max.x, bounds.min.y), red);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(bounds.max.x, bounds.min.y), DqnV2i_2f(bounds.min.x, bounds.min.y), red);
|
||||
DTRRender_Line(context, DqnV2i_2f(bounds.min.x, bounds.min.y), DqnV2i_2f(bounds.min.x, bounds.max.y), red);
|
||||
DTRRender_Line(context, DqnV2i_2f(bounds.min.x, bounds.max.y), DqnV2i_2f(bounds.max.x, bounds.max.y), red);
|
||||
DTRRender_Line(context, DqnV2i_2f(bounds.max.x, bounds.max.y), DqnV2i_2f(bounds.max.x, bounds.min.y), red);
|
||||
DTRRender_Line(context, DqnV2i_2f(bounds.max.x, bounds.min.y), DqnV2i_2f(bounds.min.x, bounds.min.y), red);
|
||||
}
|
||||
|
||||
// Draw Coordinate Basis
|
||||
@ -743,9 +755,9 @@ FILE_SCOPE void DebugRenderMarkers(DTRRenderBuffer *const renderBuffer, const Dq
|
||||
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x) * transform.scale.y;
|
||||
DqnV4 coordSysColor = DqnV4_4f(0, 1, 1, 1);
|
||||
i32 axisLen = 50;
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(origin),
|
||||
DTRRender_Line(context, DqnV2i_V2(origin),
|
||||
DqnV2i_V2(origin) + DqnV2i_V2(xAxis * axisLen), coordSysColor);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(origin),
|
||||
DTRRender_Line(context, DqnV2i_V2(origin),
|
||||
DqnV2i_V2(origin) + DqnV2i_V2(yAxis * axisLen), coordSysColor);
|
||||
}
|
||||
}
|
||||
@ -757,11 +769,40 @@ FILE_SCOPE void DebugRenderMarkers(DTRRenderBuffer *const renderBuffer, const Dq
|
||||
for (i32 i = 0; i < pListSize; i++)
|
||||
{
|
||||
DqnV2 p = pList[i];
|
||||
DTRRender_Rectangle(renderBuffer, p - DqnV2_1f(5), p + DqnV2_1f(5), colorList[i]);
|
||||
DTRRender_Rectangle(context, p - DqnV2_1f(5), p + DqnV2_1f(5), colorList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE inline f32 GetCurrZDepth(DTRRenderContext context, i32 posX, i32 posY)
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
DQN_ASSERT(renderBuffer);
|
||||
const u32 zBufferPitch = renderBuffer->width;
|
||||
|
||||
i32 zBufferIndex = posX + (posY * zBufferPitch);
|
||||
DQN_ASSERT(zBufferIndex < (renderBuffer->width * renderBuffer->height));
|
||||
|
||||
context.api->LockAcquire(renderBuffer->zDepthLock);
|
||||
f32 currZDepth = renderBuffer->zBuffer[zBufferIndex];
|
||||
context.api->LockRelease(renderBuffer->zDepthLock);
|
||||
return currZDepth;
|
||||
}
|
||||
|
||||
FILE_SCOPE inline void SetCurrZDepth(DTRRenderContext context, i32 posX, i32 posY, f32 newZDepth)
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
DQN_ASSERT(renderBuffer);
|
||||
const u32 zBufferPitch = renderBuffer->width;
|
||||
|
||||
i32 zBufferIndex = posX + (posY * zBufferPitch);
|
||||
DQN_ASSERT(zBufferIndex < (renderBuffer->width * renderBuffer->height));
|
||||
|
||||
context.api->LockAcquire(renderBuffer->zDepthLock);
|
||||
renderBuffer->zBuffer[zBufferIndex] = newZDepth;
|
||||
context.api->LockRelease(renderBuffer->zDepthLock);
|
||||
}
|
||||
|
||||
#define DEBUG_SIMD_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(type) \
|
||||
do \
|
||||
{ \
|
||||
@ -780,7 +821,7 @@ FILE_SCOPE void DebugRenderMarkers(DTRRenderBuffer *const renderBuffer, const Dq
|
||||
DTRDebug_EndCycleCount(DTRDebugCycleCount_SIMD##type); \
|
||||
} while (0)
|
||||
|
||||
FILE_SCOPE void SIMDRasteriseTrianglePixel(DTRRenderBuffer *const renderBuffer,
|
||||
FILE_SCOPE void SIMDRasteriseTrianglePixel(DTRRenderContext context,
|
||||
const DTRBitmap *const texture, const i32 posX,
|
||||
const i32 posY, const i32 maxX, const DqnV2 uv1,
|
||||
const DqnV2 uv2SubUv1, const DqnV2 uv3SubUv1,
|
||||
@ -790,7 +831,8 @@ FILE_SCOPE void SIMDRasteriseTrianglePixel(DTRRenderBuffer *const renderBuffer,
|
||||
{
|
||||
const __m128 ZERO_4X = _mm_set_ps1(0.0f);
|
||||
const u32 IS_GREATER_MASK = 0xF;
|
||||
const u32 zBufferPitch = renderBuffer->width;
|
||||
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
|
||||
// TODO(doyle): Copy lighting work over. But not important since using this
|
||||
// function causes performance problems.
|
||||
@ -806,13 +848,12 @@ FILE_SCOPE void SIMDRasteriseTrianglePixel(DTRRenderBuffer *const renderBuffer,
|
||||
__m128 barycentric = _mm_mul_ps(signedArea, invSignedAreaParallelogram_4x);
|
||||
__m128 barycentricZ = _mm_mul_ps(triangleZ, barycentric);
|
||||
|
||||
i32 zBufferIndex = posX + (posY * zBufferPitch);
|
||||
f32 pixelZValue =
|
||||
f32 pixelZDepth =
|
||||
((f32 *)&barycentricZ)[0] + ((f32 *)&barycentricZ)[1] + ((f32 *)&barycentricZ)[2];
|
||||
f32 currZValue = renderBuffer->zBuffer[zBufferIndex];
|
||||
if (pixelZValue > currZValue)
|
||||
f32 currZDepth = GetCurrZDepth(context, posX, posY);
|
||||
if (pixelZDepth > currZDepth)
|
||||
{
|
||||
renderBuffer->zBuffer[zBufferIndex] = pixelZValue;
|
||||
SetCurrZDepth(context, posX, posY, pixelZDepth);
|
||||
|
||||
__m128 finalColor = simdColor;
|
||||
if (texture)
|
||||
@ -821,25 +862,27 @@ FILE_SCOPE void SIMDRasteriseTrianglePixel(DTRRenderBuffer *const renderBuffer,
|
||||
uv3SubUv1, barycentric);
|
||||
finalColor = _mm_mul_ps(texSampledColor, simdColor);
|
||||
}
|
||||
SIMDSetPixel(renderBuffer, posX, posY, finalColor, ColorSpace_Linear);
|
||||
SIMDSetPixel(context, posX, posY, finalColor, ColorSpace_Linear);
|
||||
}
|
||||
DEBUG_SIMD_AUTO_CHOOSE_END_CYCLE_COUNT(Triangle_RasterisePixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void SIMDTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1, const DqnV3 p2,
|
||||
const DqnV3 p3, const DqnV2 uv1, const DqnV2 uv2, const DqnV2 uv3,
|
||||
const f32 lightIntensity1, const f32 lightIntensity2,
|
||||
const f32 lightIntensity3, const bool ignoreLight,
|
||||
DTRBitmap *const texture, DqnV4 color, const DqnV2i min,
|
||||
const DqnV2i max)
|
||||
FILE_SCOPE void SIMDTriangle(DTRRenderContext context,
|
||||
const DqnV3 p1, const DqnV3 p2, const DqnV3 p3, const DqnV2 uv1,
|
||||
const DqnV2 uv2, const DqnV2 uv3, const f32 lightIntensity1,
|
||||
const f32 lightIntensity2, const f32 lightIntensity3,
|
||||
const bool ignoreLight, DTRBitmap *const texture, DqnV4 color,
|
||||
const DqnV2i min, const DqnV2i max)
|
||||
|
||||
{
|
||||
DTR_DEBUG_EP_TIMED_FUNCTION();
|
||||
DEBUG_SIMD_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(Triangle);
|
||||
|
||||
DEBUG_SIMD_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(Triangle_Preamble);
|
||||
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Convert color
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -956,14 +999,27 @@ FILE_SCOPE void SIMDTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
__m128 barycentric = _mm_mul_ps(checkArea, invSignedAreaParallelogram_4x);
|
||||
__m128 barycentricZ = _mm_mul_ps(triangleZ, barycentric);
|
||||
|
||||
i32 zBufferIndex = posX + (posY * zBufferPitch);
|
||||
f32 pixelZValue = ((f32 *)&barycentricZ)[0] +
|
||||
f32 pixelZDepth = ((f32 *)&barycentricZ)[0] +
|
||||
((f32 *)&barycentricZ)[1] +
|
||||
((f32 *)&barycentricZ)[2];
|
||||
f32 currZValue = renderBuffer->zBuffer[zBufferIndex];
|
||||
if (pixelZValue > currZValue)
|
||||
|
||||
#if 0
|
||||
// f32 currZDepth = GetCurrZDepth(context, posX, posY);
|
||||
#else
|
||||
DQN_ASSERT(renderBuffer);
|
||||
i32 zBufferIndex = posX + (posY * zBufferPitch);
|
||||
|
||||
context.api->LockAcquire(renderBuffer->zDepthLock);
|
||||
f32 currZDepth = renderBuffer->zBuffer[zBufferIndex];
|
||||
context.api->LockRelease(renderBuffer->zDepthLock);
|
||||
#endif
|
||||
if (pixelZDepth > currZDepth)
|
||||
{
|
||||
// renderBuffer->zBuffer[zBufferIndex] = pixelZValue;
|
||||
|
||||
context.api->LockAcquire(renderBuffer->zDepthLock);
|
||||
renderBuffer->zBuffer[zBufferIndex] = pixelZDepth;
|
||||
context.api->LockRelease(renderBuffer->zDepthLock);
|
||||
|
||||
__m128 finalColor = simdColor;
|
||||
if (!ignoreLight)
|
||||
{
|
||||
@ -988,7 +1044,7 @@ FILE_SCOPE void SIMDTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
__m128 texSampledColor = SIMDSampleTextureForTriangle(texture, uv1, uv2SubUv1, uv3SubUv1, barycentric);
|
||||
finalColor = _mm_mul_ps(texSampledColor, finalColor);
|
||||
}
|
||||
// SIMDSetPixel(renderBuffer, posX, posY, finalColor, ColorSpace_Linear);
|
||||
SIMDSetPixel(context, posX, posY, finalColor, ColorSpace_Linear);
|
||||
}
|
||||
DEBUG_SIMD_AUTO_CHOOSE_END_CYCLE_COUNT(Triangle_RasterisePixel);
|
||||
}
|
||||
@ -1007,16 +1063,22 @@ FILE_SCOPE void SIMDTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
__m128 barycentric = _mm_mul_ps(checkArea, invSignedAreaParallelogram_4x);
|
||||
__m128 barycentricZ = _mm_mul_ps(triangleZ, barycentric);
|
||||
|
||||
i32 zBufferIndex = posX + (posY * zBufferPitch);
|
||||
f32 pixelZValue = ((f32 *)&barycentricZ)[0] +
|
||||
f32 pixelZDepth = ((f32 *)&barycentricZ)[0] +
|
||||
((f32 *)&barycentricZ)[1] +
|
||||
((f32 *)&barycentricZ)[2];
|
||||
f32 currZValue = renderBuffer->zBuffer[zBufferIndex];
|
||||
if (pixelZValue > currZValue)
|
||||
{
|
||||
// renderBuffer->zBuffer[zBufferIndex] = pixelZValue;
|
||||
__m128 finalColor = simdColor;
|
||||
i32 zBufferIndex = posX + (posY * zBufferPitch);
|
||||
|
||||
context.api->LockAcquire(renderBuffer->zDepthLock);
|
||||
f32 currZDepth = renderBuffer->zBuffer[zBufferIndex];
|
||||
context.api->LockRelease(renderBuffer->zDepthLock);
|
||||
|
||||
if (pixelZDepth > currZDepth)
|
||||
{
|
||||
context.api->LockAcquire(renderBuffer->zDepthLock);
|
||||
renderBuffer->zBuffer[zBufferIndex] = pixelZDepth;
|
||||
context.api->LockRelease(renderBuffer->zDepthLock);
|
||||
|
||||
__m128 finalColor = simdColor;
|
||||
if (!ignoreLight)
|
||||
{
|
||||
__m128 barycentricA_4x = _mm_set_ps1(((f32 *)&barycentric)[0]);
|
||||
@ -1040,7 +1102,7 @@ FILE_SCOPE void SIMDTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
__m128 texSampledColor = SIMDSampleTextureForTriangle(texture, uv1, uv2SubUv1, uv3SubUv1, barycentric);
|
||||
finalColor = _mm_mul_ps(texSampledColor, finalColor);
|
||||
}
|
||||
// SIMDSetPixel(renderBuffer, posX, posY, finalColor, ColorSpace_Linear);
|
||||
SIMDSetPixel(context, posX, posY, finalColor, ColorSpace_Linear);
|
||||
}
|
||||
}
|
||||
signedArea2 = _mm_add_ps(signedArea2, signedAreaPixelDeltaX);
|
||||
@ -1063,7 +1125,7 @@ FILE_SCOPE void SIMDTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
DEBUG_SIMD_AUTO_CHOOSE_END_CYCLE_COUNT(Triangle);
|
||||
}
|
||||
|
||||
FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1, const DqnV3 p2,
|
||||
FILE_SCOPE void SlowTriangle(DTRRenderContext context, const DqnV3 p1, const DqnV3 p2,
|
||||
const DqnV3 p3, const DqnV2 uv1, const DqnV2 uv2, const DqnV2 uv3,
|
||||
const f32 lightIntensity1, const f32 lightIntensity2,
|
||||
const f32 lightIntensity3, const bool ignoreLight,
|
||||
@ -1071,7 +1133,6 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
const DqnV2i max)
|
||||
{
|
||||
DTR_DEBUG_EP_TIMED_FUNCTION();
|
||||
|
||||
#define DEBUG_SLOW_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(type) \
|
||||
do \
|
||||
{ \
|
||||
@ -1091,8 +1152,9 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
} while (0)
|
||||
|
||||
DEBUG_SLOW_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(Triangle);
|
||||
|
||||
DEBUG_SLOW_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(Triangle_Preamble);
|
||||
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Convert Color
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -1153,14 +1215,12 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
f32 barycentricB = signedArea2 * invSignedAreaParallelogram;
|
||||
f32 barycentricC = signedArea3 * invSignedAreaParallelogram;
|
||||
|
||||
i32 zBufferIndex = bufferX + (bufferY * zBufferPitch);
|
||||
f32 pixelZValue = p1.z + (barycentricB * (p2SubP1.z)) + (barycentricC * (p3SubP1.z));
|
||||
f32 currZValue = renderBuffer->zBuffer[zBufferIndex];
|
||||
DQN_ASSERT(zBufferIndex < (renderBuffer->width * renderBuffer->height));
|
||||
f32 pixelZDepth = p1.z + (barycentricB * (p2SubP1.z)) + (barycentricC * (p3SubP1.z));
|
||||
f32 currZDepth = GetCurrZDepth(context, bufferX, bufferY);
|
||||
|
||||
if (pixelZValue > currZValue)
|
||||
if (pixelZDepth > currZDepth)
|
||||
{
|
||||
renderBuffer->zBuffer[zBufferIndex] = pixelZValue;
|
||||
SetCurrZDepth(context, bufferX, bufferY, pixelZDepth);
|
||||
DqnV4 finalColor = color;
|
||||
|
||||
if (!ignoreLight)
|
||||
@ -1202,7 +1262,7 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
|
||||
finalColor *= color1;
|
||||
}
|
||||
|
||||
SetPixel(renderBuffer, bufferX, bufferY, finalColor, ColorSpace_Linear);
|
||||
SetPixel(context, bufferX, bufferY, finalColor, ColorSpace_Linear);
|
||||
}
|
||||
DEBUG_SLOW_AUTO_CHOOSE_END_CYCLE_COUNT(Triangle_RasterisePixel);
|
||||
}
|
||||
@ -1247,11 +1307,14 @@ DqnMat4 GLViewport(f32 x, f32 y, f32 width, f32 height)
|
||||
return result;
|
||||
}
|
||||
|
||||
FILE_SCOPE void TexturedTriangleInternal(DTRRenderBuffer *const renderBuffer,
|
||||
RenderLightInternal lighting, DqnV3 p1, DqnV3 p2, DqnV3 p3,
|
||||
DqnV2 uv1, DqnV2 uv2, DqnV2 uv3, DTRBitmap *const texture,
|
||||
DqnV4 color, const DTRRenderTransform transform = DTRRender_DefaultTriangleTransform())
|
||||
FILE_SCOPE void
|
||||
TexturedTriangleInternal(DTRRenderContext context, RenderLightInternal lighting, DqnV3 p1, DqnV3 p2,
|
||||
DqnV3 p3, DqnV2 uv1, DqnV2 uv2, DqnV2 uv3, DTRBitmap *const texture,
|
||||
DqnV4 color,
|
||||
const DTRRenderTransform transform = DTRRender_DefaultTriangleTransform())
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Transform vertexes p1, p2, p3 inplace
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -1308,12 +1371,12 @@ FILE_SCOPE void TexturedTriangleInternal(DTRRenderBuffer *const renderBuffer,
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
if (globalDTRPlatformFlags.canUseSSE2)
|
||||
{
|
||||
SIMDTriangle(renderBuffer, p1, p2, p3, uv1, uv2, uv3, lightIntensity1, lightIntensity2,
|
||||
SIMDTriangle(context, p1, p2, p3, uv1, uv2, uv3, lightIntensity1, lightIntensity2,
|
||||
lightIntensity3, ignoreLight, texture, color, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
SlowTriangle(renderBuffer, p1, p2, p3, uv1, uv2, uv3, lightIntensity1, lightIntensity2,
|
||||
SlowTriangle(context, p1, p2, p3, uv1, uv2, uv3, lightIntensity1, lightIntensity2,
|
||||
lightIntensity3, ignoreLight, texture, color, min, max);
|
||||
}
|
||||
|
||||
@ -1326,7 +1389,7 @@ FILE_SCOPE void TexturedTriangleInternal(DTRRenderBuffer *const renderBuffer,
|
||||
bool drawBasis = false;
|
||||
bool drawVertexMarkers = false;
|
||||
|
||||
DebugRenderMarkers(renderBuffer, pList, DQN_ARRAY_COUNT(pList), transform, drawBoundingBox,
|
||||
DebugRenderMarkers(context, pList, DQN_ARRAY_COUNT(pList), transform, drawBoundingBox,
|
||||
drawBasis, drawVertexMarkers);
|
||||
}
|
||||
}
|
||||
@ -1337,18 +1400,18 @@ FILE_SCOPE RenderLightInternal NullRenderLightInternal()
|
||||
return result;
|
||||
}
|
||||
|
||||
void DTRRender_TexturedTriangle(DTRRenderBuffer *const renderBuffer,
|
||||
void DTRRender_TexturedTriangle(DTRRenderContext context,
|
||||
DqnV3 p1, DqnV3 p2, DqnV3 p3, DqnV2 uv1, DqnV2 uv2, DqnV2 uv3,
|
||||
DTRBitmap *const texture, DqnV4 color,
|
||||
const DTRRenderTransform transform)
|
||||
{
|
||||
TexturedTriangleInternal(renderBuffer, NullRenderLightInternal(), p1, p2, p3, uv1, uv2, uv3, texture,
|
||||
TexturedTriangleInternal(context, NullRenderLightInternal(), p1, p2, p3, uv1, uv2, uv3, texture,
|
||||
color, transform);
|
||||
}
|
||||
|
||||
typedef struct RenderMeshJob
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer;
|
||||
DTRRenderContext context;
|
||||
DTRBitmap *tex;
|
||||
RenderLightInternal lighting;
|
||||
|
||||
@ -1371,15 +1434,18 @@ void MultiThreadedRenderMesh(struct PlatformJobQueue *const queue, void *const u
|
||||
|
||||
RenderMeshJob *job = (RenderMeshJob *)userData;
|
||||
#if 1
|
||||
TexturedTriangleInternal(job->renderBuffer, job->lighting, job->v1, job->v2, job->v3, job->uv1,
|
||||
TexturedTriangleInternal(job->context, job->lighting, job->v1, job->v2, job->v3, job->uv1,
|
||||
job->uv2, job->uv3, job->tex, job->color);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DTRRender_Mesh(DTRRenderBuffer *const renderBuffer, DqnMemStack *const tempStack,
|
||||
PlatformAPI *const api, PlatformJobQueue *const jobQueue, DTRMesh *const mesh,
|
||||
void DTRRender_Mesh(DTRRenderContext context, PlatformJobQueue *const jobQueue, DTRMesh *const mesh,
|
||||
DTRRenderLight lighting, const DqnV3 pos, const DTRRenderTransform transform)
|
||||
{
|
||||
DqnMemStack *tempStack = context.tempStack;
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
PlatformAPI *api = context.api;
|
||||
|
||||
if (!mesh || !renderBuffer || !tempStack || !api || !jobQueue) return;
|
||||
|
||||
DqnMat4 viewPModelViewProjection = {};
|
||||
@ -1411,6 +1477,7 @@ void DTRRender_Mesh(DTRRenderBuffer *const renderBuffer, DqnMemStack *const temp
|
||||
viewPModelViewProjection = DqnMat4_Mul(viewport, modelViewProjection);
|
||||
}
|
||||
|
||||
bool RUN_MULTITHREADED = false;
|
||||
for (u32 i = 0; i < mesh->numFaces; i++)
|
||||
{
|
||||
DTRMeshFace face = mesh->faces[i];
|
||||
@ -1492,7 +1559,6 @@ void DTRRender_Mesh(DTRRenderBuffer *const renderBuffer, DqnMemStack *const temp
|
||||
lightingInternal.numNormals = 3;
|
||||
|
||||
bool DEBUG_NO_TEX = false;
|
||||
bool RUN_MULTITHREADED = true;
|
||||
|
||||
if (RUN_MULTITHREADED)
|
||||
{
|
||||
@ -1506,8 +1572,8 @@ void DTRRender_Mesh(DTRRenderBuffer *const renderBuffer, DqnMemStack *const temp
|
||||
jobData->uv2 = uv2;
|
||||
jobData->uv3 = uv3;
|
||||
jobData->color = color;
|
||||
jobData->renderBuffer = renderBuffer;
|
||||
jobData->lighting = lightingInternal;
|
||||
jobData->context = context;
|
||||
|
||||
if (DTR_DEBUG && DEBUG_NO_TEX)
|
||||
{
|
||||
@ -1537,12 +1603,12 @@ void DTRRender_Mesh(DTRRenderBuffer *const renderBuffer, DqnMemStack *const temp
|
||||
{
|
||||
if (DTR_DEBUG && DEBUG_NO_TEX)
|
||||
{
|
||||
TexturedTriangleInternal(renderBuffer, lightingInternal, v1.xyz, v2.xyz, v3.xyz,
|
||||
TexturedTriangleInternal(context, lightingInternal, v1.xyz, v2.xyz, v3.xyz,
|
||||
uv1, uv2, uv3, NULL, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
TexturedTriangleInternal(renderBuffer, lightingInternal, v1.xyz, v2.xyz, v3.xyz,
|
||||
TexturedTriangleInternal(context, lightingInternal, v1.xyz, v2.xyz, v3.xyz,
|
||||
uv1, uv2, uv3, &mesh->tex, color);
|
||||
}
|
||||
}
|
||||
@ -1550,28 +1616,33 @@ void DTRRender_Mesh(DTRRenderBuffer *const renderBuffer, DqnMemStack *const temp
|
||||
if (DTR_DEBUG && DEBUG_WIREFRAME)
|
||||
{
|
||||
DqnV4 wireColor = DqnV4_4f(1.0f, 1.0f, 1.0f, 0.01f);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(v1.xy), DqnV2i_V2(v2.xy), wireColor);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(v2.xy), DqnV2i_V2(v3.xy), wireColor);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(v3.xy), DqnV2i_V2(v1.xy), wireColor);
|
||||
DTRRender_Line(context, DqnV2i_V2(v1.xy), DqnV2i_V2(v2.xy), wireColor);
|
||||
DTRRender_Line(context, DqnV2i_V2(v2.xy), DqnV2i_V2(v3.xy), wireColor);
|
||||
DTRRender_Line(context, DqnV2i_V2(v3.xy), DqnV2i_V2(v1.xy), wireColor);
|
||||
}
|
||||
}
|
||||
|
||||
if (RUN_MULTITHREADED)
|
||||
{
|
||||
while (api->QueueTryExecuteNextJob(jobQueue))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void DTRRender_Triangle(DTRRenderBuffer *const renderBuffer, DqnV3 p1, DqnV3 p2, DqnV3 p3,
|
||||
DqnV4 color, const DTRRenderTransform transform)
|
||||
void DTRRender_Triangle(DTRRenderContext context, DqnV3 p1, DqnV3 p2, DqnV3 p3, DqnV4 color,
|
||||
const DTRRenderTransform transform)
|
||||
{
|
||||
const DqnV2 NO_UV = {};
|
||||
DTRBitmap *const NO_TEX = NULL;
|
||||
TexturedTriangleInternal(renderBuffer, NullRenderLightInternal(), p1, p2, p3, NO_UV, NO_UV,
|
||||
TexturedTriangleInternal(context, NullRenderLightInternal(), p1, p2, p3, NO_UV, NO_UV,
|
||||
NO_UV, NO_TEX, color, transform);
|
||||
}
|
||||
|
||||
void DTRRender_Bitmap(DTRRenderBuffer *const renderBuffer, DTRBitmap *const bitmap, DqnV2 pos,
|
||||
void DTRRender_Bitmap(DTRRenderContext context, DTRBitmap *const bitmap, DqnV2 pos,
|
||||
const DTRRenderTransform transform, DqnV4 color)
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
|
||||
if (!bitmap || !bitmap->memory || !renderBuffer) return;
|
||||
DTR_DEBUG_EP_TIMED_FUNCTION();
|
||||
|
||||
@ -1745,7 +1816,7 @@ void DTRRender_Bitmap(DTRRenderBuffer *const renderBuffer, DTRBitmap *const bitm
|
||||
blend.g *= color.g;
|
||||
blend.b *= color.b;
|
||||
|
||||
SetPixel(renderBuffer, bufferX, bufferY, blend, ColorSpace_Linear);
|
||||
SetPixel(context, bufferX, bufferY, blend, ColorSpace_Linear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1759,14 +1830,14 @@ void DTRRender_Bitmap(DTRRenderBuffer *const renderBuffer, DTRBitmap *const bitm
|
||||
bool drawBasis = true;
|
||||
bool drawVertexMarkers = true;
|
||||
|
||||
DebugRenderMarkers(renderBuffer, pList, RECT_PLIST_SIZE, transform, drawBoundingBox,
|
||||
DebugRenderMarkers(context, pList, RECT_PLIST_SIZE, transform, drawBoundingBox,
|
||||
drawBasis, drawVertexMarkers);
|
||||
}
|
||||
}
|
||||
|
||||
void DTRRender_Clear(DTRRenderBuffer *const renderBuffer,
|
||||
DqnV3 color)
|
||||
void DTRRender_Clear(DTRRenderContext context, DqnV3 color)
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer = context.renderBuffer;
|
||||
if (!renderBuffer) return;
|
||||
|
||||
DQN_ASSERT(color.r >= 0.0f && color.r <= 1.0f);
|
||||
|
@ -17,6 +17,9 @@ typedef struct DTRRenderBuffer
|
||||
i32 height;
|
||||
i32 bytesPerPixel;
|
||||
|
||||
PlatformLock *volatile zDepthLock;
|
||||
PlatformLock *volatile blitLock;
|
||||
|
||||
u8 *memory; // Format: XX RR GG BB, and has (width * height * bytesPerPixels) elements
|
||||
f32 *zBuffer; // zBuffer has (width * height) elements
|
||||
|
||||
@ -74,15 +77,22 @@ typedef struct DTRRenderLight
|
||||
DqnV4 color;
|
||||
} DTRRenderLight;
|
||||
|
||||
typedef struct DTRRenderContext
|
||||
{
|
||||
DTRRenderBuffer *renderBuffer;
|
||||
DqnMemStack *tempStack;
|
||||
PlatformAPI *api;
|
||||
} DTRRenderContext;
|
||||
|
||||
// NOTE: All colors should be in the range of [0->1] where DqnV4 is a struct with 4 floats, rgba
|
||||
// Leaving len = -1 for text will make the system use strlen to determine len.
|
||||
void DTRRender_Text (DTRRenderBuffer *const renderBuffer, const DTRFont font, DqnV2 pos, const char *const text, DqnV4 color = DqnV4_1f(1), i32 len = -1);
|
||||
void DTRRender_Line (DTRRenderBuffer *const renderBuffer, DqnV2i a, DqnV2i b, DqnV4 color);
|
||||
void DTRRender_Rectangle (DTRRenderBuffer *const renderBuffer, DqnV2 min, DqnV2 max, DqnV4 color, const DTRRenderTransform transform = DTRRender_DefaultTransform());
|
||||
void DTRRender_Mesh (DTRRenderBuffer *const renderBuffer, DqnMemStack *const tempStack, PlatformAPI *const api, PlatformJobQueue *const jobQueue, DTRMesh *const mesh, DTRRenderLight lighting, const DqnV3 pos, const DTRRenderTransform transform);
|
||||
void DTRRender_Triangle (DTRRenderBuffer *const renderBuffer, DqnV3 p1, DqnV3 p2, DqnV3 p3, DqnV4 color, const DTRRenderTransform transform = DTRRender_DefaultTriangleTransform());
|
||||
void DTRRender_TexturedTriangle(DTRRenderBuffer *const renderBuffer, DqnV3 p1, DqnV3 p2, DqnV3 p3, DqnV2 uv1, DqnV2 uv2, DqnV2 uv3, DTRBitmap *const texture, DqnV4 color, const DTRRenderTransform transform = DTRRender_DefaultTriangleTransform());
|
||||
void DTRRender_Bitmap (DTRRenderBuffer *const renderBuffer, DTRBitmap *const bitmap, DqnV2 pos, const DTRRenderTransform transform = DTRRender_DefaultTransform(), DqnV4 color = DqnV4_4f(1, 1, 1, 1));
|
||||
void DTRRender_Clear (DTRRenderBuffer *const renderBuffer, DqnV3 color);
|
||||
void DTRRender_Text (DTRRenderContext context, const DTRFont font, DqnV2 pos, const char *const text, DqnV4 color = DqnV4_1f(1), i32 len = -1);
|
||||
void DTRRender_Line (DTRRenderContext context, DqnV2i a, DqnV2i b, DqnV4 color);
|
||||
void DTRRender_Rectangle (DTRRenderContext context, DqnV2 min, DqnV2 max, DqnV4 color, const DTRRenderTransform transform = DTRRender_DefaultTransform());
|
||||
void DTRRender_Mesh (DTRRenderContext context, PlatformJobQueue *const jobQueue, DTRMesh *const mesh, DTRRenderLight lighting, const DqnV3 pos, const DTRRenderTransform transform);
|
||||
void DTRRender_Triangle (DTRRenderContext context, DqnV3 p1, DqnV3 p2, DqnV3 p3, DqnV4 color, const DTRRenderTransform transform = DTRRender_DefaultTriangleTransform());
|
||||
void DTRRender_TexturedTriangle(DTRRenderContext context, DqnV3 p1, DqnV3 p2, DqnV3 p3, DqnV2 uv1, DqnV2 uv2, DqnV2 uv3, DTRBitmap *const texture, DqnV4 color, const DTRRenderTransform transform = DTRRender_DefaultTriangleTransform());
|
||||
void DTRRender_Bitmap (DTRRenderContext context, DTRBitmap *const bitmap, DqnV2 pos, const DTRRenderTransform transform = DTRRender_DefaultTransform(), DqnV4 color = DqnV4_4f(1, 1, 1, 1));
|
||||
void DTRRender_Clear (DTRRenderContext context, DqnV3 color);
|
||||
|
||||
#endif
|
||||
|
@ -8,15 +8,57 @@
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
|
||||
const char *const DLL_NAME = "dtrenderer.dll";
|
||||
const char *const DLL_TMP_NAME = "dtrenderer_temp.dll";
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Platform Mutex/Lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct PlatformLock
|
||||
{
|
||||
CRITICAL_SECTION critSection;
|
||||
} PlatformLock;
|
||||
|
||||
PlatformLock *Platform_LockInit(DqnMemStack *const stack)
|
||||
{
|
||||
const u32 DEFAULT_SPIN_COUNT = 16000;
|
||||
PlatformLock *lock = (PlatformLock *)DqnMemStack_Push(stack, sizeof(*lock));
|
||||
if (lock)
|
||||
{
|
||||
if (InitializeCriticalSectionEx(&lock->critSection, DEFAULT_SPIN_COUNT, 0))
|
||||
{
|
||||
return lock;
|
||||
}
|
||||
else
|
||||
{
|
||||
DqnMemStack_Pop(stack, lock, sizeof(*lock));
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Platform_LockAcquire(PlatformLock *const lock)
|
||||
{
|
||||
if (lock) EnterCriticalSection(&lock->critSection);
|
||||
}
|
||||
|
||||
void Platform_LockRelease(PlatformLock *const lock)
|
||||
{
|
||||
if (lock) LeaveCriticalSection(&lock->critSection);
|
||||
}
|
||||
|
||||
void Platform_LockDelete(PlatformLock *const lock)
|
||||
{
|
||||
if (lock)
|
||||
{
|
||||
DeleteCriticalSection(&lock->critSection);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Platform Multi Threading
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct PlatformJobQueue
|
||||
{
|
||||
PlatformJob volatile *jobList;
|
||||
PlatformJob *volatile jobList;
|
||||
LONG size;
|
||||
|
||||
// NOTE: Modified by main+worker threads
|
||||
@ -43,6 +85,13 @@ bool Platform_QueueAddJob(PlatformJobQueue *const queue, const PlatformJob job)
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE_SCOPE void DebugWin32JobPrintNumber(PlatformJobQueue *const queue, void *const userData)
|
||||
{
|
||||
i32 numberToPrint = *((i32 *)userData);
|
||||
DqnWin32_OutputDebugString("Thread %d: Printing number: %d\n", GetCurrentThreadId(),
|
||||
numberToPrint);
|
||||
}
|
||||
|
||||
bool Platform_QueueTryExecuteNextJob(PlatformJobQueue *const queue)
|
||||
{
|
||||
LONG originalJobToExecute = queue->jobToExecuteIndex;
|
||||
@ -167,6 +216,10 @@ void Platform_FileClose(PlatformFile *const file)
|
||||
#include <Windows.h>
|
||||
#include <Windowsx.h> // For GET_X|Y_LPARAM(), mouse input
|
||||
#include <Psapi.h> // For win32 GetProcessMemoryInfo()
|
||||
|
||||
const char *const DLL_NAME = "dtrenderer.dll";
|
||||
const char *const DLL_TMP_NAME = "dtrenderer_temp.dll";
|
||||
|
||||
typedef struct Win32RenderBitmap
|
||||
{
|
||||
BITMAPINFO info;
|
||||
@ -510,13 +563,6 @@ i32 Win32GetModuleDirectory(char *const buf, const u32 bufLen)
|
||||
return lastSlashIndex;
|
||||
}
|
||||
|
||||
FILE_SCOPE void DebugWin32JobPrintNumber(PlatformJobQueue *const queue, void *const userData)
|
||||
{
|
||||
i32 numberToPrint = *((i32 *)userData);
|
||||
DqnWin32_OutputDebugString("Thread %d: Printing number: %d\n", GetCurrentThreadId(),
|
||||
numberToPrint);
|
||||
}
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
|
||||
@ -637,6 +683,11 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
platformAPI.QueueAddJob = Platform_QueueAddJob;
|
||||
platformAPI.QueueTryExecuteNextJob = Platform_QueueTryExecuteNextJob;
|
||||
|
||||
platformAPI.LockInit = Platform_LockInit;
|
||||
platformAPI.LockAcquire = Platform_LockAcquire;
|
||||
platformAPI.LockRelease = Platform_LockRelease;
|
||||
platformAPI.LockDelete = Platform_LockDelete;
|
||||
|
||||
PlatformJobQueue jobQueue = {};
|
||||
|
||||
PlatformInput platformInput = {};
|
||||
@ -646,6 +697,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
platformInput.flags.canUseRdtsc = IsProcessorFeaturePresent(PF_RDTSC_INSTRUCTION_AVAILABLE);
|
||||
|
||||
// Threading
|
||||
PlatformJob jobQueueMemory[512] = {};
|
||||
{
|
||||
DqnMemStackTempRegion memRegion;
|
||||
if (!DqnMemStackTempRegion_Begin(&memRegion, &globalPlatformMemory.tempStack))
|
||||
@ -717,15 +769,12 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Threading
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
const i32 QUEUE_SIZE = 512;
|
||||
jobQueue.jobList = (PlatformJob *)DqnMemStack_Push(&globalPlatformMemory.mainStack,
|
||||
sizeof(*jobQueue.jobList) * QUEUE_SIZE);
|
||||
jobQueue.jobList = jobQueueMemory;
|
||||
jobQueue.size = DQN_ARRAY_COUNT(jobQueueMemory);
|
||||
|
||||
// NOTE: InterlockedIncrement requires things to be on 32bit boundaries.
|
||||
DQN_ASSERT(((size_t)&jobQueue.jobToExecuteIndex) % 4 == 0);
|
||||
|
||||
if (jobQueue.jobList)
|
||||
{
|
||||
// NOTE: (numCores - 1), 1 core is already exclusively for main thread
|
||||
i32 availableThreads = (numCores - 1) * numLogicalCores;
|
||||
|
||||
@ -745,8 +794,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
// Create jobs
|
||||
jobQueue.size = QUEUE_SIZE;
|
||||
#if 0
|
||||
// DEBUG Create jobs
|
||||
for (i32 i = 0; i < 20; i++)
|
||||
{
|
||||
PlatformJob job = {};
|
||||
@ -761,6 +810,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
|
||||
while (Platform_QueueTryExecuteNextJob(&jobQueue))
|
||||
;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -768,7 +818,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
DqnWin32_DisplayLastError("CreateSemaphore() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Update Loop
|
||||
|
@ -39,7 +39,7 @@ REM wd4100 unused argument parameters
|
||||
REM wd4201 nonstandard extension used: nameless struct/union
|
||||
REM wd4189 local variable is initialised but not referenced
|
||||
REM wd4505 unreferenced local function not used will be removed
|
||||
set CompileFlags=-EHsc -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc /I..\src\external\
|
||||
set CompileFlags=-EHsc -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -O2 -FAsc /I..\src\external\
|
||||
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
|
||||
set Win32Flags=/FmWin32DTRenderer /FeWin32DTRenderer
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user