citro3d/source/uniforms.c

135 lines
3.3 KiB
C
Raw Permalink Normal View History

2017-02-09 04:30:25 +01:00
#include "internal.h"
2014-12-20 21:34:19 +01:00
#include <c3d/uniforms.h>
2015-03-05 23:05:14 +01:00
C3D_FVec C3D_FVUnif[2][C3D_FVUNIF_COUNT];
C3D_IVec C3D_IVUnif[2][C3D_IVUNIF_COUNT];
u16 C3D_BoolUnifs[2];
2014-12-20 21:34:19 +01:00
2015-03-05 23:05:14 +01:00
bool C3D_FVUnifDirty[2][C3D_FVUNIF_COUNT];
bool C3D_IVUnifDirty[2][C3D_IVUNIF_COUNT];
bool C3D_BoolUnifsDirty[2];
2014-12-20 21:34:19 +01:00
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];
2015-03-05 23:05:14 +01:00
void C3D_UpdateUniforms(GPU_SHADER_TYPE type)
2014-12-20 21:34:19 +01:00
{
2015-03-05 23:05:14 +01:00
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;
}
2015-03-05 23:05:14 +01:00
2014-12-20 21:34:19 +01:00
// Update FVec uniforms
while (i < C3D_FVUNIF_COUNT)
{
2015-03-05 23:05:14 +01:00
if (!C3D_FVUnifDirty[type][i])
2014-12-20 21:34:19 +01:00
{
i ++;
continue;
}
// Find the number of consecutive dirty uniforms
int j;
2015-03-05 23:05:14 +01:00
for (j = i; j < C3D_FVUNIF_COUNT && C3D_FVUnifDirty[type][j]; j ++);
2014-12-20 21:34:19 +01:00
// Upload the uniforms
GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+offset, 0x80000000|i);
GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+offset, (u32*)&C3D_FVUnif[type][i], (j-i)*4);
2014-12-20 21:34:19 +01:00
// Clear the dirty flag
int k;
for (k = i; k < j; k ++)
{
2015-03-05 23:05:14 +01:00
C3D_FVUnifDirty[type][k] = false;
C3Di_FVUnifEverDirty[type][k] = true;
}
2014-12-20 21:34:19 +01:00
// Advance
2017-03-04 18:16:20 +01:00
i = j;
2014-12-20 21:34:19 +01:00
}
// Update IVec uniforms
for (i = 0; i < C3D_IVUNIF_COUNT; i ++)
{
2015-03-05 23:05:14 +01:00
if (!C3D_IVUnifDirty[type][i]) continue;
2014-12-20 21:34:19 +01:00
2015-03-05 23:05:14 +01:00
GPUCMD_AddWrite(GPUREG_VSH_INTUNIFORM_I0+offset+i, C3D_IVUnif[type][i]);
C3D_IVUnifDirty[type][i] = false;
C3Di_IVUnifEverDirty[type][i] = false;
2014-12-20 21:34:19 +01:00
}
// Update bool uniforms
2015-03-05 23:05:14 +01:00
if (C3D_BoolUnifsDirty[type])
2014-12-20 21:34:19 +01:00
{
2016-01-24 01:45:39 +01:00
GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM+offset, 0x7FFF0000 | C3D_BoolUnifs[type]);
2015-03-05 23:05:14 +01:00
C3D_BoolUnifsDirty[type] = false;
2014-12-20 21:34:19 +01:00
}
}
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;
if (si->boolUniformMask)
{
C3D_BoolUnifs[type] &= ~si->boolUniformMask;
C3D_BoolUnifs[type] |= si->boolUniforms;
}
2016-07-21 12:06:09 +02:00
if (type == GPU_GEOMETRY_SHADER)
C3D_BoolUnifs[type] &= ~BIT(15);
C3D_BoolUnifsDirty[type] = true;
if (si->intUniformMask)
{
int i;
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;
}