]> Chaos Git - corbenik/ctrulib.git/commitdiff
Several improvements to shaderProgram, see details:
authorfincs <fincs.alt1@gmail.com>
Fri, 20 Nov 2015 23:49:33 +0000 (00:49 +0100)
committerfincs <fincs.alt1@gmail.com>
Fri, 20 Nov 2015 23:49:33 +0000 (00:49 +0100)
- shaderProgramSetGshInputPermutation() was added
- shaderInstanceGetUniformLocation() return type corrected
- shaderInstanceSetBool bug fixed (true/false were incorrectly mapped)
- shaderInstance now has bitmasks indicating which int/bool uniforms are
  used by int/bool constants in the DVLE
- shaderProgramUse() was revamped:
  - Shader unit setup/code/opdesc upload code was separated into a new
    function called shaderProgramConfigure()
  - shaderProgramUse() calls shaderProgramConfigure() and afterwards
    uploads DVLE constants
  - GPU wrappers that perform uniform management will want to use
    shaderProgramConfigure() instead of shaderProgramUse() and later
    read the shaderInstance uniform usage bitmasks to set the constants.

libctru/include/3ds/gpu/registers.h
libctru/include/3ds/gpu/shaderProgram.h
libctru/source/gpu/shaderProgram.c

index 9a61a79514330c42fb8053b6e27ee61dd82daf1f..52bf566e41f8e690b6b394fa24a3809e4d086897 100644 (file)
@@ -1,6 +1,6 @@
 /**\r
  * @file registers.h\r
- * @param GPU registers.\r
+ * @description GPU registers.\r
  */\r
 #pragma once\r
 \r
index 0393107b0a7bbd0be0df27a67a44d3617a013cd7..70d2457537bad94f4d78cbf71d657ddf6005a330 100644 (file)
@@ -19,8 +19,10 @@ typedef struct
 {\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
@@ -29,7 +31,8 @@ typedef struct
 {\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
@@ -66,7 +69,7 @@ Result shaderInstanceGetBool(shaderInstance_s* si, int id, bool* value);
  * @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
@@ -96,7 +99,22 @@ Result shaderProgramSetVsh(shaderProgram_s* sp, DVLE_s* dvle);
 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
index 5f548298bc33d4df92b4b29ee54e2a5ae517c06c..abefbe180f87853da8457bc41a41d2f020d7d2d7 100644 (file)
@@ -1,6 +1,7 @@
 #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
@@ -14,12 +15,14 @@ Result shaderInstanceInit(shaderInstance_s* si, DVLE_s* dvle)
 \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
@@ -34,7 +37,11 @@ Result shaderInstanceInit(shaderInstance_s* si, DVLE_s* dvle)
                                        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
@@ -92,6 +99,7 @@ Result shaderInstanceSetBool(shaderInstance_s* si, int id, bool value)
 \r
        si->boolUniforms &= ~(1<<id);\r
        si->boolUniforms |= (value)<<id;\r
+       si->boolUniformMask |= (1<<id);\r
 \r
        return 0;\r
 }\r
@@ -102,12 +110,12 @@ Result shaderInstanceGetBool(shaderInstance_s* si, int id, bool* value)
        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
@@ -157,19 +165,28 @@ Result shaderProgramSetGsh(shaderProgram_s* sp, DVLE_s* dvle, u8 stride)
        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
@@ -184,11 +201,11 @@ Result shaderProgramUse(shaderProgram_s* sp)
        // 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
@@ -209,19 +226,19 @@ Result shaderProgramUse(shaderProgram_s* sp)
                // 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
@@ -230,6 +247,27 @@ Result shaderProgramUse(shaderProgram_s* sp)
        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