mojoshader icon indicating copy to clipboard operation
mojoshader copied to clipboard

[hlsl] PointCoord Support

Open flibitijibibo opened this issue 4 years ago • 1 comments
trafficstars

I'm pretty sure we noticed this the first time around, but it came up again while we were using Flotilla as an experiment for NativeAOT support. Simply put, GLSL/SPIR-V both have gl_PointCoord or gl_TexCoord[0] working with point sprites, but D3D11 doesn't appear to have a straightforward equivalent (as far as I know, TEXCOORD0 doesn't work like it did with D3D9). Microsoft incorrectly suggests using VPOS, and ANGLE emulates point sprites with geometry shaders, so this doesn't look good.

flibitijibibo avatar Jul 13 '21 03:07 flibitijibibo

If anyone's interested in experimenting with possible solutions, I've scribbled out a rough version of what the general structure might look like, minus the key part -- what semantic or convoluted workaround we should use.

diff --git a/mojoshader_d3d11.c b/mojoshader_d3d11.c
index 92902fd..e113a05 100644
--- a/mojoshader_d3d11.c
+++ b/mojoshader_d3d11.c
@@ -415,7 +415,7 @@ static char *rewritePixelShader(MOJOSHADER_d3d11Shader *vshader,
     const char *_Input = "_Input" ENDLINE_STR "{" ENDLINE_STR;
     const char *vsrc = vpd->output;
     const char *psrc = ppd->output;
-    const char *a, *b, *vout, *pstart, *vface, *pend;
+    const char *a, *b, *vout, *pstart, *vface, *pointcoord, *pend;
     size_t substr_len;
     char *pfinal;
 
@@ -449,6 +449,7 @@ static char *rewritePixelShader(MOJOSHADER_d3d11Shader *vshader,
     // Find matching semantics
     int i, j;
     int vfaceidx = -1;
+    int pointcoordidx = -1;
     const char *pvarname, *vvarname;
     for (i = 0; i < ppd->attribute_count; i++)
     {
@@ -477,7 +478,21 @@ static char *rewritePixelShader(MOJOSHADER_d3d11Shader *vshader,
         } // for
 
         if (strcmp(ppd->attributes[i].name, "vFace") == 0)
+        {
+            found_matching_vs_output_for_ps_input = 1;
             vfaceidx = i;
+        } // if
+
+        if (!found_matching_vs_output_for_ps_input)
+        {
+            if (ppd->attributes[i].usage == MOJOSHADER_USAGE_TEXCOORD &&
+                ppd->attributes[i].index == 0)
+            {
+                found_matching_vs_output_for_ps_input = 1;
+                pointcoordidx = i;
+                replaceVarname(ppd->attributes[i].name, "pointCoord", &pend);
+            } // if
+        } // if
 
         // A vertex shader that doesn't properly initialize all its outputs
         //  can produce a situation where vpd->outputs is missing a matching
@@ -491,14 +506,18 @@ static char *rewritePixelShader(MOJOSHADER_d3d11Shader *vshader,
     // Special handling for VFACE
     vface = (vfaceidx != -1) ? "\tbool m_vFace : SV_IsFrontFace;\n" : "";
 
+    // Special handling for point coord (aka TEXCOORD0)
+    pointcoord = (pointcoordidx != -1) ? "\tfloat2 m_pointCoord : TEXCOORD0;\n" : ""; // FIXME: What semantic...?
+
     // Concatenate the shader pieces together
-    substr_len = strlen(pstart) + strlen(vout) + strlen(vface) + strlen(pend);
+    substr_len = strlen(pstart) + strlen(vout) + strlen(vface) + strlen(pointcoord) + strlen(pend);
     pfinal = (char *) ctx->malloc_fn(substr_len + 1, ctx->malloc_data);
     memset((void *) pfinal, '\0', substr_len + 1);
     memcpy(pfinal, pstart, strlen(pstart));
     memcpy(pfinal + strlen(pstart), vout, strlen(vout));
     memcpy(pfinal + strlen(pstart) + strlen(vout), vface, strlen(vface));
-    memcpy(pfinal + strlen(pstart) + strlen(vout) + strlen(vface), pend, strlen(pend));
+    memcpy(pfinal + strlen(pstart) + strlen(vout) + strlen(vface), pointcoord, strlen(pointcoord));
+    memcpy(pfinal + strlen(pstart) + strlen(vout) + strlen(vface) + strlen(pointcoord), pend, strlen(pend));
 
     // Free the temporary buffers
     ctx->free_fn((void *) vout, ctx->malloc_data);

TheSpydog avatar Jul 13 '21 03:07 TheSpydog