Introduce framebuffer (light renderbuffer) infrastructure

This commit is contained in:
fincs 2017-02-14 18:24:57 +01:00
parent 15de0e300e
commit 5c1d037fa2
7 changed files with 143 additions and 48 deletions

56
include/c3d/framebuffer.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
#include "texture.h"
typedef struct
{
void* colorBuf;
void* depthBuf;
u16 width;
u16 height;
GPU_COLORBUF colorFmt;
GPU_DEPTHBUF depthFmt;
bool block32;
u8 colorMask : 4;
u8 depthMask : 4;
} C3D_FrameBuf;
C3D_FrameBuf* C3D_GetFrameBuf(void);
void C3D_SetFrameBuf(C3D_FrameBuf* fb);
void C3D_FrameBufTex(C3D_FrameBuf* fb, C3D_Tex* tex, GPU_TEXFACE face, int level);
static inline void C3D_FrameBufAttrib(C3D_FrameBuf* fb, u16 width, u16 height, bool block32)
{
fb->width = width;
fb->height = height;
fb->block32 = block32;
}
static inline void C3D_FrameBufColor(C3D_FrameBuf* fb, void* buf, GPU_COLORBUF fmt)
{
if (buf)
{
fb->colorBuf = buf;
fb->colorFmt = fmt;
fb->colorMask = 0xF;
} else
{
fb->colorBuf = NULL;
fb->colorFmt = GPU_RB_RGBA8;
fb->colorMask = 0;
}
}
static inline void C3D_FrameBufDepth(C3D_FrameBuf* fb, void* buf, GPU_DEPTHBUF fmt)
{
if (buf)
{
fb->depthBuf = buf;
fb->depthFmt = fmt;
fb->depthMask = fmt == GPU_RB_DEPTH24_STENCIL8 ? 0x3 : 0x2;
} else
{
fb->depthBuf = NULL;
fb->depthFmt = GPU_RB_DEPTH24;
fb->depthMask = 0;
}
}

View File

@ -24,6 +24,7 @@ extern "C" {
#include "c3d/light.h" #include "c3d/light.h"
#include "c3d/lightlut.h" #include "c3d/lightlut.h"
#include "c3d/framebuffer.h"
#include "c3d/renderbuffer.h" #include "c3d/renderbuffer.h"
#include "c3d/renderqueue.h" #include "c3d/renderqueue.h"

View File

@ -21,7 +21,7 @@ static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
} }
case APTHOOK_ONRESTORE: case APTHOOK_ONRESTORE:
{ {
ctx->flags |= C3DiF_AttrInfo | C3DiF_BufInfo | C3DiF_Effect | C3DiF_RenderBuf ctx->flags |= C3DiF_AttrInfo | C3DiF_BufInfo | C3DiF_Effect | C3DiF_FrameBuf
| C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode | C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode
| C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_LightEnv; | C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_LightEnv;
@ -55,7 +55,7 @@ bool C3D_Init(size_t cmdBufSize)
GPUCMD_SetBuffer(ctx->cmdBuf, ctx->cmdBufSize, 0); GPUCMD_SetBuffer(ctx->cmdBuf, ctx->cmdBufSize, 0);
ctx->flags = C3DiF_Active | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_Effect | C3DiF_TexAll; ctx->flags = C3DiF_Active | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_Effect | C3DiF_TexStatus | C3DiF_TexAll;
ctx->renderQueueExit = NULL; ctx->renderQueueExit = NULL;
// TODO: replace with direct struct access // TODO: replace with direct struct access
@ -120,16 +120,16 @@ void C3Di_UpdateContext(void)
ctx->flags &= ~(C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode); ctx->flags &= ~(C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode);
} }
if (ctx->flags & C3DiF_RenderBuf) if (ctx->flags & C3DiF_FrameBuf)
{ {
ctx->flags &= ~C3DiF_RenderBuf; ctx->flags &= ~C3DiF_FrameBuf;
if (ctx->flags & C3DiF_DrawUsed) if (ctx->flags & C3DiF_DrawUsed)
{ {
ctx->flags &= ~C3DiF_DrawUsed; ctx->flags &= ~C3DiF_DrawUsed;
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 1); GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 1);
GPUCMD_AddWrite(GPUREG_EARLYDEPTH_CLEAR, 1); GPUCMD_AddWrite(GPUREG_EARLYDEPTH_CLEAR, 1);
} }
C3Di_RenderBufBind(ctx->rb); C3Di_FrameBufBind(&ctx->fb);
} }
if (ctx->flags & C3DiF_Viewport) if (ctx->flags & C3DiF_Viewport)

55
source/framebuffer.c Normal file
View File

