From c048221f866052fe4c3762bb321d0ed6827ed459 Mon Sep 17 00:00:00 2001 From: fincs Date: Sat, 5 Dec 2015 13:28:41 +0100 Subject: [PATCH] Add shaderProgramSetGshMode() for configuring geoshader mode --- libctru/include/3ds/gpu/shaderProgram.h | 17 +++++++++++++++++ libctru/source/gpu/shaderProgram.c | 22 +++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/libctru/include/3ds/gpu/shaderProgram.h b/libctru/include/3ds/gpu/shaderProgram.h index 70d2457..90f1692 100644 --- a/libctru/include/3ds/gpu/shaderProgram.h +++ b/libctru/include/3ds/gpu/shaderProgram.h @@ -33,8 +33,18 @@ typedef struct shaderInstance_s* geometryShader; ///< Geometry shader. u32 geoShaderInputPermutation[2]; ///< Geometry shader input permutation. u8 geoShaderInputStride; ///< Geometry shader input stride. + u8 geoShaderMode; ///< Geometry shader operation mode. }shaderProgram_s; +/// Geometry shader operation modes. +typedef enum +{ + GSH_NORMAL = 0, ///< Normal operation. + GSH_PARTICLE = 1, ///< Particle system. + GSH_SUBDIVISION_LOOP = 2, ///< Loop subdivision surface. + GSH_SUBDIVISION_CATMULL_CLARK = 3, ///< Catmull-Clark subdivision surface. +} geoShaderMode; + /** * @brief Initializes a shader instance. * @param si Shader instance to initialize. @@ -105,6 +115,13 @@ Result shaderProgramSetGsh(shaderProgram_s* sp, DVLE_s* dvle, u8 stride); */ Result shaderProgramSetGshInputPermutation(shaderProgram_s* sp, u64 permutation); +/** + * @brief Configures the operation mode of the geometry shader of a shader program. + * @param sp Shader program to use. + * @param mode Operation mode to use. + */ +Result shaderProgramSetGshMode(shaderProgram_s* sp, geoShaderMode mode); + /** * @brief Configures the shader units to use the specified shader program. * @param sp Shader program to use. diff --git a/libctru/source/gpu/shaderProgram.c b/libctru/source/gpu/shaderProgram.c index a891dcb..8b2c34e 100644 --- a/libctru/source/gpu/shaderProgram.c +++ b/libctru/source/gpu/shaderProgram.c @@ -168,6 +168,7 @@ Result shaderProgramSetGsh(shaderProgram_s* sp, DVLE_s* dvle, u8 stride) sp->geoShaderInputPermutation[0] = 0x76543210; sp->geoShaderInputPermutation[1] = 0xFEDCBA98; sp->geoShaderInputStride = stride; + sp->geoShaderMode = GSH_NORMAL; return shaderInstanceInit(sp->geometryShader, dvle); } @@ -181,6 +182,14 @@ Result shaderProgramSetGshInputPermutation(shaderProgram_s* sp, u64 permutation) return 0; } +Result shaderProgramSetGshMode(shaderProgram_s* sp, geoShaderMode mode) +{ + if(!sp || !sp->geometryShader)return -1; + + sp->geoShaderMode = mode & 3; + return 0; +} + Result shaderProgramConfigure(shaderProgram_s* sp, bool sendVshCode, bool sendGshCode) { if(!sp)return -1; @@ -212,8 +221,15 @@ Result shaderProgramConfigure(shaderProgram_s* sp, bool sendVshCode, bool sendGs GPUCMD_AddWrite(GPUREG_VSH_OUTMAP_TOTAL1, vshDvle->outmapData[0]-1); // ? GPUCMD_AddWrite(GPUREG_VSH_OUTMAP_TOTAL2, vshDvle->outmapData[0]-1); // ? - GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 0x8, 0x00000000); // ? - GPUCMD_AddWrite(GPUREG_GSH_MISC0, 0x00000000); // ? + bool subdivision = sp->geoShaderMode >= GSH_SUBDIVISION_LOOP; + GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 0x8, subdivision ? 0x80000000 : 0); // Enable or disable subdivision + u32 gshMisc = 0; + if (subdivision) + gshMisc = 1; + else if (sp->geoShaderMode == GSH_PARTICLE) + gshMisc = 0x01004302; + GPUCMD_AddWrite(GPUREG_GSH_MISC0, gshMisc); + GPUCMD_AddWrite(GPUREG_GSH_MISC1, sp->geoShaderMode); if(!sp->geometryShader) { @@ -237,7 +253,7 @@ Result shaderProgramConfigure(shaderProgram_s* sp, bool sendVshCode, bool sendGs GPU_SetShaderOutmap((u32*)gshDvle->outmapData); //GSH input attributes stuff - GPUCMD_AddWrite(GPUREG_GSH_INPUTBUFFER_CONFIG, 0x08000000|(sp->geoShaderInputStride-1)); + GPUCMD_AddWrite(GPUREG_GSH_INPUTBUFFER_CONFIG, 0x08000000|(sp->geoShaderInputStride-1)|(subdivision?0x100:0)); GPUCMD_AddIncrementalWrites(GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW, sp->geoShaderInputPermutation, 2); GPUCMD_AddWrite(GPUREG_SH_OUTATTR_MODE, gshDvle->outmapMode);