Implement proper shader program DVLE constant management

This commit is contained in:
fincs 2015-11-21 01:02:25 +01:00
parent ca410a80ac
commit dfad81b53c
3 changed files with 109 additions and 15 deletions

View File

@ -49,9 +49,12 @@ static void C3Di_AptEventHook(APT_HookType hookType, 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_RenderBuf
| C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | 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;
C3Di_DirtyUniforms(GPU_VERTEX_SHADER);
C3Di_DirtyUniforms(GPU_GEOMETRY_SHADER);
C3D_LightEnv* env = ctx->lightEnv; C3D_LightEnv* env = ctx->lightEnv;
if (env) if (env)
env->Dirty(env); env->Dirty(env);
@ -129,8 +132,8 @@ void C3Di_UpdateContext(void)
if (ctx->flags & C3DiF_Program) if (ctx->flags & C3DiF_Program)
{ {
ctx->flags &= ~C3DiF_Program; shaderProgramConfigure(ctx->program, (ctx->flags & C3DiF_VshCode) != 0, (ctx->flags & C3DiF_GshCode) != 0);
shaderProgramUse(ctx->program); ctx->flags &= ~(C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode);
} }
if (ctx->flags & C3DiF_RenderBuf) if (ctx->flags & C3DiF_RenderBuf)
@ -270,6 +273,27 @@ void C3D_BindProgram(shaderProgram_s* program)
if (!(ctx->flags & C3DiF_Active)) if (!(ctx->flags & C3DiF_Active))
return; return;
ctx->program = program; shaderProgram_s* oldProg = ctx->program;
ctx->flags |= C3DiF_Program; shaderInstance_s* newGsh = program->geometryShader;
if (oldProg != program)
{
ctx->program = program;
ctx->flags |= C3DiF_Program;
if (oldProg)
{
if (oldProg->vertexShader->dvle->dvlp != program->vertexShader->dvle->dvlp)
ctx->flags |= C3DiF_VshCode;
shaderInstance_s* oldGsh = oldProg->geometryShader;
if (newGsh && (!oldGsh || oldGsh->dvle->dvlp != newGsh->dvle->dvlp))
ctx->flags |= C3DiF_GshCode;
} else
ctx->flags |= C3DiF_VshCode | C3DiF_GshCode;
}
C3Di_LoadShaderUniforms(program->vertexShader);
if (newGsh)
C3Di_LoadShaderUniforms(newGsh);
else
C3Di_ClearShaderUniforms(GPU_GEOMETRY_SHADER);
} }

View File

@ -59,6 +59,8 @@ enum
C3DiF_Program = BIT(8), C3DiF_Program = BIT(8),
C3DiF_TexEnvBuf = BIT(9), C3DiF_TexEnvBuf = BIT(9),
C3DiF_LightEnv = BIT(10), C3DiF_LightEnv = BIT(10),
C3DiF_VshCode = BIT(11),
C3DiF_GshCode = BIT(12),
#define C3DiF_Tex(n) BIT(23+(n)) #define C3DiF_Tex(n) BIT(23+(n))
C3DiF_TexAll = 7 << 23, C3DiF_TexAll = 7 << 23,
@ -80,3 +82,7 @@ void C3Di_EffectBind(C3D_Effect* effect);
void C3Di_RenderBufBind(C3D_RenderBuf* rb); void C3Di_RenderBufBind(C3D_RenderBuf* rb);
void C3Di_LightMtlBlend(C3D_Light* light); void C3Di_LightMtlBlend(C3D_Light* light);
void C3Di_DirtyUniforms(GPU_SHADER_TYPE type);
void C3Di_LoadShaderUniforms(shaderInstance_s* si);
void C3Di_ClearShaderUniforms(GPU_SHADER_TYPE type);

View File

