#include "internal.h" #include C3D_FVec C3D_FVUnif[2][C3D_FVUNIF_COUNT]; C3D_IVec C3D_IVUnif[2][C3D_IVUNIF_COUNT]; u16 C3D_BoolUnifs[2]; bool C3D_FVUnifDirty[2][C3D_FVUNIF_COUNT]; bool C3D_IVUnifDirty[2][C3D_IVUNIF_COUNT]; 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) { 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 while (i < C3D_FVUNIF_COUNT) { if (!C3D_FVUnifDirty[type][i]) { i ++; continue; } // Find the number of consecutive dirty uniforms int j; for (j = i; j < C3D_FVUNIF_COUNT && C3D_FVUnifDirty[type][j]; j ++); // 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); // Clear the dirty flag int k; for (k = i; k < j; k ++) { C3D_FVUnifDirty[type][k] = false; C3Di_FVUnifEverDirty[type][k] = true; } // Advance i = j; } // Update IVec uniforms for (i = 0; i < C3D_IVUNIF_COUNT; i ++) { if (!C3D_IVUnifDirty[type][i]) continue; GPUCMD_AddWrite(GPUREG_VSH_INTUNIFORM_I0+offset+i, C3D_IVUnif[type][i]); C3D_IVUnifDirty[type][i] = false; C3Di_IVUnifEverDirty[type][i] = false; } // Update bool uniforms if (C3D_BoolUnifsDirty[type]) { GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM+offset, 0x7FFF0000 | C3D_BoolUnifs[type]); 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; if (si->boolUniformMask) { C3D_BoolUnifs[type] &= ~si->boolUniformMask; C3D_BoolUnifs[type] |= si->boolUniforms; } 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; }