Decouple attribute and buffer management

This commit is contained in:
fincs 2015-09-07 14:47:20 +02:00
parent 3e42b1a9a4
commit f640360108
13 changed files with 146 additions and 89 deletions

View File

@ -73,7 +73,7 @@ static void drawScene(float trX, float trY)
MtxStack_Update(&projMtx); MtxStack_Update(&projMtx);
MtxStack_Update(&mdlvMtx); MtxStack_Update(&mdlvMtx);
C3D_DrawArray(&myVbo, GPU_TRIANGLES); C3D_DrawArrays(GPU_TRIANGLES, 0, myVbo.vertexCount);
C3D_Flush(); C3D_Flush();
} }
@ -96,7 +96,7 @@ static void drawSceneBottom(float trX, float trY)
MtxStack_Update(&projMtx); MtxStack_Update(&projMtx);
MtxStack_Update(&mdlvMtx); MtxStack_Update(&mdlvMtx);
C3D_DrawArray(&myVbo, GPU_TRIANGLES); C3D_DrawArrays(GPU_TRIANGLES, 0, myVbo.vertexCount);
C3D_Flush(); C3D_Flush();
} }
@ -139,16 +139,20 @@ int main()
// Configure attributes // Configure attributes
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo); AttrInfo_Init(attrInfo);
AttrInfo_AddParam(attrInfo, GPU_FLOAT, 3); // position AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // position
AttrInfo_AddParam(attrInfo, GPU_FLOAT, 2); // texcoord AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // texcoord
AttrInfo_AddParam(attrInfo, GPU_FLOAT, 3); // vertex color AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 3); // vertex color
AttrInfo_AddBuffer(attrInfo, 0, sizeof(vertex_t), 3, 0x210);
// Configure VBO // Configure VBO
C3D_VBOInit(&myVbo, sizeof(vertices)); C3D_VBOInit(&myVbo, sizeof(vertices));
C3D_VBOAddData(&myVbo, vertices, sizeof(vertices), sizeof(vertices)/sizeof(vertex_t)); 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(&rbTop);
C3D_RenderBufClear(&rbBot); C3D_RenderBufClear(&rbBot);

View File

@ -3,29 +3,14 @@
typedef struct typedef struct
{ {
u32 offset;
u32 flags[2]; 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; u64 permutation;
int attrCount; int attrCount;
int bufCount;
} C3D_AttrInfo; } C3D_AttrInfo;
void AttrInfo_Init(C3D_AttrInfo* info); void AttrInfo_Init(C3D_AttrInfo* info);
bool AttrInfo_AddParam(C3D_AttrInfo* info, GPU_FORMATS format, int count); int AttrInfo_AddLoader(C3D_AttrInfo* info, int regId, GPU_FORMATS format, int count);
bool AttrInfo_AddBuffer(C3D_AttrInfo* info, ptrdiff_t offset, ptrdiff_t stride, int attribCount, u64 permutation); int AttrInfo_AddFixed(C3D_AttrInfo* info, int regId);
C3D_AttrInfo* C3D_GetAttrInfo(void); C3D_AttrInfo* C3D_GetAttrInfo(void);
void C3D_SetAttrInfo(C3D_AttrInfo* info); void C3D_SetAttrInfo(C3D_AttrInfo* info);

View File