@ -0,0 +1,55 @@
#include "internal.h"
C3D_FrameBuf* C3D_GetFrameBuf(void)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return NULL;
ctx->flags |= C3DiF_FrameBuf;
return &ctx->fb;
}
void C3D_SetFrameBuf(C3D_FrameBuf* fb)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
if (fb != &ctx->fb)
memcpy(&ctx->fb, fb, sizeof(*fb));
ctx->flags |= C3DiF_FrameBuf;
}
void C3D_FrameBufTex(C3D_FrameBuf* fb, C3D_Tex* tex, GPU_TEXFACE face, int level)
{
C3D_FrameBufAttrib(fb, tex->width, tex->height, false);
C3D_FrameBufColor(fb, C3D_TexGetImagePtr(tex,
C3Di_TexIs2D(tex) ? tex->data : tex->cube->data[face], level, NULL),
(GPU_COLORBUF)tex->fmt);
}
void C3Di_FrameBufBind(C3D_FrameBuf* fb)
{
static const u8 colorFmtSizes[] = {2,1,0,0,0};
u32 param[4] = { 0, 0, 0, 0 };
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 1);
param[0] = osConvertVirtToPhys(fb->depthBuf) >> 3;
param[1] = osConvertVirtToPhys(fb->colorBuf) >> 3;
param[2] = 0x01000000 | (((u32)(fb->height-1) & 0xFFF) << 12) | (fb->width & 0xFFF);
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 3);
GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, param[2]);
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, fb->depthFmt);
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, colorFmtSizes[fb->colorFmt] | ((u32)fb->colorFmt << 16));
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, fb->block32 ? 1 : 0);
// Enable or disable color/depth buffers
param[0] = param[1] = fb->colorBuf ? fb->colorMask : 0;
param[2] = param[3] = fb->depthBuf ? fb->depthMask : 0;
GPUCMD_AddIncrementalWrites(GPUREG_COLORBUFFER_READ, param, 4);
}

View File

@ -2,7 +2,7 @@
#include <c3d/attribs.h> #include <c3d/attribs.h>
#include <c3d/buffers.h> #include <c3d/buffers.h>
#include <c3d/light.h> #include <c3d/light.h>
#include <c3d/renderbuffer.h> #include <c3d/framebuffer.h>
#include <c3d/texenv.h> #include <c3d/texenv.h>
#define C3D_UNUSED __attribute__((unused)) #define C3D_UNUSED __attribute__((unused))
@ -43,7 +43,7 @@ typedef struct
u32 texEnvBuf, texEnvBufClr; u32 texEnvBuf, texEnvBufClr;
C3D_RenderBuf* rb; C3D_FrameBuf fb;
u32 viewport[5]; u32 viewport[5];
u32 scissor[3]; u32 scissor[3];
@ -62,7 +62,7 @@ enum
C3DiF_AttrInfo = BIT(2), C3DiF_AttrInfo = BIT(2),
C3DiF_BufInfo = BIT(3), C3DiF_BufInfo = BIT(3),
C3DiF_Effect = BIT(4), C3DiF_Effect = BIT(4),
C3DiF_RenderBuf = BIT(5), C3DiF_FrameBuf = BIT(5),
C3DiF_Viewport = BIT(6), C3DiF_Viewport = BIT(6),
C3DiF_Scissor = BIT(7), C3DiF_Scissor = BIT(7),
C3DiF_Program = BIT(8), C3DiF_Program = BIT(8),
@ -84,13 +84,23 @@ static inline C3D_Context* C3Di_GetContext(void)
return &__C3D_Context; return &__C3D_Context;
} }
static inline bool typeIsCube(GPU_TEXTURE_MODE_PARAM type)
{
return type == GPU_TEX_CUBE_MAP || type == GPU_TEX_SHADOW_CUBE;
}
static inline bool C3Di_TexIs2D(C3D_Tex* tex)
{
return !typeIsCube(C3D_TexGetType(tex));
}
void C3Di_UpdateContext(void); void C3Di_UpdateContext(void);
void C3Di_AttrInfoBind(C3D_AttrInfo* info); void C3Di_AttrInfoBind(C3D_AttrInfo* info);
void C3Di_BufInfoBind(C3D_BufInfo* info); void C3Di_BufInfoBind(C3D_BufInfo* info);
void C3Di_FrameBufBind(C3D_FrameBuf* fb);
void C3Di_TexEnvBind(int id, C3D_TexEnv* env); void C3Di_TexEnvBind(int id, C3D_TexEnv* env);
void C3Di_SetTex(GPU_TEXUNIT unit, C3D_Tex* tex); void C3Di_SetTex(GPU_TEXUNIT unit, C3D_Tex* tex);
void C3Di_EffectBind(C3D_Effect* effect); void C3Di_EffectBind(C3D_Effect* effect);
void C3Di_RenderBufBind(C3D_RenderBuf* rb);
void C3Di_LightMtlBlend(C3D_Light* light); void C3Di_LightMtlBlend(C3D_Light* light);

