Skip to content

Commit

Permalink
spirv: Fix PointCoord input using vec4 instead of vec2
Browse files Browse the repository at this point in the history
  • Loading branch information
krolli committed Nov 11, 2020
1 parent 884cae5 commit bfdc87c
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 7 deletions.
6 changes: 5 additions & 1 deletion mojoshader_common.c
Expand Up @@ -1135,13 +1135,17 @@ void MOJOSHADER_spirv_link_attributes(const MOJOSHADER_parseData *vertex,
{
if (vTable->attrib_offsets[MOJOSHADER_USAGE_POINTSIZE][0] > 0)
{
((uint32 *) pixel->output)[pTable->pointcoord_var_offset + 1] = pTable->tid_pvec2i;
((uint32 *) pixel->output)[pTable->pointcoord_load_offset + 1] = pTable->tid_vec2;
((uint32 *) pixel->output)[texcoord0Loc - 1] = SpvDecorationBuiltIn;
((uint32 *) pixel->output)[texcoord0Loc] = SpvBuiltInPointCoord;
} // if
else
{
// texcoord0Loc should already have attr_loc from the above work!
((uint32 *) pixel->output)[pTable->pointcoord_var_offset + 1] = pTable->tid_pvec4i;
((uint32 *) pixel->output)[pTable->pointcoord_load_offset + 1] = pTable->tid_vec4;
((uint32 *) pixel->output)[texcoord0Loc - 1] = SpvDecorationLocation;
// texcoord0Loc should already have attr_loc from the above work!
} // else
} // if
} // MOJOSHADER_spirv_link_attributes
Expand Down
10 changes: 10 additions & 0 deletions mojoshader_internal.h
Expand Up @@ -753,6 +753,16 @@ typedef struct SpirvPatchTable
SpirvPatchEntry samplers[16];
int32 location_count;

// TEXCOORD0 is patched to PointCoord if VS outputs PointSize.
// In `helpers`: [OpDecorate|id|Location|0xDEADBEEF] -> [OpDecorate|id|BuiltIn|PointCoord]
// Offset derived from attrib_offsets[TEXCOORD][0].
uint32 pointcoord_var_offset; // in `mainline_intro`, [OpVariable|tid|id|StorageClass], patch tid to pvec2i
uint32 pointcoord_load_offset; // in `mainline_top`, [OpLoad|tid|id|src_id], patch tid to vec2
uint32 tid_pvec2i;
uint32 tid_vec2;
uint32 tid_pvec4i;
uint32 tid_vec4;