@ -12,8 +12,8 @@ void C3D_BindProgram(shaderProgram_s* program);
void C3D_SetViewport(u32 x, u32 y, u32 w, u32 h); 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_SetScissor(GPU_SCISSORMODE mode, u32 x, u32 y, u32 w, u32 h);
void C3D_DrawArray(C3D_VBO* vbo, GPU_Primitive_t primitive); void C3D_DrawArrays(GPU_Primitive_t primitive, int first, int size);
void C3D_DrawElements(C3D_IBO* ibo, GPU_Primitive_t primitive); void C3D_DrawElements(GPU_Primitive_t primitive, int count, int type, const void* indices);
static inline void C3D_FlushAwait(void) static inline void C3D_FlushAwait(void)
{ {

View File

@ -1,6 +1,25 @@
#pragma once #pragma once
#include "types.h" #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 typedef struct
{ {
void* data; void* data;
@ -12,7 +31,6 @@ typedef struct
bool C3D_VBOInit(C3D_VBO* vbo, size_t capacity); bool C3D_VBOInit(C3D_VBO* vbo, size_t capacity);
bool C3D_VBOAddData(C3D_VBO* vbo, const void* data, size_t size, int vertexCount); bool C3D_VBOAddData(C3D_VBO* vbo, const void* data, size_t size, int vertexCount);
void C3D_VBOFlush(C3D_VBO* vbo); void C3D_VBOFlush(C3D_VBO* vbo);
void C3D_VBOBind(C3D_VBO* vbo);
void C3D_VBODelete(C3D_VBO* vbo); void C3D_VBODelete(C3D_VBO* vbo);
typedef struct typedef struct

View File

@ -5,32 +5,33 @@
void AttrInfo_Init(C3D_AttrInfo* info) void AttrInfo_Init(C3D_AttrInfo* info)
{ {
memset(info, 0, sizeof(*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++; int id = info->attrCount++;
if (regId < 0) regId = id;
if (id < 8) if (id < 8)
info->cfg.flags[0] |= GPU_ATTRIBFMT(id, count, format); info->flags[0] |= GPU_ATTRIBFMT(id, count, format);
else else
info->cfg.flags[1] |= GPU_ATTRIBFMT(id-8, count, format); info->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->flags[1] = (info->flags[1] &~ (0xF0000000 | BIT(id+16))) | (id << 28);
info->permutation |= id << (id*4); info->permutation |= regId << (id*4);
return true; 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; if (info->attrCount == 12) return -1;
int id = info->bufCount++; int id = info->attrCount++;
C3D_AttrBufCfg* buf = &info->cfg.buffers[id]; if (regId < 0) regId = id;
buf->offset = offset;
buf->flags[0] = permutation & 0xFFFFFFFF; info->flags[1] = (info->flags[1] &~ 0xF0000000) | (id << 28);
buf->flags[1] = (permutation >> 32) | (stride << 16) | (attribCount << 28); info->permutation |= regId << (id*4);
return true; return id;
} }
C3D_AttrInfo* C3D_GetAttrInfo(void) C3D_AttrInfo* C3D_GetAttrInfo(void)
@ -40,7 +41,7 @@ C3D_AttrInfo* C3D_GetAttrInfo(void)
if (!(ctx->flags & C3DiF_Active)) if (!(ctx->flags & C3DiF_Active))
return NULL; return NULL;
ctx->flags |= C3DiF_AttrBuf; ctx->flags |= C3DiF_AttrInfo;
return &ctx->attrInfo; return &ctx->attrInfo;
} }
@ -51,13 +52,14 @@ void C3D_SetAttrInfo(C3D_AttrInfo* info)
if (!(ctx->flags & C3DiF_Active)) if (!(ctx->flags & C3DiF_Active))
return; return;
if (info != &ctx->attrInfo)
memcpy(&ctx->attrInfo, info, sizeof(*info)); memcpy(&ctx->attrInfo, info, sizeof(*info));
ctx->flags |= C3DiF_AttrBuf; ctx->flags |= C3DiF_AttrInfo;
} }
void C3Di_AttrInfoBind(C3D_AttrInfo* info) 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_AddMaskedWrite(GPUREG_VSH_INPUTBUFFER_CONFIG, 0xB, 0xA0000000 | (info->attrCount - 1));
GPUCMD_AddWrite(GPUREG_0242, info->attrCount - 1); GPUCMD_AddWrite(GPUREG_0242, info->attrCount - 1);
GPUCMD_AddIncrementalWrites(GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW, (u32*)&info->permutation, 2); GPUCMD_AddIncrementalWrites(GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW, (u32*)&info->permutation, 2);

View File

@ -47,7 +47,7 @@ static void C3Di_AptEventHook(int hookType, void* param)
} }
case APTHOOK_ONRESTORE: 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_Viewport | C3DiF_Scissor | C3DiF_Program
| C3DiF_TexAll | C3DiF_TexEnvAll; | C3DiF_TexAll | C3DiF_TexEnvAll;
break; break;
@ -150,12 +150,18 @@ void C3Di_UpdateContext(void)
GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, ctx->scissor, 3); 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); C3Di_AttrInfoBind(&ctx->attrInfo);
} }
if (ctx->flags & C3DiF_BufInfo)
{
ctx->flags &= ~C3DiF_BufInfo;
C3Di_BufInfoBind(&ctx->bufInfo);
}
if (ctx->flags & C3DiF_Effect) if (ctx->flags & C3DiF_Effect)
{ {
ctx->flags &= ~C3DiF_Effect; ctx->flags &= ~C3DiF_Effect;

55
source/buffers.c Normal file
View File

@ -0,0 +1,55 @@
#include <c3d/buffers.h>
#include <string.h>
#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));
}

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <c3d/base.h> #include <c3d/base.h>
#include <c3d/uniforms.h> #include <c3d/uniforms.h>
#include <c3d/buffers.h>
#include <c3d/attribs.h> #include <c3d/attribs.h>
#include <c3d/buffers.h>
#include <c3d/texenv.h> #include <c3d/texenv.h>
#include <c3d/effect.h> #include <c3d/effect.h>
#include <c3d/texture.h> #include <c3d/texture.h>
@ -29,8 +29,8 @@ typedef struct
u32 flags; u32 flags;
shaderProgram_s* program; shaderProgram_s* program;
u32 vboPos;
C3D_AttrInfo attrInfo; C3D_AttrInfo attrInfo;
C3D_BufInfo bufInfo;
C3D_Effect effect; C3D_Effect effect;
C3D_Tex* tex[3]; C3D_Tex* tex[3];
@ -46,12 +46,13 @@ enum
{ {
C3DiF_Active = BIT(0), C3DiF_Active = BIT(0),
C3DiF_NeedFinishDrawing = BIT(1), C3DiF_NeedFinishDrawing = BIT(1),
C3DiF_AttrBuf = BIT(2), C3DiF_AttrInfo = BIT(2),
C3DiF_Effect = BIT(3), C3DiF_BufInfo = BIT(3),
C3DiF_RenderBuf = BIT(4), C3DiF_Effect = BIT(4),
C3DiF_Viewport = BIT(5), C3DiF_RenderBuf = BIT(5),
C3DiF_Scissor = BIT(6), C3DiF_Viewport = BIT(6),
C3DiF_Program = BIT(7), C3DiF_Scissor = BIT(7),
C3DiF_Program = BIT(8),
#define C3DiF_Tex(n) BIT(23+(n)) #define C3DiF_Tex(n) BIT(23+(n))
C3DiF_TexAll = 7 << 23, C3DiF_TexAll = 7 << 23,
@ -66,8 +67,8 @@ static inline C3D_Context* C3Di_GetContext(void)
} }
void C3Di_UpdateContext(void); void C3Di_UpdateContext(void);
void C3Di_IBOBind(C3D_IBO* ibo);
void C3Di_AttrInfoBind(C3D_AttrInfo* info); void C3Di_AttrInfoBind(C3D_AttrInfo* info);
void C3Di_BufInfoBind(C3D_BufInfo* info);
void C3Di_TexEnvBind(int id, C3D_TexEnv* env); void C3Di_TexEnvBind(int id, C3D_TexEnv* env);
void C3Di_EffectBind(C3D_Effect* effect); void C3Di_EffectBind(C3D_Effect* effect);
void C3Di_RenderBufBind(C3D_RenderBuf* rb); void C3Di_RenderBufBind(C3D_RenderBuf* rb);

View File

@ -1,8 +1,7 @@
#include "context.h" #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(); C3Di_UpdateContext();
// Set primitive type // 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 // The index buffer is not used, but 0x000F0227 is still required
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000); GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000);
// Number of vertices // 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 // Unknown commands
GPUCMD_AddMaskedWrite(GPUREG_0253, 1, 0x00000001); GPUCMD_AddMaskedWrite(GPUREG_0253, 1, 0x00000001);

