shaderInstance_s* geometryShader; ///< Geometry shader.\r
u32 geoShaderInputPermutation[2]; ///< Geometry shader input permutation.\r
u8 geoShaderInputStride; ///< Geometry shader input stride.\r
+ u8 geoShaderMode; ///< Geometry shader operation mode.\r
}shaderProgram_s;\r
\r
+/// Geometry shader operation modes.\r
+typedef enum\r
+{\r
+ GSH_NORMAL = 0, ///< Normal operation.\r
+ GSH_PARTICLE = 1, ///< Particle system.\r
+ GSH_SUBDIVISION_LOOP = 2, ///< Loop subdivision surface.\r
+ GSH_SUBDIVISION_CATMULL_CLARK = 3, ///< Catmull-Clark subdivision surface.\r
+} geoShaderMode;\r
+\r
/**\r
* @brief Initializes a shader instance.\r
* @param si Shader instance to initialize.\r
*/\r
Result shaderProgramSetGshInputPermutation(shaderProgram_s* sp, u64 permutation);\r
\r
+/**\r
+ * @brief Configures the operation mode of the geometry shader of a shader program.\r
+ * @param sp Shader program to use.\r
+ * @param mode Operation mode to use.\r
+ */\r
+Result shaderProgramSetGshMode(shaderProgram_s* sp, geoShaderMode mode);\r
+\r
/**\r
* @brief Configures the shader units to use the specified shader program.\r
* @param sp Shader program to use.\r
sp->geoShaderInputPermutation[0] = 0x76543210;\r
sp->geoShaderInputPermutation[1] = 0xFEDCBA98;\r
sp->geoShaderInputStride = stride;\r
+ sp->geoShaderMode = GSH_NORMAL;\r
\r
return shaderInstanceInit(sp->geometryShader, dvle);\r
}\r
return 0;\r
}\r
\r
+Result shaderProgramSetGshMode(shaderProgram_s* sp, geoShaderMode mode)\r
+{\r
+ if(!sp || !sp->geometryShader)return -1;\r
+\r
+ sp->geoShaderMode = mode & 3;\r
+ return 0;\r
+}\r
+\r
Result shaderProgramConfigure(shaderProgram_s* sp, bool sendVshCode, bool sendGshCode)\r
{\r
if(!sp)return -1;\r
GPUCMD_AddWrite(GPUREG_VSH_OUTMAP_TOTAL1, vshDvle->outmapData[0]-1); // ?\r
GPUCMD_AddWrite(GPUREG_VSH_OUTMAP_TOTAL2, vshDvle->outmapData[0]-1); // ?\r
\r
- GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 0x8, 0x00000000); // ?\r
- GPUCMD_AddWrite(GPUREG_GSH_MISC0, 0x00000000); // ?\r
+ bool subdivision = sp->geoShaderMode >= GSH_SUBDIVISION_LOOP;\r
+ GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 0x8, subdivision ? 0x80000000 : 0); // Enable or disable subdivision\r
+ u32 gshMisc = 0;\r
+ if (subdivision)\r
+ gshMisc = 1;\r
+ else if (sp->geoShaderMode == GSH_PARTICLE)\r
+ gshMisc = 0x01004302;\r
+ GPUCMD_AddWrite(GPUREG_GSH_MISC0, gshMisc);\r
+ GPUCMD_AddWrite(GPUREG_GSH_MISC1, sp->geoShaderMode);\r
\r
if(!sp->geometryShader)\r
{\r
GPU_SetShaderOutmap((u32*)gshDvle->outmapData);\r
\r
//GSH input attributes stuff\r
- GPUCMD_AddWrite(GPUREG_GSH_INPUTBUFFER_CONFIG, 0x08000000|(sp->geoShaderInputStride-1));\r
+ GPUCMD_AddWrite(GPUREG_GSH_INPUTBUFFER_CONFIG, 0x08000000|(sp->geoShaderInputStride-1)|(subdivision?0x100:0));\r
GPUCMD_AddIncrementalWrites(GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW, sp->geoShaderInputPermutation, 2);\r
\r
GPUCMD_AddWrite(GPUREG_SH_OUTATTR_MODE, gshDvle->outmapMode);\r