{\r
DVLE_s* dvle; ///< Shader DVLE.\r
u16 boolUniforms; ///< Boolean uniforms.\r
+ u16 boolUniformMask; ///< Used boolean uniform mask.\r
u32 intUniforms[4]; ///< Integer uniforms.\r
float24Uniform_s* float24Uniforms; ///< 24-bit float uniforms.\r
+ u8 intUniformMask; ///< Used integer uniform mask.\r
u8 numFloat24Uniforms; ///< Float uniform count.\r
}shaderInstance_s;\r
\r
{\r
shaderInstance_s* vertexShader; ///< Vertex shader.\r
shaderInstance_s* geometryShader; ///< Geometry shader.\r
- u8 geometryShaderInputStride; ///< Geometry shader input stride.\r
+ u32 geoShaderInputPermutation[2]; ///< Geometry shader input permutation.\r
+ u8 geoShaderInputStride; ///< Geometry shader input stride.\r
}shaderProgram_s;\r
\r
/**\r
* @param si Shader instance to use.\r
* @param name Name of the uniform.\r
*/\r
-Result shaderInstanceGetUniformLocation(shaderInstance_s* si, const char* name);\r
+s8 shaderInstanceGetUniformLocation(shaderInstance_s* si, const char* name);\r
\r
/**\r
* @brief Initializes a shader program.\r
Result shaderProgramSetGsh(shaderProgram_s* sp, DVLE_s* dvle, u8 stride);\r
\r
/**\r
- * @brief Sets the active shader program.\r
+ * @brief Configures the permutation of the input attributes of the geometry shader of a shader program.\r
+ * @param sp Shader program to use.\r
+ * @param permutation Attribute permutation to use.\r
+ */\r
+Result shaderProgramSetGshInputPermutation(shaderProgram_s* sp, u64 permutation);\r
+\r
+/**\r
+ * @brief Configures the shader units to use the specified shader program.\r
+ * @param sp Shader program to use.\r
+ * @param sendVshCode When true, the vertex shader's code and operand descriptors are uploaded.\r
+ * @param sendGshCode When true, the geometry shader's code and operand descriptors are uploaded.\r
+ */\r
+Result shaderProgramConfigure(shaderProgram_s* sp, bool sendVshCode, bool sendGshCode);\r
+\r
+/**\r
+ * @brief Same as shaderProgramConfigure, but always loading code/operand descriptors and uploading DVLE constants afterwards.\r
* @param sp Shader program to use.\r
*/\r
Result shaderProgramUse(shaderProgram_s* sp);\r
#include <stdlib.h>\r
#include <string.h>\r
#include <3ds/types.h>\r
+#include <3ds/result.h>\r
#include <3ds/gpu/registers.h>\r
#include <3ds/gpu/shaderProgram.h>\r
\r
\r
si->dvle = dvle;\r
\r
- si->boolUniforms = 0xFFFF;\r
+ si->boolUniforms = 0;\r
+ si->boolUniformMask = 0;\r
si->intUniforms[0] = 0x00000000;\r
si->intUniforms[1] = 0x00000000;\r
si->intUniforms[2] = 0x00000000;\r
si->intUniforms[3] = 0x00000000;\r
si->float24Uniforms = NULL;\r
+ si->intUniformMask = 0;\r
\r
int i;\r
DVLE_constEntry_s* cnst = dvle->constTableData;\r
shaderInstanceSetBool(si, cnst[i].id, cnst[i].data[0]&1);\r
break;\r
case DVLE_CONST_u8:\r
- if(cnst[i].id<4)si->intUniforms[cnst[i].id] = cnst[i].data[0];\r
+ if(cnst[i].id<4)\r
+ {\r
+ si->intUniforms[cnst[i].id] = cnst[i].data[0];\r
+ si->intUniformMask |= (1<<cnst[i].id);\r
+ }\r
break;\r
case DVLE_CONST_FLOAT24:\r
float24cnt++;\r
\r
si->boolUniforms &= ~(1<<id);\r
si->boolUniforms |= (value)<<id;\r
+ si->boolUniformMask |= (1<<id);\r
\r
return 0;\r
}\r
if(id<0 || id>15)return -2;\r
if(!value)return -3;\r
\r
- *value = !((si->boolUniforms>>id)&1);\r
+ *value = ((si->boolUniforms>>id)&1);\r
\r
return 0;\r
}\r
\r
-Result shaderInstanceGetUniformLocation(shaderInstance_s* si, const char* name)\r
+s8 shaderInstanceGetUniformLocation(shaderInstance_s* si, const char* name)\r
{\r
if(!si)return -1;\r
\r
sp->geometryShader = (shaderInstance_s*)malloc(sizeof(shaderInstance_s));\r
if(!sp->geometryShader)return -3;\r
\r
- sp->geometryShaderInputStride = stride;\r
+ sp->geoShaderInputPermutation[0] = 0x76543210;\r
+ sp->geoShaderInputPermutation[1] = 0xFEDCBA98;\r
+ sp->geoShaderInputStride = stride;\r
\r
return shaderInstanceInit(sp->geometryShader, dvle);\r
}\r
\r
-Result shaderProgramUse(shaderProgram_s* sp)\r
+Result shaderProgramSetGshInputPermutation(shaderProgram_s* sp, u64 permutation)\r
+{\r
+ if(!sp || !sp->geometryShader)return -1;\r
+\r
+ sp->geoShaderInputPermutation[0] = permutation & 0xFFFFFFFF;\r
+ sp->geoShaderInputPermutation[0] = permutation>>32;\r
+ return 0;\r
+}\r
+\r
+Result shaderProgramConfigure(shaderProgram_s* sp, bool sendVshCode, bool sendGshCode)\r
{\r
if(!sp)return -1;\r
\r
if(!sp->vertexShader)return -2;\r
\r
- int i;\r
-\r
// configure geostage\r
// has to be done first or else VSH registers might only reconfigure 3 of the 4 shader units !\r
if(!sp->geometryShader)\r
// setup vertex shader stuff no matter what\r
const DVLE_s* vshDvle = sp->vertexShader->dvle;\r
const DVLP_s* vshDvlp = vshDvle->dvlp;\r
- GPU_SendShaderCode(vshDvle->type, vshDvlp->codeData, 0, vshDvlp->codeSize);\r
- GPU_SendOperandDescriptors(vshDvle->type, vshDvlp->opcdescData, 0, vshDvlp->opdescSize);\r
- GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM, 0x7FFF0000|sp->vertexShader->boolUniforms);\r
- GPUCMD_AddIncrementalWrites(GPUREG_VSH_INTUNIFORM_I0, sp->vertexShader->intUniforms, 4);\r
- for(i=0; i<sp->vertexShader->numFloat24Uniforms; i++) GPUCMD_AddIncrementalWrites(GPUREG_VSH_FLOATUNIFORM_CONFIG, (u32*)&sp->vertexShader->float24Uniforms[i], 4);\r
+ if (sendVshCode)\r
+ {\r
+ GPU_SendShaderCode(vshDvle->type, vshDvlp->codeData, 0, vshDvlp->codeSize);\r
+ GPU_SendOperandDescriptors(vshDvle->type, vshDvlp->opcdescData, 0, vshDvlp->opdescSize);\r
+ }\r
GPUCMD_AddWrite(GPUREG_VSH_ENTRYPOINT, 0x7FFF0000|(vshDvle->mainOffset&0xFFFF));\r
GPUCMD_AddWrite(GPUREG_VSH_OUTMAP_MASK, vshDvle->outmapMask);\r
\r
// setup both vertex and geometry shader\r
const DVLE_s* gshDvle = sp->geometryShader->dvle;\r
const DVLP_s* gshDvlp = gshDvle->dvlp;\r
- GPU_SendShaderCode(gshDvle->type, gshDvlp->codeData, 0, gshDvlp->codeSize);\r
- GPU_SendOperandDescriptors(gshDvle->type, gshDvlp->opcdescData, 0, gshDvlp->opdescSize);\r
- GPUCMD_AddWrite(GPUREG_GSH_BOOLUNIFORM, 0x7FFF0000|sp->geometryShader->boolUniforms);\r
- GPUCMD_AddIncrementalWrites(GPUREG_GSH_INTUNIFORM_I0, sp->geometryShader->intUniforms, 4);\r
- for(i=0; i<sp->geometryShader->numFloat24Uniforms; i++) GPUCMD_AddIncrementalWrites(GPUREG_GSH_FLOATUNIFORM_CONFIG, (u32*)&sp->geometryShader->float24Uniforms[i], 4);\r
+ if (sendGshCode)\r
+ {\r
+ GPU_SendShaderCode(gshDvle->type, gshDvlp->codeData, 0, gshDvlp->codeSize);\r
+ GPU_SendOperandDescriptors(gshDvle->type, gshDvlp->opcdescData, 0, gshDvlp->opdescSize);\r
+ }\r
GPUCMD_AddWrite(GPUREG_GSH_ENTRYPOINT, 0x7FFF0000|(gshDvle->mainOffset&0xFFFF));\r
GPUCMD_AddWrite(GPUREG_GSH_OUTMAP_MASK, gshDvle->outmapMask);\r
\r
GPU_SetShaderOutmap((u32*)gshDvle->outmapData);\r
\r
//GSH input attributes stuff\r
- GPUCMD_AddWrite(GPUREG_GSH_INPUTBUFFER_CONFIG, 0x08000000|(sp->geometryShaderInputStride-1));\r
- GPUCMD_AddIncrementalWrites(GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW, ((u32[]){0x76543210, 0xFEDCBA98}), 2);\r
+ GPUCMD_AddWrite(GPUREG_GSH_INPUTBUFFER_CONFIG, 0x08000000|(sp->geoShaderInputStride-1));\r
+ GPUCMD_AddIncrementalWrites(GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW, sp->geoShaderInputPermutation, 2);\r
\r
GPUCMD_AddWrite(GPUREG_0064, 0x00000001); // ?\r
GPUCMD_AddWrite(GPUREG_006F, 0x01030703); // ?\r
return 0;\r
}\r
\r
+Result shaderProgramUse(shaderProgram_s* sp)\r
+{\r
+ Result rc = shaderProgramConfigure(sp, true, true);\r
+ if (R_FAILED(rc)) return rc;\r
+\r
+ int i;\r
+\r
+ // Set up uniforms\r
+ GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM, 0x7FFF0000|~sp->vertexShader->boolUniforms);\r
+ GPUCMD_AddIncrementalWrites(GPUREG_VSH_INTUNIFORM_I0, sp->vertexShader->intUniforms, 4);\r
+ for(i=0; i<sp->vertexShader->numFloat24Uniforms; i++) GPUCMD_AddIncrementalWrites(GPUREG_VSH_FLOATUNIFORM_CONFIG, (u32*)&sp->vertexShader->float24Uniforms[i], 4);\r
+ if (sp->geometryShader)\r
+ {\r
+ GPUCMD_AddWrite(GPUREG_GSH_BOOLUNIFORM, 0x7FFF0000|~sp->geometryShader->boolUniforms);\r
+ GPUCMD_AddIncrementalWrites(GPUREG_GSH_INTUNIFORM_I0, sp->geometryShader->intUniforms, 4);\r
+ for(i=0; i<sp->geometryShader->numFloat24Uniforms; i++) GPUCMD_AddIncrementalWrites(GPUREG_GSH_FLOATUNIFORM_CONFIG, (u32*)&sp->geometryShader->float24Uniforms[i], 4);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
void GPU_SetShaderOutmap(u32 outmapData[8])\r
{\r
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x1, outmapData[0]-1);\r