// Patches for linking vertex output/pixel input
uint32 attrib_offsets[MOJOSHADER_USAGE_TOTAL][16];
uint32 output_offsets[16];
Expand Down
79 changes: 74 additions & 5 deletions profiles/mojoshader_profile_spirv.c
Expand Up @@ -403,6 +403,12 @@ static uint32 spv_get_type(Context *ctx, SpirvTypeIdx tidx)
tid = spv_bumpid(ctx);
spv_emit(ctx, 4, SpvOpTypePointer, tid, SpvStorageClassUniformConstant, tid_image);
} // else if
else if (tidx == STI_PTR_VEC2_I)
{
uint32 tid_base = spv_get_type(ctx, STI_VEC2);
tid = spv_bumpid(ctx);
spv_emit(ctx, 4, SpvOpTypePointer, tid, SpvStorageClassInput, tid_base);
} // else if
else
assert(!"Unexpected value of type index.");
pop_output(ctx);
Expand Down Expand Up @@ -2281,11 +2287,56 @@ void emit_SPIRV_attribute(Context *ctx, RegisterType regtype, int regnum,
// ps_1_1 is dealt with in emit_SPIRV_global().
if (usage != MOJOSHADER_USAGE_TEXCOORD || shader_version_atleast(ctx, 1, 4))
{
spv_link_ps_attributes(ctx, r->spirv.iddecl, regtype, usage, index);
push_output(ctx, &ctx->mainline_intro);
tid = spv_get_type(ctx, STI_PTR_VEC4_I);
spv_emit(ctx, 4, SpvOpVariable, tid, r->spirv.iddecl, SpvStorageClassInput);
pop_output(ctx);
if (usage == MOJOSHADER_USAGE_TEXCOORD && index == 0)
{
// This can be either BuiltInPointCoord (vec2) or normal TEXCOORD0 input (vec4).
// To determine correct type, we need to wait until link-time when we can see
// vertex shader outputs and then patch in correct types. To avoid having to
// fix all loads from the input variable, we never access it directly, but
// instead go through private variable that is always vec4.
// Here we generate input and private variables and helper code that gets
// patched at link-time. See SpirvPatchTable for details on patching.
SpirvPatchTable* table = &ctx->spirv.patch_table;

uint32 tid_pvec2i = spv_get_type(ctx, STI_PTR_VEC2_I);
uint32 tid_pvec4i = spv_get_type(ctx, STI_PTR_VEC4_I);
uint32 tid_pvec4p = spv_get_type(ctx, STI_PTR_VEC4_P);
uint32 tid_vec2 = spv_get_type(ctx, STI_VEC2);
uint32 tid_vec4 = spv_get_type(ctx, STI_VEC4);

table->tid_pvec2i = tid_pvec2i;
table->tid_vec2 = tid_vec2;
table->tid_pvec4i = tid_pvec4i;
table->tid_vec4 = tid_vec4;

push_output(ctx, &ctx->mainline_intro);
ctx->spirv.id_var_texcoord0_private = r->spirv.iddecl;
ctx->spirv.id_var_texcoord0_input = spv_bumpid(ctx);
table->pointcoord_var_offset = buffer_size(ctx->mainline_intro) >> 2;
spv_emit(ctx, 4, SpvOpVariable, tid_pvec4i, ctx->spirv.id_var_texcoord0_input, SpvStorageClassInput);
spv_emit(ctx, 4, SpvOpVariable, tid_pvec4p, ctx->spirv.id_var_texcoord0_private, SpvStorageClassPrivate);
pop_output(ctx);

spv_link_ps_attributes(ctx, ctx->spirv.id_var_texcoord0_input, regtype, usage, index);
spv_output_name(ctx, ctx->spirv.id_var_texcoord0_input, "ps_PointCoordOrTexCoord0");

push_output(ctx, &ctx->mainline_top);
uint32 id_loaded = spv_bumpid(ctx);
uint32 id_shuffled = spv_bumpid(ctx);
table->pointcoord_load_offset = buffer_size(ctx->mainline_top) >> 2;
spv_emit(ctx, 4, SpvOpLoad, tid_vec4, id_loaded, ctx->spirv.id_var_texcoord0_input);
spv_emit(ctx, 9, SpvOpVectorShuffle, tid_vec4, id_shuffled, id_loaded, id_loaded, 0, 1, 2, 3);
spv_emit(ctx, 3, SpvOpStore, ctx->spirv.id_var_texcoord0_private, id_shuffled);
pop_output(ctx);
} // if
else
{
spv_link_ps_attributes(ctx, r->spirv.iddecl, regtype, usage, index);
push_output(ctx, &ctx->mainline_intro);
tid = spv_get_type(ctx, STI_PTR_VEC4_I);
spv_emit(ctx, 4, SpvOpVariable, tid, r->spirv.iddecl, SpvStorageClassInput);
pop_output(ctx);
} // else
} // if
break;
default:
Expand Down Expand Up @@ -2517,6 +2568,8 @@ void emit_SPIRV_finalize(Context *ctx)
spv_emit_word(ctx, ctx->spirv.id_var_fragcoord);
else if (r->spirv.iddecl == ctx->spirv.id_var_vface)
spv_emit_word(ctx, ctx->spirv.id_var_frontfacing);
else if (r->spirv.iddecl == ctx->spirv.id_var_texcoord0_private)
spv_emit_word(ctx, ctx->spirv.id_var_texcoord0_input);
else
spv_emit_word(ctx, r->spirv.iddecl);
} // if
Expand Down Expand Up @@ -2630,6 +2683,22 @@ void emit_SPIRV_finalize(Context *ctx)
if (table->output_offsets[i])
table->output_offsets[i] += base_offset;

base_offset <<= 2;
if (ctx->helpers) base_offset += buffer_size(ctx->helpers);
if (ctx->subroutines) base_offset += buffer_size(ctx->subroutines);
base_offset >>= 2;

if (table->pointcoord_var_offset)
table->pointcoord_var_offset += base_offset;

base_offset <<= 2;
if (ctx->mainline_intro) base_offset += buffer_size(ctx->mainline_intro);
if (ctx->mainline_arguments) base_offset += buffer_size(ctx->mainline_arguments);
base_offset >>= 2;

if (table->pointcoord_load_offset)
table->pointcoord_load_offset += base_offset;

push_output(ctx, &ctx->postflight);
buffer_append(ctx->output, &ctx->spirv.patch_table, sizeof(ctx->spirv.patch_table));
pop_output(ctx);
Expand Down
5 changes: 4 additions & 1 deletion profiles/mojoshader_profile_spirv.h
Expand Up @@ -75,8 +75,9 @@ typedef enum SpirvTypeIdx
STI_PTR_IMAGE2D = 6,
STI_PTR_IMAGE3D = 7,
STI_PTR_IMAGECUBE = 8,
STI_PTR_VEC2_I = 9, // special case, needed only for point coord input.

// 7 unused entries
// 6 unused entries

// 4 base types * 4 vector sizes = 16 entries
STI_FLOAT = (0 << 5) | (1 << 4) | (ST_FLOAT << 2) | 0,
Expand Down Expand Up @@ -175,6 +176,8 @@ typedef struct SpirvContext
uint32 id_var_vpos;
uint32 id_var_frontfacing;
uint32 id_var_vface;
uint32 id_var_texcoord0_input;
uint32 id_var_texcoord0_private;
// ids for types so we can reuse them after they're declared
uint32 tid[STI_LENGTH_];
uint32 idtrue;
Expand Down

0 comments on commit bfdc87c

Please sign in to comment.