View File

@ -1,5 +1,6 @@
#include "internal.h" #include "internal.h"
#include <c3d/base.h> #include <c3d/base.h>
#include <c3d/renderbuffer.h>
static const u8 colorFmtSizes[] = {2,1,0,0,0}; static const u8 colorFmtSizes[] = {2,1,0,0,0};
static const u8 depthFmtSizes[] = {0,0,1,2}; static const u8 depthFmtSizes[] = {0,0,1,2};
@ -16,11 +17,6 @@ static inline u16 getDepthBufFillFlag(int fmt)
return BIT(0) | ((u32)depthFmtSizes[fmt] << 8); return BIT(0) | ((u32)depthFmtSizes[fmt] << 8);
} }
static inline u32 getColorBufFormatReg(int fmt)
{
return (fmt << 16) | colorFmtSizes[fmt];
}
static inline GPU_TEXCOLOR colorFmtFromDepthFmt(int fmt) static inline GPU_TEXCOLOR colorFmtFromDepthFmt(int fmt)
{ {
switch (fmt) switch (fmt)
@ -76,33 +72,20 @@ void C3D_RenderBufTransferAsync(C3D_RenderBuf* rb, u32* frameBuf, u32 flags)
void C3D_RenderBufBind(C3D_RenderBuf* rb) void C3D_RenderBufBind(C3D_RenderBuf* rb)
{ {
C3D_Context* ctx = C3Di_GetContext(); C3D_Context* ctx = C3Di_GetContext();
ctx->flags |= C3DiF_RenderBuf; C3D_FrameBuf* fb = &ctx->fb;
ctx->rb = rb; ctx->flags |= C3DiF_FrameBuf;
fb->colorBuf = rb->colorBuf.data;
fb->depthBuf = rb->depthBuf.data;
fb->width = rb->colorBuf.width;
fb->height = rb->colorBuf.height;
fb->colorFmt = (GPU_COLORBUF)rb->colorBuf.fmt;
fb->depthFmt = rb->depthFmt >= 0 ? (GPU_DEPTHBUF)rb->depthFmt : GPU_RB_DEPTH16;
fb->block32 = false;
fb->colorMask = 0xF;
fb->depthMask = 0x2;
C3D_SetViewport(0, 0, rb->colorBuf.width, rb->colorBuf.height); C3D_SetViewport(0, 0, rb->colorBuf.width, rb->colorBuf.height);
} }
void C3Di_RenderBufBind(C3D_RenderBuf* rb)
{
u32 param[4] = { 0, 0, 0, 0 };
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 1);
param[0] = osConvertVirtToPhys(rb->depthBuf.data) >> 3;
param[1] = osConvertVirtToPhys(rb->colorBuf.data) >> 3;
param[2] = 0x01000000 | (((u32)(rb->colorBuf.height-1) & 0xFFF) << 12) | (rb->colorBuf.width & 0xFFF);
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 3);
GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, param[2]);
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, rb->depthFmt >= 0 ? rb->depthFmt : GPU_RB_DEPTH16);
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, getColorBufFormatReg(rb->colorBuf.fmt));
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0x00000000); //?
// Enable or disable color/depth buffers
param[0] = param[1] = rb->colorBuf.data ? 0xF : 0;
param[2] = param[3] = rb->depthBuf.data ? 0x2 : 0;
GPUCMD_AddIncrementalWrites(GPUREG_COLORBUFFER_READ, param, 4);
}
void C3D_RenderBufDelete(C3D_RenderBuf* rb) void C3D_RenderBufDelete(C3D_RenderBuf* rb)
{ {
C3D_TexDelete(&rb->colorBuf); C3D_TexDelete(&rb->colorBuf);

View File

@ -30,16 +30,6 @@ static inline size_t fmtSize(GPU_TEXCOLOR fmt)
} }
} }
static inline bool typeIsCube(GPU_TEXTURE_MODE_PARAM type)
{
return type == GPU_TEX_CUBE_MAP || type == GPU_TEX_SHADOW_CUBE;
}
static inline bool C3Di_TexIs2D(C3D_Tex* tex)
{
return !typeIsCube(C3D_TexGetType(tex));
}
static inline bool addrIsVRAM(const void* addr) static inline bool addrIsVRAM(const void* addr)
{ {
u32 vaddr = (u32)addr; u32 vaddr = (u32)addr;