@ -9,12 +9,35 @@ bool C3D_FVUnifDirty[2][C3D_FVUNIF_COUNT];
bool C3D_IVUnifDirty[2][C3D_IVUNIF_COUNT]; bool C3D_IVUnifDirty[2][C3D_IVUNIF_COUNT];
bool C3D_BoolUnifsDirty[2]; bool C3D_BoolUnifsDirty[2];
static struct
{
bool dirty;
int count;
float24Uniform_s* data;
} C3Di_ShaderFVecData[2];
static bool C3Di_FVUnifEverDirty[2][C3D_FVUNIF_COUNT];
static bool C3Di_IVUnifEverDirty[2][C3D_IVUNIF_COUNT];
void C3D_UpdateUniforms(GPU_SHADER_TYPE type) void C3D_UpdateUniforms(GPU_SHADER_TYPE type)
{ {
int offset = type == GPU_GEOMETRY_SHADER ? (GPUREG_GSH_BOOLUNIFORM-GPUREG_VSH_BOOLUNIFORM) : 0; int offset = type == GPU_GEOMETRY_SHADER ? (GPUREG_GSH_BOOLUNIFORM-GPUREG_VSH_BOOLUNIFORM) : 0;
int i = 0;
// Update FVec uniforms that come from shader constants
if (C3Di_ShaderFVecData[type].dirty)
{
while (i < C3Di_ShaderFVecData[type].count)
{
float24Uniform_s* u = &C3Di_ShaderFVecData[type].data[i++];
GPUCMD_AddIncrementalWrites(GPUREG_VSH_FLOATUNIFORM_CONFIG+offset, (u32*)u, 4);
C3D_FVUnifDirty[type][u->id] = false;
}
C3Di_ShaderFVecData[type].dirty = false;
i = 0;
}
// Update FVec uniforms // Update FVec uniforms
int i = 0;
while (i < C3D_FVUNIF_COUNT) while (i < C3D_FVUNIF_COUNT)
{ {
if (!C3D_FVUnifDirty[type][i]) if (!C3D_FVUnifDirty[type][i])
@ -27,14 +50,6 @@ void C3D_UpdateUniforms(GPU_SHADER_TYPE type)
int j; int j;
for (j = i; j < C3D_FVUNIF_COUNT && C3D_FVUnifDirty[type][j]; j ++); for (j = i; j < C3D_FVUNIF_COUNT && C3D_FVUnifDirty[type][j]; j ++);
/*
consoleClear();
printf("FVEC Uniform %02X--%02X\n", i, j-1);
int pp;
for (pp = i; pp < j; pp ++)
printf("%02X: (%f, %f, %f, %f)\n", pp, C3D_FVUnif[pp].x, C3D_FVUnif[pp].y, C3D_FVUnif[pp].z, C3D_FVUnif[pp].w);
*/
// Upload the uniforms // Upload the uniforms
GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+offset, 0x80000000|i); GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+offset, 0x80000000|i);
GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+offset, (u32*)&C3D_FVUnif[i], (j-i)*4); GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+offset, (u32*)&C3D_FVUnif[i], (j-i)*4);
@ -42,7 +57,10 @@ void C3D_UpdateUniforms(GPU_SHADER_TYPE type)
// Clear the dirty flag // Clear the dirty flag
int k; int k;
for (k = i; k < j; k ++) for (k = i; k < j; k ++)
{
C3D_FVUnifDirty[type][k] = false; C3D_FVUnifDirty[type][k] = false;
C3Di_FVUnifEverDirty[type][k] = true;
}
// Advance // Advance
i += j; i += j;
@ -55,12 +73,58 @@ void C3D_UpdateUniforms(GPU_SHADER_TYPE type)
GPUCMD_AddWrite(GPUREG_VSH_INTUNIFORM_I0+offset+i, C3D_IVUnif[type][i]); GPUCMD_AddWrite(GPUREG_VSH_INTUNIFORM_I0+offset+i, C3D_IVUnif[type][i]);
C3D_IVUnifDirty[type][i] = false; C3D_IVUnifDirty[type][i] = false;
C3Di_IVUnifEverDirty[type][i] = false;
} }
// Update bool uniforms // Update bool uniforms
if (C3D_BoolUnifsDirty[type]) if (C3D_BoolUnifsDirty[type])
{ {
GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM+offset, 0x7FFF0000 | (u32)C3D_BoolUnifs[type]); GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM+offset, 0x7FFF0000 | (u32)~C3D_BoolUnifs[type]);
C3D_BoolUnifsDirty[type] = false; C3D_BoolUnifsDirty[type] = false;
} }
} }
void C3Di_DirtyUniforms(GPU_SHADER_TYPE type)
{
int i;
C3D_BoolUnifsDirty[type] = true;
if (C3Di_ShaderFVecData[type].count)
C3Di_ShaderFVecData[type].dirty = true;
for (i = 0; i < C3D_FVUNIF_COUNT; i ++)
C3D_FVUnifDirty[type][i] = C3D_FVUnifDirty[type][i] || C3Di_FVUnifEverDirty[type][i];
for (i = 0; i < C3D_IVUNIF_COUNT; i ++)
C3D_IVUnifDirty[type][i] = C3D_IVUnifDirty[type][i] || C3Di_IVUnifEverDirty[type][i];
}
void C3Di_LoadShaderUniforms(shaderInstance_s* si)
{
GPU_SHADER_TYPE type = si->dvle->type;
int i;
if (si->boolUniformMask)
{
C3D_BoolUnifs[type] &= ~si->boolUniformMask;
C3D_BoolUnifs[type] |= si->boolUniforms;
C3D_BoolUnifsDirty[type] = true;
}
if (si->intUniformMask)
{
for (i = 0; i < 4; i ++)
{
if (si->intUniformMask & BIT(i))
{
C3D_IVUnif[type][i] = si->intUniforms[i];
C3D_IVUnifDirty[type][i] = true;
}
}
}
C3Di_ShaderFVecData[type].dirty = true;
C3Di_ShaderFVecData[type].count = si->numFloat24Uniforms;
C3Di_ShaderFVecData[type].data = si->float24Uniforms;
}
void C3Di_ClearShaderUniforms(GPU_SHADER_TYPE type)
{
C3Di_ShaderFVecData[type].dirty = false;
C3Di_ShaderFVecData[type].count = 0;
C3Di_ShaderFVecData[type].data = NULL;
}