diff --git a/examples/gputest/source/main.c b/examples/gputest/source/main.c index 0e2adb1..cdf449e 100644 --- a/examples/gputest/source/main.c +++ b/examples/gputest/source/main.c @@ -73,7 +73,7 @@ static void drawScene(float trX, float trY) MtxStack_Update(&projMtx); MtxStack_Update(&mdlvMtx); - C3D_DrawArray(&myVbo, GPU_TRIANGLES); + C3D_DrawArrays(GPU_TRIANGLES, 0, myVbo.vertexCount); C3D_Flush(); } @@ -96,7 +96,7 @@ static void drawSceneBottom(float trX, float trY) MtxStack_Update(&projMtx); MtxStack_Update(&mdlvMtx); - C3D_DrawArray(&myVbo, GPU_TRIANGLES); + C3D_DrawArrays(GPU_TRIANGLES, 0, myVbo.vertexCount); C3D_Flush(); } @@ -139,16 +139,20 @@ int main() // Configure attributes C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); AttrInfo_Init(attrInfo); - AttrInfo_AddParam(attrInfo, GPU_FLOAT, 3); // position - AttrInfo_AddParam(attrInfo, GPU_FLOAT, 2); // texcoord - AttrInfo_AddParam(attrInfo, GPU_FLOAT, 3); // vertex color - AttrInfo_AddBuffer(attrInfo, 0, sizeof(vertex_t), 3, 0x210); + AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // position + AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // texcoord + AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 3); // vertex color // Configure VBO C3D_VBOInit(&myVbo, sizeof(vertices)); C3D_VBOAddData(&myVbo, vertices, sizeof(vertices), sizeof(vertices)/sizeof(vertex_t)); - // Clear buffers + // Configure buffers + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, myVbo.data, sizeof(vertex_t), 3, 0x210); + + // Clear renderbuffers C3D_RenderBufClear(&rbTop); C3D_RenderBufClear(&rbBot); diff --git a/include/c3d/attribs.h b/include/c3d/attribs.h index c3f3e3e..71d404d 100644 --- a/include/c3d/attribs.h +++ b/include/c3d/attribs.h @@ -3,29 +3,14 @@ typedef struct { - u32 offset; u32 flags[2]; -} C3D_AttrBufCfg; - -typedef struct -{ - // Base physical address intentionally left out - // Write to 0x0201 instead of 0x0200 - u32 flags[2]; - C3D_AttrBufCfg buffers[12]; -} C3D_AttrCfg; - -typedef struct -{ - C3D_AttrCfg cfg; u64 permutation; int attrCount; - int bufCount; } C3D_AttrInfo; void AttrInfo_Init(C3D_AttrInfo* info); -bool AttrInfo_AddParam(C3D_AttrInfo* info, GPU_FORMATS format, int count); -bool AttrInfo_AddBuffer(C3D_AttrInfo* info, ptrdiff_t offset, ptrdiff_t stride, int attribCount, u64 permutation); +int AttrInfo_AddLoader(C3D_AttrInfo* info, int regId, GPU_FORMATS format, int count); +int AttrInfo_AddFixed(C3D_AttrInfo* info, int regId); C3D_AttrInfo* C3D_GetAttrInfo(void); void C3D_SetAttrInfo(C3D_AttrInfo* info); diff --git a/include/c3d/base.h b/include/c3d/base.h index ea43cb8..f317117 100644 --- a/include/c3d/base.h +++ b/include/c3d/base.h @@ -12,8 +12,8 @@ void C3D_BindProgram(shaderProgram_s* program); void C3D_SetViewport(u32 x, u32 y, u32 w, u32 h); void C3D_SetScissor(GPU_SCISSORMODE mode, u32 x, u32 y, u32 w, u32 h); -void C3D_DrawArray(C3D_VBO* vbo, GPU_Primitive_t primitive); -void C3D_DrawElements(C3D_IBO* ibo, GPU_Primitive_t primitive); +void C3D_DrawArrays(GPU_Primitive_t primitive, int first, int size); +void C3D_DrawElements(GPU_Primitive_t primitive, int count, int type, const void* indices); static inline void C3D_FlushAwait(void) { diff --git a/include/c3d/buffers.h b/include/c3d/buffers.h index eb3fed3..b8c8356 100644 --- a/include/c3d/buffers.h +++ b/include/c3d/buffers.h @@ -1,6 +1,25 @@ #pragma once #include "types.h" +typedef struct +{ + u32 offset; + u32 flags[2]; +} C3D_BufCfg; + +typedef struct +{ + u32 base_paddr; + int bufCount; + C3D_BufCfg buffers[12]; +} C3D_BufInfo; + +void BufInfo_Init(C3D_BufInfo* info); +int BufInfo_Add(C3D_BufInfo* info, const void* data, ptrdiff_t stride, int attribCount, u64 permutation); + +C3D_BufInfo* C3D_GetBufInfo(void); +void C3D_SetBufInfo(C3D_BufInfo* info); + typedef struct { void* data; @@ -12,7 +31,6 @@ typedef struct bool C3D_VBOInit(C3D_VBO* vbo, size_t capacity); bool C3D_VBOAddData(C3D_VBO* vbo, const void* data, size_t size, int vertexCount); void C3D_VBOFlush(C3D_VBO* vbo); -void C3D_VBOBind(C3D_VBO* vbo); void C3D_VBODelete(C3D_VBO* vbo); typedef struct diff --git a/source/attribs.c b/source/attribs.c index 32b0ac9..04ac48d 100644 --- a/source/attribs.c +++ b/source/attribs.c @@ -5,32 +5,33 @@ void AttrInfo_Init(C3D_AttrInfo* info) { memset(info, 0, sizeof(*info)); - info->cfg.flags[1] = 0xFFF << 16; + info->flags[1] = 0xFFF << 16; } -bool AttrInfo_AddParam(C3D_AttrInfo* info, GPU_FORMATS format, int count) +int AttrInfo_AddLoader(C3D_AttrInfo* info, int regId, GPU_FORMATS format, int count) { - if (info->attrCount == 12) return false; + if (info->attrCount == 12) return -1; int id = info->attrCount++; + if (regId < 0) regId = id; if (id < 8) - info->cfg.flags[0] |= GPU_ATTRIBFMT(id, count, format); + info->flags[0] |= GPU_ATTRIBFMT(id, count, format); else - info->cfg.flags[1] |= GPU_ATTRIBFMT(id-8, count, format); - info->cfg.flags[1] &= ~BIT(id+16); - info->cfg.flags[1] = (info->cfg.flags[1] &~ 0xF0000000) | (id << 28); - info->permutation |= id << (id*4); - return true; + info->flags[1] |= GPU_ATTRIBFMT(id-8, count, format); + + info->flags[1] = (info->flags[1] &~ (0xF0000000 | BIT(id+16))) | (id << 28); + info->permutation |= regId << (id*4); + return id; } -bool AttrInfo_AddBuffer(C3D_AttrInfo* info, ptrdiff_t offset, ptrdiff_t stride, int attribCount, u64 permutation) +int AttrInfo_AddFixed(C3D_AttrInfo* info, int regId) { - if (info->bufCount == 12) return false; - int id = info->bufCount++; - C3D_AttrBufCfg* buf = &info->cfg.buffers[id]; - buf->offset = offset; - buf->flags[0] = permutation & 0xFFFFFFFF; - buf->flags[1] = (permutation >> 32) | (stride << 16) | (attribCount << 28); - return true; + if (info->attrCount == 12) return -1; + int id = info->attrCount++; + if (regId < 0) regId = id; + + info->flags[1] = (info->flags[1] &~ 0xF0000000) | (id << 28); + info->permutation |= regId << (id*4); + return id; } C3D_AttrInfo* C3D_GetAttrInfo(void) @@ -40,7 +41,7 @@ C3D_AttrInfo* C3D_GetAttrInfo(void) if (!(ctx->flags & C3DiF_Active)) return NULL; - ctx->flags |= C3DiF_AttrBuf; + ctx->flags |= C3DiF_AttrInfo; return &ctx->attrInfo; } @@ -51,13 +52,14 @@ void C3D_SetAttrInfo(C3D_AttrInfo* info) if (!(ctx->flags & C3DiF_Active)) return; - memcpy(&ctx->attrInfo, info, sizeof(*info)); - ctx->flags |= C3DiF_AttrBuf; + if (info != &ctx->attrInfo) + memcpy(&ctx->attrInfo, info, sizeof(*info)); + ctx->flags |= C3DiF_AttrInfo; } void C3Di_AttrInfoBind(C3D_AttrInfo* info) { - GPUCMD_AddIncrementalWrites(GPUREG_ATTRIBBUFFERS_FORMAT_LOW, (u32*)&info->cfg, sizeof(C3D_AttrCfg)/sizeof(u32)); + GPUCMD_AddIncrementalWrites(GPUREG_ATTRIBBUFFERS_FORMAT_LOW, (u32*)info->flags, sizeof(info->flags)/sizeof(u32)); GPUCMD_AddMaskedWrite(GPUREG_VSH_INPUTBUFFER_CONFIG, 0xB, 0xA0000000 | (info->attrCount - 1)); GPUCMD_AddWrite(GPUREG_0242, info->attrCount - 1); GPUCMD_AddIncrementalWrites(GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW, (u32*)&info->permutation, 2); diff --git a/source/base.c b/source/base.c index e6fb7f4..7ca1d6c 100644 --- a/source/base.c +++ b/source/base.c @@ -47,7 +47,7 @@ static void C3Di_AptEventHook(int hookType, void* param) } case APTHOOK_ONRESTORE: { - ctx->flags |= C3DiF_AttrBuf | C3DiF_Effect | C3DiF_RenderBuf + ctx->flags |= C3DiF_AttrInfo | C3DiF_BufInfo | C3DiF_Effect | C3DiF_RenderBuf | C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_TexAll | C3DiF_TexEnvAll; break; @@ -150,12 +150,18 @@ void C3Di_UpdateContext(void) GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, ctx->scissor, 3); } - if (ctx->flags & C3DiF_AttrBuf) + if (ctx->flags & C3DiF_AttrInfo) { - ctx->flags &= ~C3DiF_AttrBuf; + ctx->flags &= ~C3DiF_AttrInfo; C3Di_AttrInfoBind(&ctx->attrInfo); } + if (ctx->flags & C3DiF_BufInfo) + { + ctx->flags &= ~C3DiF_BufInfo; + C3Di_BufInfoBind(&ctx->bufInfo); + } + if (ctx->flags & C3DiF_Effect) { ctx->flags &= ~C3DiF_Effect; diff --git a/source/buffers.c b/source/buffers.c new file mode 100644 index 0000000..6a41a7a --- /dev/null +++ b/source/buffers.c @@ -0,0 +1,55 @@ +#include +#include +#include "context.h" + +#define BUFFER_BASE_PADDR 0x18000000 + +void BufInfo_Init(C3D_BufInfo* info) +{ + memset(info, 0, sizeof(*info)); + info->base_paddr = BUFFER_BASE_PADDR; +} + +int BufInfo_Add(C3D_BufInfo* info, const void* data, ptrdiff_t stride, int attribCount, u64 permutation) +{ + if (info->bufCount == 12) return -1; + int id = info->bufCount++; + + u32 pa = osConvertVirtToPhys((u32)data); + if (pa < info->base_paddr) return -2; + + C3D_BufCfg* buf = &info->buffers[id]; + buf->offset = pa - info->base_paddr; + buf->flags[0] = permutation & 0xFFFFFFFF; + buf->flags[1] = (permutation >> 32) | (stride << 16) | (attribCount << 28); + return id; +} + +C3D_BufInfo* C3D_GetBufInfo(void) +{ + C3D_Context* ctx = C3Di_GetContext(); + + if (!(ctx->flags & C3DiF_Active)) + return NULL; + + ctx->flags |= C3DiF_BufInfo; + return &ctx->bufInfo; +} + +void C3D_SetBufInfo(C3D_BufInfo* info) +{ + C3D_Context* ctx = C3Di_GetContext(); + + if (!(ctx->flags & C3DiF_Active)) + return; + + if (info != &ctx->bufInfo) + memcpy(&ctx->bufInfo, info, sizeof(*info)); + ctx->flags |= C3DiF_BufInfo; +} + +void C3Di_BufInfoBind(C3D_BufInfo* info) +{ + GPUCMD_AddWrite(GPUREG_ATTRIBBUFFERS_LOC, info->base_paddr >> 3); + GPUCMD_AddIncrementalWrites(GPUREG_ATTRIBBUFFER0_CONFIG0, (u32*)info->buffers, sizeof(info->buffers)/sizeof(u32)); +} diff --git a/source/context.h b/source/context.h index 9bb72d4..93ca0e7 100644 --- a/source/context.h +++ b/source/context.h @@ -1,8 +1,8 @@ #pragma once #include #include -#include #include +#include #include #include #include @@ -29,8 +29,8 @@ typedef struct u32 flags; shaderProgram_s* program; - u32 vboPos; C3D_AttrInfo attrInfo; + C3D_BufInfo bufInfo; C3D_Effect effect; C3D_Tex* tex[3]; @@ -46,12 +46,13 @@ enum { C3DiF_Active = BIT(0), C3DiF_NeedFinishDrawing = BIT(1), - C3DiF_AttrBuf = BIT(2), - C3DiF_Effect = BIT(3), - C3DiF_RenderBuf = BIT(4), - C3DiF_Viewport = BIT(5), - C3DiF_Scissor = BIT(6), - C3DiF_Program = BIT(7), + C3DiF_AttrInfo = BIT(2), + C3DiF_BufInfo = BIT(3), + C3DiF_Effect = BIT(4), + C3DiF_RenderBuf = BIT(5), + C3DiF_Viewport = BIT(6), + C3DiF_Scissor = BIT(7), + C3DiF_Program = BIT(8), #define C3DiF_Tex(n) BIT(23+(n)) C3DiF_TexAll = 7 << 23, @@ -66,8 +67,8 @@ static inline C3D_Context* C3Di_GetContext(void) } void C3Di_UpdateContext(void); -void C3Di_IBOBind(C3D_IBO* ibo); void C3Di_AttrInfoBind(C3D_AttrInfo* info); +void C3Di_BufInfoBind(C3D_BufInfo* info); void C3Di_TexEnvBind(int id, C3D_TexEnv* env); void C3Di_EffectBind(C3D_Effect* effect); void C3Di_RenderBufBind(C3D_RenderBuf* rb); diff --git a/source/drawArray.c b/source/drawArrays.c similarity index 78% rename from source/drawArray.c rename to source/drawArrays.c index c349529..ec2e0c5 100644 --- a/source/drawArray.c +++ b/source/drawArrays.c @@ -1,8 +1,7 @@ #include "context.h" -void C3D_DrawArray(C3D_VBO* vbo, GPU_Primitive_t primitive) +void C3D_DrawArrays(GPU_Primitive_t primitive, int first, int size) { - C3D_VBOBind(vbo); C3Di_UpdateContext(); // Set primitive type @@ -11,7 +10,9 @@ void C3D_DrawArray(C3D_VBO* vbo, GPU_Primitive_t primitive) // The index buffer is not used, but 0x000F0227 is still required GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000); // Number of vertices - GPUCMD_AddWrite(GPUREG_NUMVERTICES, vbo->vertexCount); + GPUCMD_AddWrite(GPUREG_NUMVERTICES, size); + // First vertex + GPUCMD_AddWrite(GPUREG_DRAW_VERTEX_OFFSET, first); // Unknown commands GPUCMD_AddMaskedWrite(GPUREG_0253, 1, 0x00000001); diff --git a/source/drawElements.c b/source/drawElements.c index fd3a329..c7bda83 100644 --- a/source/drawElements.c +++ b/source/drawElements.c @@ -1,16 +1,21 @@ #include "context.h" -void C3D_DrawElements(C3D_IBO* ibo, GPU_Primitive_t primitive) +void C3D_DrawElements(GPU_Primitive_t primitive, int count, int type, const void* indices) { + C3D_Context* ctx = C3Di_GetContext(); + u32 pa = osConvertVirtToPhys((u32)indices); + u32 base = ctx->bufInfo.base_paddr; + if (pa < base) return; + C3Di_UpdateContext(); // Set primitive type GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 2, primitive); GPUCMD_AddMaskedWrite(GPUREG_025F, 2, 0x00000001); - // Bind the IBO - C3Di_IBOBind(ibo); + // Configure the index buffer + GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, (pa - base) | (type << 31)); // Number of vertices - GPUCMD_AddWrite(GPUREG_NUMVERTICES, ibo->indexCount); + GPUCMD_AddWrite(GPUREG_NUMVERTICES, count); // Unknown commands GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 2, 0x00000100); diff --git a/source/ibo.c b/source/ibo.c index 761e1bc..eb4afc5 100644 --- a/source/ibo.c +++ b/source/ibo.c @@ -30,15 +30,6 @@ void C3D_IBOFlush(C3D_IBO* ibo) GSPGPU_FlushDataCache(ibo->data, ibo->indexCount*stride); } -void C3Di_IBOBind(C3D_IBO* ibo) -{ - C3D_Context* ctx = C3Di_GetContext(); - - u32 pa = osConvertVirtToPhys((u32)ibo->data); - u32 offset = (pa - ctx->vboPos) &~ BIT(31); - GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, offset | (ibo->format << 31)); -} - void C3D_IBODelete(C3D_IBO* ibo) { if (!ibo->data) return; diff --git a/source/renderbuffer.c b/source/renderbuffer.c index 8b5b15a..bff441a 100644 --- a/source/renderbuffer.c +++ b/source/renderbuffer.c @@ -41,7 +41,7 @@ void C3D_RenderBufClearAsync(C3D_RenderBuf* rb) { u32 colorBufSize = calcColorBufSize(rb->width, rb->height, rb->colorFmt); u32 depthBufSize = calcDepthBufSize(rb->width, rb->height, rb->depthFmt); - GX_SetMemoryFill( + GX_MemoryFill( (u32*)rb->colorBuf, rb->clearColor, (u32*)((u8*)rb->colorBuf+colorBufSize), BIT(0) | ((u32)colorFmtSizes[rb->colorFmt] << 8), (u32*)rb->depthBuf, rb->clearDepth, (u32*)((u8*)rb->depthBuf+depthBufSize), BIT(0) | ((u32)depthFmtSizes[rb->depthFmt] << 8)); } @@ -49,7 +49,7 @@ void C3D_RenderBufClearAsync(C3D_RenderBuf* rb) void C3D_RenderBufTransferAsync(C3D_RenderBuf* rb, u32* frameBuf, u32 flags) { u32 dim = GX_BUFFER_DIM((u32)rb->width, (u32)rb->height); - GX_SetDisplayTransfer((u32*)rb->colorBuf, dim, frameBuf, dim, flags); + GX_DisplayTransfer((u32*)rb->colorBuf, dim, frameBuf, dim, flags); } void C3D_RenderBufBind(C3D_RenderBuf* rb) diff --git a/source/vbo.c b/source/vbo.c index 717a655..c7608ef 100644 --- a/source/vbo.c +++ b/source/vbo.c @@ -30,17 +30,6 @@ void C3D_VBOFlush(C3D_VBO* vbo) GSPGPU_FlushDataCache(vbo->data, vbo->size); } -void C3D_VBOBind(C3D_VBO* vbo) -{ - C3D_Context* ctx = C3Di_GetContext(); - - if (!(ctx->flags & C3DiF_Active)) - return; - - ctx->vboPos = osConvertVirtToPhys((u32)vbo->data); - GPUCMD_AddWrite(GPUREG_ATTRIBBUFFERS_LOC, ctx->vboPos >> 3); -} - void C3D_VBODelete(C3D_VBO* vbo) { if (!vbo->data) return;