nir/spirv: add gl_spirv_validation method

ARB_gl_spirv adds the ability to use SPIR-V binaries, and a new
method, glSpecializeShader. Here we add a new function to do the
validation for this function:

From OpenGL 4.6 spec, section 7.2.1"

   "Shader Specialization", error table:

    INVALID_VALUE is generated if <pEntryPoint> does not name a valid
    entry point for <shader>.

    INVALID_VALUE is generated if any element of <pConstantIndex>
    refers to a specialization constant that does not exist in the
    shader module contained in <shader>.""

v2: rebase update (spirv_to_nir options added, changes on the warning
    logging, and others)

v3: include passing options on common initialization, doesn't call
    setjmp on common_initialization

v4: (after Jason comments):
  * Rename common_initialization to vtn_builder_create
  * Move validation method and their helpers to own source file.
  * Create own handle_constant_decoration_cb instead of reuse existing one

v5: put vtn_build_create refactoring to their own patch (Jason)

v6: update after vtn_builder_create method renamed, add explanatory
    comment, tweak existing comment and commit message (Timothy)
This commit is contained in:
Alejandro Piñeiro
2018-01-18 12:31:52 +01:00
parent bebe3d626e
commit 9063bf7ad8
6 changed files with 305 additions and 14 deletions

View File

@@ -466,7 +466,7 @@ vtn_foreach_execution_mode(struct vtn_builder *b, struct vtn_value *value,
}
}
static void
void
vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
{
@@ -3191,6 +3191,24 @@ stage_for_execution_model(struct vtn_builder *b, SpvExecutionModel model)
spirv_capability_to_string(cap)); \
} while(0)
void
vtn_handle_entry_point(struct vtn_builder *b, const uint32_t *w,
unsigned count)
{
struct vtn_value *entry_point = &b->values[w[2]];
/* Let this be a name label regardless */
unsigned name_words;
entry_point->name = vtn_string_literal(b, &w[3], count - 3, &name_words);
if (strcmp(entry_point->name, b->entry_point_name) != 0 ||
stage_for_execution_model(b, w[1]) != b->entry_point_stage)
return;
vtn_assert(b->entry_point == NULL);
b->entry_point = entry_point;
}
static bool
vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
@@ -3379,20 +3397,9 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
w[2] == SpvMemoryModelGLSL450);
break;
case SpvOpEntryPoint: {
struct vtn_value *entry_point = &b->values[w[2]];
/* Let this be a name label regardless */
unsigned name_words;
entry_point->name = vtn_string_literal(b, &w[3], count - 3, &name_words);
if (strcmp(entry_point->name, b->entry_point_name) != 0 ||
stage_for_execution_model(b, w[1]) != b->entry_point_stage)
break;
vtn_assert(b->entry_point == NULL);
b->entry_point = entry_point;
case SpvOpEntryPoint:
vtn_handle_entry_point(b, w, count);
break;
}
case SpvOpString:
vtn_push_value(b, w[1], vtn_value_type_string)->str =