spirv: Separate pixel shader outputs from inputs, fix linker accordingly
authorEthan Lee <flibitijibibo@flibitijibibo.com>
Sun, 30 Aug 2020 21:35:31 -0400
changeset 1303 7a43f238f28a
parent 1302 974d2cc3558e
child 1304 d68910d81b6e
spirv: Separate pixel shader outputs from inputs, fix linker accordingly
mojoshader_common.c
mojoshader_internal.h
profiles/mojoshader_profile_spirv.c
--- a/mojoshader_common.c	Thu Aug 27 17:18:38 2020 -0400
+++ b/mojoshader_common.c	Sun Aug 30 21:35:31 2020 -0400
@@ -1062,7 +1062,7 @@
                                       const MOJOSHADER_parseData *pixel)
 {
     int i;
-    uint32 attr_loc = 1; // 0 is reserved for COLOR0
+    uint32 attr_loc = 0;
     uint32 vOffset, pOffset;
     int vDataLen = vertex->output_len - sizeof(SpirvPatchTable);
     int pDataLen = pixel->output_len - sizeof(SpirvPatchTable);
@@ -1075,11 +1075,21 @@
     {
         const MOJOSHADER_attribute *pAttr = &pixel->outputs[i];
         assert(pAttr->usage == MOJOSHADER_USAGE_COLOR);
-        if (pAttr->index == 0)
-            continue;
+
+        // Set the loc for the output declaration...
+        pOffset = pTable->output_offsets[pAttr->index];
+        assert(pOffset > 0);
+        ((uint32 *) pixel->output)[pOffset] = attr_loc;
 
+        // Set the same value for the vertex output/pixel input...
         pOffset = pTable->attrib_offsets[pAttr->usage][pAttr->index];
-        ((uint32 *) pixel->output)[pOffset] = attr_loc;
+        if (pOffset)
+            ((uint32 *) pixel->output)[pOffset] = attr_loc;
+        vOffset = vTable->attrib_offsets[pAttr->usage][pAttr->index];
+        if (vOffset)
+            ((uint32 *) vertex->output)[vOffset] = attr_loc;
+
+        // ... increment location index, finally.
         attr_loc++;
     } // for
 
@@ -1089,7 +1099,7 @@
         const MOJOSHADER_attribute *pAttr = &pixel->attributes[i];
         if (pAttr->usage == MOJOSHADER_USAGE_UNKNOWN)
             continue; // Probably something like VPOS, ignore!
-        if (pAttr->usage == MOJOSHADER_USAGE_COLOR && pAttr->index == 0)
+        if (pAttr->usage == MOJOSHADER_USAGE_COLOR && pTable->output_offsets[pAttr->index])
             continue;
 
         // The input may not exist in the output list!
@@ -1110,7 +1120,7 @@
             continue;
         if (vAttr->usage == MOJOSHADER_USAGE_POINTSIZE && vAttr->index == 0)
             continue;
-        if (vAttr->usage == MOJOSHADER_USAGE_COLOR && vAttr->index == 0)
+        if (vAttr->usage == MOJOSHADER_USAGE_COLOR && pTable->output_offsets[vAttr->index])
             continue;
 
         if (!pTable->attrib_offsets[vAttr->usage][vAttr->index])
--- a/mojoshader_internal.h	Thu Aug 27 17:18:38 2020 -0400
+++ b/mojoshader_internal.h	Sun Aug 30 21:35:31 2020 -0400
@@ -755,6 +755,7 @@
 
     // Patches for linking vertex output/pixel input
     uint32 attrib_offsets[MOJOSHADER_USAGE_TOTAL][16];
+    uint32 output_offsets[16];
 } SpirvPatchTable;
 
 void MOJOSHADER_spirv_link_attributes(const MOJOSHADER_parseData *vertex,
--- a/profiles/mojoshader_profile_spirv.c	Thu Aug 27 17:18:38 2020 -0400
+++ b/profiles/mojoshader_profile_spirv.c	Sun Aug 30 21:35:31 2020 -0400
@@ -271,6 +271,15 @@
     return (buffer_size(ctx->helpers) >> 2) - 1;
 } // spv_output_location
 
+static void spv_output_color_location(Context *ctx, uint32 id, uint32 index)
+{
+    SpirvPatchTable* table = &ctx->spirv.patch_table;
+    push_output(ctx, &ctx->helpers);
+    spv_emit(ctx, 4, SpvOpDecorate, id, SpvDecorationLocation, index);
+    pop_output(ctx);
+    table->output_offsets[index] = (buffer_size(ctx->helpers) >> 2) - 1;
+} // spv_output_color_location
+
 static void spv_output_attrib_location(Context *ctx, uint32 id,
                                        MOJOSHADER_usage usage, uint32 index)
 {
@@ -1632,8 +1641,6 @@
         spv_output_builtin(ctx, id, SpvBuiltInPointSize);
         ctx->spirv.patch_table.attrib_offsets[usage][index] = 1;
     } // else if
-    else if (usage == MOJOSHADER_USAGE_COLOR && index == 0)
-        spv_output_location(ctx, id, 0);
     else
         spv_output_attrib_location(ctx, id, usage, index);
 } // spv_link_vs_attributes
@@ -1652,16 +1659,10 @@
             // - decorated with location 0
             // - not decorated as a built-in variable.
             // There is no implicit broadcast.
-            if (index == 0)
-                spv_output_location(ctx, id, 0);
-            else
-                spv_output_attrib_location(ctx, id, MOJOSHADER_USAGE_COLOR, index);
+            spv_output_color_location(ctx, id, index);
             break;
         case REG_TYPE_INPUT: // v# (MOJOSHADER_USAGE_COLOR aka `oC#` in vertex shader)
-            if (usage == MOJOSHADER_USAGE_COLOR && index == 0)
-                spv_output_location(ctx, id, 0);
-            else
-                spv_output_attrib_location(ctx, id, usage, index);
+            spv_output_attrib_location(ctx, id, usage, index);
             break;
         case REG_TYPE_TEXTURE: // t# (MOJOSHADER_USAGE_TEXCOORD aka `oT#` in vertex shader)
             spv_output_attrib_location(ctx, id, MOJOSHADER_USAGE_TEXCOORD, index);
@@ -2625,6 +2626,9 @@
         for (j = 0; j < 16; j++)
             if (table->attrib_offsets[i][j])
                 table->attrib_offsets[i][j] += base_offset;
+    for (i = 0; i < 16; i++)
+        if (table->output_offsets[i])
+            table->output_offsets[i] += base_offset;
 
     push_output(ctx, &ctx->postflight);
     buffer_append(ctx->output, &ctx->spirv.patch_table, sizeof(ctx->spirv.patch_table));