View File

@ -1,16 +1,21 @@
#include "context.h" #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(); C3Di_UpdateContext();
// Set primitive type // Set primitive type
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 2, primitive); GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 2, primitive);
GPUCMD_AddMaskedWrite(GPUREG_025F, 2, 0x00000001); GPUCMD_AddMaskedWrite(GPUREG_025F, 2, 0x00000001);
// Bind the IBO // Configure the index buffer
C3Di_IBOBind(ibo); GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, (pa - base) | (type << 31));
// Number of vertices // Number of vertices
GPUCMD_AddWrite(GPUREG_NUMVERTICES, ibo->indexCount); GPUCMD_AddWrite(GPUREG_NUMVERTICES, count);
// Unknown commands // Unknown commands
GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 2, 0x00000100); GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 2, 0x00000100);

View File

@ -30,15 +30,6 @@ void C3D_IBOFlush(C3D_IBO* ibo)
GSPGPU_FlushDataCache(ibo->data, ibo->indexCount*stride); 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) void C3D_IBODelete(C3D_IBO* ibo)
{ {
if (!ibo->data) return; if (!ibo->data) return;

View File

@ -41,7 +41,7 @@ void C3D_RenderBufClearAsync(C3D_RenderBuf* rb)
{ {
u32 colorBufSize = calcColorBufSize(rb->width, rb->height, rb->colorFmt); u32 colorBufSize = calcColorBufSize(rb->width, rb->height, rb->colorFmt);
u32 depthBufSize = calcDepthBufSize(rb->width, rb->height, rb->depthFmt); 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->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)); (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) void C3D_RenderBufTransferAsync(C3D_RenderBuf* rb, u32* frameBuf, u32 flags)
{ {
u32 dim = GX_BUFFER_DIM((u32)rb->width, (u32)rb->height); 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) void C3D_RenderBufBind(C3D_RenderBuf* rb)

View File

@ -30,17 +30,6 @@ void C3D_VBOFlush(C3D_VBO* vbo)
GSPGPU_FlushDataCache(vbo->data, vbo->size); 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) void C3D_VBODelete(C3D_VBO* vbo)
{ {
if (!vbo->data) return; if (!vbo->data) return;