mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-07 18:01:30 +00:00
[qfcc] Handle execution modes for spir-v/glsl
This means that `layout(triangles)` etc now work, though there are issues with frag shaders missing functions (since getting function calls working) and compute shaders silently failing.
This commit is contained in:
parent
105edc5126
commit
fb7025dbd3
15 changed files with 381 additions and 172 deletions
|
@ -115,6 +115,7 @@ extern type_t type_glsl_sampled_image;
|
|||
typedef struct glsl_sublang_s {
|
||||
const char *name;
|
||||
const char **interface_default_names;
|
||||
const char *model_name;
|
||||
} glsl_sublang_t;
|
||||
extern glsl_sublang_t glsl_sublang;
|
||||
extern glsl_sublang_t glsl_comp_sublanguage;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "tools/qfcc/include/expr.h"
|
||||
|
||||
typedef struct symbol_s symbol_t;
|
||||
typedef struct expr_s expr_t;
|
||||
|
||||
typedef struct entrypoint_s {
|
||||
struct entrypoint_s *next;
|
||||
|
@ -45,12 +46,22 @@ typedef struct entrypoint_s {
|
|||
ex_list_t interface; ///< list of symbols forming interface
|
||||
struct DARRAY_TYPE (symbol_t *) interface_syms;
|
||||
struct function_s *func;
|
||||
|
||||
const expr_t *invocations;
|
||||
const expr_t *local_size[3];
|
||||
const expr_t *primitive_in;
|
||||
const expr_t *primitive_out;
|
||||
const expr_t *max_vertices;
|
||||
const expr_t *spacing;
|
||||
const expr_t *order;
|
||||
const expr_t *frag_depth;
|
||||
bool point_mode;
|
||||
bool early_fragment_tests;
|
||||
} entrypoint_t;
|
||||
|
||||
typedef struct module_s {
|
||||
ex_list_t capabilities;
|
||||
ex_list_t extensions;
|
||||
SpvExecutionModel default_model;
|
||||
symtab_t *extinst_imports;
|
||||
const expr_t *addressing_model;
|
||||
const expr_t *memory_model;
|
||||
|
|
|
@ -100,5 +100,6 @@ const plitem_t *spirv_operand_kind (const char *set, const char *kind);
|
|||
uint32_t spirv_instruction_opcode (const char *set, const expr_t *opcode);
|
||||
|
||||
bool spirv_setup_intrinsic_symtab (symtab_t *symtab);
|
||||
uint32_t spirv_execution_model (const char *model);
|
||||
|
||||
#endif//__spirv_grammar_h
|
||||
|
|
|
@ -44,6 +44,8 @@ typedef struct {
|
|||
symtab_t *symtab, expr_t *block);
|
||||
void (*vararg_int) (const expr_t *e);
|
||||
|
||||
bool (*create_entry_point) (const char *name, const char *model_name);
|
||||
|
||||
const expr_t *(*initialized_temp) (const type_t *type, const expr_t *src);
|
||||
const expr_t *(*assign_vector) (const expr_t *dst, const expr_t *src);
|
||||
const expr_t *(*proc_switch) (const expr_t *expr, rua_ctx_t *ctx);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "tools/qfcc/include/rua-lang.h"
|
||||
#include "tools/qfcc/include/spirv.h"
|
||||
#include "tools/qfcc/include/struct.h"
|
||||
#include "tools/qfcc/include/target.h"
|
||||
#include "tools/qfcc/include/type.h"
|
||||
|
||||
glsl_sublang_t glsl_sublang;
|
||||
|
@ -1364,6 +1365,13 @@ glsl_init_common (rua_ctx_t *ctx)
|
|||
static module_t module; //FIXME probably not what I want
|
||||
pr.module = &module;
|
||||
|
||||
spirv_set_addressing_model (pr.module, SpvAddressingModelLogical);
|
||||
spirv_set_memory_model (pr.module, SpvMemoryModelGLSL450);
|
||||
|
||||
glsl_sublang = *(glsl_sublang_t *) ctx->language->sublanguage;
|
||||
|
||||
current_target.create_entry_point ("main", glsl_sublang.model_name);
|
||||
|
||||
make_structure ("@image", 's', glsl_image_struct, &type_glsl_image);
|
||||
make_structure ("@sampled_image", 's', glsl_sampled_image_struct,
|
||||
&type_glsl_sampled_image);
|
||||
|
@ -1374,10 +1382,6 @@ glsl_init_common (rua_ctx_t *ctx)
|
|||
|
||||
DARRAY_RESIZE (&glsl_imageset, 0);
|
||||
|
||||
spirv_set_addressing_model (pr.module, SpvAddressingModelLogical);
|
||||
spirv_set_memory_model (pr.module, SpvMemoryModelGLSL450);
|
||||
|
||||
glsl_sublang = *(glsl_sublang_t *) ctx->language->sublanguage;
|
||||
ctx->language->initialized = true;
|
||||
glsl_block_clear ();
|
||||
rua_ctx_t rua_ctx = { .language = &lang_ruamoko };
|
||||
|
@ -1410,8 +1414,6 @@ glsl_init_vert (rua_ctx_t *ctx)
|
|||
glsl_parse_vars (glsl_Vulkan_vertex_vars, ctx);
|
||||
rua_ctx_t rua_ctx = { .language = &lang_ruamoko };
|
||||
qc_parse_string (glsl_other_texture_functions, &rua_ctx);
|
||||
|
||||
pr.module->default_model = SpvExecutionModelVertex;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1423,7 +1425,6 @@ glsl_init_tesc (rua_ctx_t *ctx)
|
|||
qc_parse_string (glsl_other_texture_functions, &rua_ctx);
|
||||
|
||||
spirv_add_capability (pr.module, SpvCapabilityTessellation);
|
||||
pr.module->default_model = SpvExecutionModelTessellationControl;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1435,7 +1436,6 @@ glsl_init_tese (rua_ctx_t *ctx)
|
|||
qc_parse_string (glsl_other_texture_functions, &rua_ctx);
|
||||
|
||||
spirv_add_capability (pr.module, SpvCapabilityTessellation);
|
||||
pr.module->default_model = SpvExecutionModelTessellationEvaluation;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1448,7 +1448,6 @@ glsl_init_geom (rua_ctx_t *ctx)
|
|||
qc_parse_string (glsl_other_texture_functions, &rua_ctx);
|
||||
|
||||
spirv_add_capability (pr.module, SpvCapabilityGeometry);
|
||||
pr.module->default_model = SpvExecutionModelGeometry;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1459,6 +1458,4 @@ glsl_init_frag (rua_ctx_t *ctx)
|
|||
rua_ctx_t rua_ctx = { .language = &lang_ruamoko };
|
||||
qc_parse_string (glsl_fragment_functions, &rua_ctx);
|
||||
qc_parse_string (glsl_frag_texture_functions, &rua_ctx);
|
||||
|
||||
pr.module->default_model = SpvExecutionModelFragment;
|
||||
}
|
||||
|
|
|
@ -39,21 +39,57 @@
|
|||
#include "tools/qfcc/include/def.h"
|
||||
#include "tools/qfcc/include/diagnostic.h"
|
||||
#include "tools/qfcc/include/glsl-lang.h"
|
||||
#include "tools/qfcc/include/qfcc.h"
|
||||
#include "tools/qfcc/include/shared.h"
|
||||
#include "tools/qfcc/include/spirv.h"
|
||||
#include "tools/qfcc/include/strpool.h"
|
||||
#include "tools/qfcc/include/symtab.h"
|
||||
#include "tools/qfcc/include/type.h"
|
||||
#include "tools/qfcc/include/value.h"
|
||||
|
||||
typedef enum {
|
||||
decl_var = 1 << 0,
|
||||
decl_qual = 1 << 1,
|
||||
decl_block = 1 << 2,
|
||||
decl_member = 1 << 3,
|
||||
} glsl_obj_t;
|
||||
|
||||
typedef enum {
|
||||
var_any,
|
||||
var_opaque,
|
||||
var_atomic,
|
||||
var_subpass,
|
||||
var_scalar,
|
||||
var_image,
|
||||
var_gl_FragCoord,
|
||||
var_gl_FragDepth,
|
||||
} glsl_var_t;
|
||||
|
||||
typedef struct layout_qual_s layout_qual_t;
|
||||
typedef struct layout_qual_s {
|
||||
const char *name;
|
||||
void (*apply) (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name);
|
||||
void (*apply_expr) (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val);
|
||||
unsigned obj_mask;
|
||||
glsl_var_t var_type;
|
||||
unsigned if_mask;
|
||||
const char **stage_filter;
|
||||
int val;
|
||||
const char *accessor;
|
||||
} layout_qual_t;
|
||||
|
||||
static void
|
||||
glsl_layout_invalid_A (specifier_t spec, const expr_t *qual_name)
|
||||
glsl_layout_invalid_A (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name)
|
||||
{
|
||||
error (qual_name, "not allowed for vulkan");
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_invalid_E (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
glsl_layout_invalid_E (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
error (qual_name, "not allowed for vulkan");
|
||||
}
|
||||
|
@ -73,26 +109,22 @@ set_attribute (attribute_t **attributes, const char *name, const expr_t *val)
|
|||
}
|
||||
|
||||
static void
|
||||
glsl_layout_packing (specifier_t spec, const expr_t *qual_name)
|
||||
glsl_layout_packing (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_location (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
glsl_layout_location (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
const char *name = expr_string (qual_name);
|
||||
set_attribute (&spec.sym->attributes, name, val);
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_geom_in_primitive (specifier_t spec, const expr_t *qual_name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_constant_id (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
glsl_layout_constant_id (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
if (spec.sym->sy_type == sy_const) {
|
||||
auto expr = new_value_expr (spec.sym->value, false);
|
||||
|
@ -115,96 +147,107 @@ glsl_layout_constant_id (specifier_t spec, const expr_t *qual_name,
|
|||
}
|
||||
|
||||
static void
|
||||
glsl_layout_binding (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
glsl_layout_binding (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
const char *name = expr_string (qual_name);
|
||||
set_attribute (&spec.sym->attributes, name, val);
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_offset (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
glsl_layout_offset (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_set (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
glsl_layout_set (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
const char *name = expr_string (qual_name);
|
||||
set_attribute (&spec.sym->attributes, name, val);
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_set_property (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
{
|
||||
//auto interface = glsl_iftype_from_sc (spec.storage);
|
||||
//notice (qual_name, "%s %s %s", glsl_interface_names[interface],
|
||||
// expr_string (qual_name), get_value_string (val->value));
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_geom_out_primitive (specifier_t spec, const expr_t *qual_name)
|
||||
glsl_layout_format (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_geom_out_max_vertices (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
glsl_layout_push_constant (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_format (specifier_t spec, const expr_t *qual_name)
|
||||
glsl_layout_input_attachment_index (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_push_constant (specifier_t spec, const expr_t *qual_name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_input_attachment_index (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_execution_mode (specifier_t spec, const expr_t *qual_name)
|
||||
{
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
decl_var = 1 << 0,
|
||||
decl_qual = 1 << 1,
|
||||
decl_block = 1 << 2,
|
||||
decl_member = 1 << 3,
|
||||
} glsl_obj_t;
|
||||
|
||||
typedef enum {
|
||||
var_any,
|
||||
var_opaque,
|
||||
var_atomic,
|
||||
var_subpass,
|
||||
var_scalar,
|
||||
var_image,
|
||||
var_gl_FragCoord,
|
||||
var_gl_FragDepth,
|
||||
} glsl_var_t;
|
||||
|
||||
typedef struct layout_qual_s {
|
||||
#define EP(n) {.name = #n, .offset = offsetof (entrypoint_t, n)}
|
||||
#define EPF(n) {.name = #n, .offset = offsetof (entrypoint_t, n), .flag = true}
|
||||
static struct {
|
||||
const char *name;
|
||||
void (*apply) (specifier_t spec, const expr_t *qual_name);
|
||||
void (*apply_expr) (specifier_t spec, const expr_t *qual_name,
|
||||
const expr_t *val);
|
||||
unsigned obj_mask;
|
||||
glsl_var_t var_type;
|
||||
unsigned if_mask;
|
||||
const char **stage_filter;
|
||||
} layout_qual_t;
|
||||
int offset;
|
||||
bool flag;
|
||||
} entrypoint_fields[] = {
|
||||
EP (invocations),
|
||||
EP (local_size[0]),
|
||||
EP (local_size[1]),
|
||||
EP (local_size[2]),
|
||||
EP (primitive_in),
|
||||
EP (primitive_out),
|
||||
EP (max_vertices),
|
||||
EP (spacing),
|
||||
EP (order),
|
||||
EP (frag_depth),
|
||||
EPF (point_mode),
|
||||
EPF (early_fragment_tests),
|
||||
{}
|
||||
};
|
||||
#undef EP
|
||||
|
||||
static void
|
||||
glsl_layout_exec_mode_param (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name, const expr_t *val)
|
||||
{
|
||||
auto entry_point = pr.module->entry_points;
|
||||
if (!entry_point) {
|
||||
internal_error (0, "no entry point");
|
||||
}
|
||||
for (auto ep = entrypoint_fields; ep->name; ep++) {
|
||||
if (strcmp (ep->name, qual->accessor) == 0) {
|
||||
auto val_ptr = ((byte *) entry_point + ep->offset);
|
||||
if (ep->flag) {
|
||||
auto flag = (bool *) val_ptr;
|
||||
*flag = true;
|
||||
} else {
|
||||
auto expr = (const expr_t **) val_ptr;
|
||||
*expr = val;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
internal_error (0, "invalid accessor: %s", qual->accessor);
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_exec_mode (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name)
|
||||
{
|
||||
auto val = new_int_expr (qual->val, false);
|
||||
glsl_layout_exec_mode_param (qual, spec, qual_name, val);
|
||||
}
|
||||
|
||||
static void
|
||||
glsl_layout_ignore (const layout_qual_t *qual, specifier_t spec,
|
||||
const expr_t *qual_name)
|
||||
{
|
||||
const char *name = expr_string (qual_name);
|
||||
debug (qual_name, "ignoring %s", name);
|
||||
}
|
||||
|
||||
#define A(a) a, nullptr
|
||||
#define E(e) nullptr, e
|
||||
|
@ -314,100 +357,130 @@ static layout_qual_t layout_qualifiers[] = {
|
|||
},
|
||||
|
||||
{ .name = "triangles",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeTriangles,
|
||||
.accessor = "primitive_out",
|
||||
},
|
||||
{ .name = "quads",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeQuads,
|
||||
.accessor = "primitive_out",
|
||||
},
|
||||
{ .name = "isolines",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeIsolines,
|
||||
.accessor = "primitive_out",
|
||||
},
|
||||
{ .name = "equal_spacing",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeSpacingEqual,
|
||||
.accessor = "spacing",
|
||||
},
|
||||
{ .name = "fractional_even_spacing",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeSpacingFractionalEven,
|
||||
.accessor = "spacing",
|
||||
},
|
||||
{ .name = "fractional_odd_spacing",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeSpacingFractionalOdd,
|
||||
.accessor = "spacing",
|
||||
},
|
||||
{ .name = "cw",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeVertexOrderCw,
|
||||
.accessor = "order",
|
||||
},
|
||||
{ .name = "ccw",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = SpvExecutionModeVertexOrderCcw,
|
||||
.accessor = "order",
|
||||
},
|
||||
{ .name = "point_mode",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||
.val = true,
|
||||
.accessor = "point_mode",
|
||||
},
|
||||
|
||||
{ .name = "points",
|
||||
.apply = A(glsl_layout_geom_in_primitive),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in)|I(out),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeInputPoints,
|
||||
.accessor = "primitive_in",
|
||||
},
|
||||
{ .name = "lines",
|
||||
.apply = A(glsl_layout_geom_in_primitive),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeInputLines,
|
||||
.accessor = "primitive_in",
|
||||
},
|
||||
{ .name = "lines_adjacency",
|
||||
.apply = A(glsl_layout_geom_in_primitive),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeInputLinesAdjacency,
|
||||
.accessor = "primitive_in",
|
||||
},
|
||||
{ .name = "triangles",
|
||||
.apply = A(glsl_layout_geom_in_primitive),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeTriangles,
|
||||
.accessor = "primitive_in",
|
||||
},
|
||||
{ .name = "triangles_adjacency",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeInputTrianglesAdjacency,
|
||||
.accessor = "primitive_in",
|
||||
},
|
||||
{ .name = "invocations",
|
||||
.apply = E(nullptr),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.accessor = "invocations",
|
||||
},
|
||||
|
||||
{ .name = "origin_upper_left",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_ignore),
|
||||
.obj_mask = D(qual),
|
||||
.var_type = V(gl_FragCoord),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "fragment", nullptr },
|
||||
},
|
||||
|
@ -418,47 +491,55 @@ static layout_qual_t layout_qualifiers[] = {
|
|||
.stage_filter = C { "fragment", nullptr },
|
||||
},
|
||||
{ .name = "early_fragment_tests",
|
||||
.apply = A(glsl_layout_execution_mode),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "fragment", nullptr },
|
||||
.val = true,
|
||||
.accessor = "early_fragment_tests",
|
||||
},
|
||||
|
||||
{ .name = "local_size_x",
|
||||
.apply = E(glsl_layout_set_property),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "compute", nullptr },
|
||||
.accessor = "local_size[0]",
|
||||
},
|
||||
{ .name = "local_size_y",
|
||||
.apply = E(glsl_layout_set_property),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "compute", nullptr },
|
||||
.accessor = "local_size[1]",
|
||||
},
|
||||
{ .name = "local_size_z",
|
||||
.apply = E(glsl_layout_set_property),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "compute", nullptr },
|
||||
.accessor = "local_size[2]",
|
||||
},
|
||||
{ .name = "local_size_x_id",
|
||||
.apply = E(glsl_layout_set_property),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "compute", nullptr },
|
||||
.accessor = "local_size[0]",
|
||||
},
|
||||
{ .name = "local_size_y_id",
|
||||
.apply = E(glsl_layout_set_property),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "compute", nullptr },
|
||||
.accessor = "local_size[1]",
|
||||
},
|
||||
{ .name = "local_size_z_id",
|
||||
.apply = E(glsl_layout_set_property),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(in),
|
||||
.stage_filter = C { "compute", nullptr },
|
||||
.accessor = "local_size[2]",
|
||||
},
|
||||
|
||||
{ .name = "xfb_buffer",
|
||||
|
@ -502,35 +583,43 @@ static layout_qual_t layout_qualifiers[] = {
|
|||
},
|
||||
|
||||
{ .name = "vertices",
|
||||
.apply = E(nullptr),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "tessellation control", nullptr },
|
||||
.accessor = "max_vertices",
|
||||
},
|
||||
|
||||
{ .name = "points",
|
||||
.apply = A(glsl_layout_geom_out_primitive),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeOutputPoints,
|
||||
.accessor = "primitive_out",
|
||||
},
|
||||
{ .name = "line_strip",
|
||||
.apply = A(glsl_layout_geom_out_primitive),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeOutputLineStrip,
|
||||
.accessor = "primitive_out",
|
||||
},
|
||||
{ .name = "triangle_strip",
|
||||
.apply = A(glsl_layout_geom_out_primitive),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.val = SpvExecutionModeOutputTriangleStrip,
|
||||
.accessor = "primitive_out",
|
||||
},
|
||||
{ .name = "max_vertices",
|
||||
.apply = E(glsl_layout_geom_out_max_vertices),
|
||||
.apply = E(glsl_layout_exec_mode_param),
|
||||
.obj_mask = D(qual),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "geometry", nullptr },
|
||||
.accessor = "max_vertices",
|
||||
},
|
||||
{ .name = "stream",
|
||||
.apply = E(nullptr),
|
||||
|
@ -541,32 +630,40 @@ static layout_qual_t layout_qualifiers[] = {
|
|||
},
|
||||
|
||||
{ .name = "depth_any",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(var),
|
||||
.var_type = V(any),
|
||||
.var_type = V(gl_FragDepth),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "fragment", nullptr },
|
||||
.val = SpvExecutionModeDepthReplacing,
|
||||
.accessor = "frag_depth",
|
||||
},
|
||||
{ .name = "depth_greater",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(var),
|
||||
.var_type = V(any),
|
||||
.var_type = V(gl_FragDepth),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "fragment", nullptr },
|
||||
.val = SpvExecutionModeDepthGreater,
|
||||
.accessor = "frag_depth",
|
||||
},
|
||||
{ .name = "depth_less",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(var),
|
||||
.var_type = V(any),
|
||||
.var_type = V(gl_FragDepth),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "fragment", nullptr },
|
||||
.val = SpvExecutionModeDepthLess,
|
||||
.accessor = "frag_depth",
|
||||
},
|
||||
{ .name = "depth_unchanged",
|
||||
.apply = A(nullptr),
|
||||
.apply = A(glsl_layout_exec_mode),
|
||||
.obj_mask = D(var),
|
||||
.var_type = V(any),
|
||||
.var_type = V(gl_FragDepth),
|
||||
.if_mask = I(out),
|
||||
.stage_filter = C { "fragment", nullptr },
|
||||
.val = SpvExecutionModeDepthUnchanged,
|
||||
.accessor = "frag_depth",
|
||||
},
|
||||
|
||||
{ .name = "constant_id",
|
||||
|
@ -953,14 +1050,14 @@ layout_apply_qualifier (const expr_t *qualifier, specifier_t spec)
|
|||
if (!val) {
|
||||
error (qualifier, "%s requires a value", key.name);
|
||||
} else {
|
||||
qual->apply_expr (spec, qualifier->expr.e1, val);
|
||||
qual->apply_expr (qual, spec, qualifier->expr.e1, val);
|
||||
}
|
||||
return;
|
||||
} else if (qual->apply) {
|
||||
if (val) {
|
||||
error (qualifier, "%s does not take a value", key.name);
|
||||
} else {
|
||||
qual->apply (spec, qualifier->expr.e1);
|
||||
qual->apply (qual, spec, qualifier->expr.e1);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -50,4 +50,5 @@ static const char *glsl_comp_interface_default_names[glsl_num_interfaces] = {
|
|||
glsl_sublang_t glsl_comp_sublanguage = {
|
||||
.name = "compute",
|
||||
.interface_default_names = glsl_comp_interface_default_names,
|
||||
.model_name = "GLCompute",
|
||||
};
|
||||
|
|
|
@ -48,4 +48,5 @@ static const char *glsl_frag_interface_default_names[glsl_num_interfaces] = {
|
|||
glsl_sublang_t glsl_frag_sublanguage = {
|
||||
.name = "fragment",
|
||||
.interface_default_names = glsl_frag_interface_default_names,
|
||||
.model_name = "Fragment",
|
||||
};
|
||||
|
|
|
@ -52,4 +52,5 @@ static const char *glsl_geom_interface_default_names[glsl_num_interfaces] = {
|
|||
glsl_sublang_t glsl_geom_sublanguage = {
|
||||
.name = "geometry",
|
||||
.interface_default_names = glsl_geom_interface_default_names,
|
||||
.model_name = "Geometry",
|
||||
};
|
||||
|
|
|
@ -50,4 +50,5 @@ static const char *glsl_tesc_interface_default_names[glsl_num_interfaces] = {
|
|||
glsl_sublang_t glsl_tesc_sublanguage = {
|
||||
.name = "tessellation control",
|
||||
.interface_default_names = glsl_tesc_interface_default_names,
|
||||
.model_name = "TessellationControl",
|
||||
};
|
||||
|
|
|
@ -50,4 +50,5 @@ static const char *glsl_tese_interface_default_names[glsl_num_interfaces] = {
|
|||
glsl_sublang_t glsl_tese_sublanguage = {
|
||||
.name = "tessellation evaluation",
|
||||
.interface_default_names = glsl_tese_interface_default_names,
|
||||
.model_name = "TessellationEvaluation",
|
||||
};
|
||||
|
|
|
@ -50,4 +50,5 @@ static const char *glsl_vert_interface_default_names[glsl_num_interfaces] = {
|
|||
glsl_sublang_t glsl_vert_sublanguage = {
|
||||
.name = "vertex",
|
||||
.interface_default_names = glsl_vert_interface_default_names,
|
||||
.model_name = "Vertex",
|
||||
};
|
||||
|
|
|
@ -3274,7 +3274,7 @@ static void
|
|||
rua_init (rua_ctx_t *ctx)
|
||||
{
|
||||
ctx->language->initialized = true;
|
||||
if (options.code.spirv) {
|
||||
if (options.code.spirv && !pr.module) {
|
||||
static module_t module; //FIXME probably not what I want
|
||||
pr.module = &module;
|
||||
|
||||
|
|
|
@ -424,31 +424,14 @@ build_grammars (void)
|
|||
}
|
||||
}
|
||||
|
||||
const plitem_t *
|
||||
spirv_operand_kind (const char *set, const char *kind)
|
||||
{
|
||||
if (!built) {
|
||||
build_grammars ();
|
||||
built = true;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint32_t
|
||||
spirv_instruction_opcode (const char *set, const expr_t *opcode)
|
||||
static spirv_grammar_t *
|
||||
find_grammar (const char *set)
|
||||
{
|
||||
if (!built) {
|
||||
build_grammars ();
|
||||
built = true;
|
||||
}
|
||||
|
||||
if (is_integral_val (opcode)) {
|
||||
return expr_integral (opcode);
|
||||
}
|
||||
if (opcode->type != ex_symbol) {
|
||||
error (opcode, "not a an integer constant or symbol");
|
||||
return 0;
|
||||
}
|
||||
spirv_grammar_t *grammar = nullptr;
|
||||
for (int i = 0; builtin_json[i].name; i++) {
|
||||
if (strcmp (builtin_json[i].name, set) == 0) {
|
||||
|
@ -456,6 +439,28 @@ spirv_instruction_opcode (const char *set, const expr_t *opcode)
|
|||
break;
|
||||
}
|
||||
}
|
||||
return grammar;
|
||||
}
|
||||
|
||||
const plitem_t *
|
||||
spirv_operand_kind (const char *set, const char *kind)
|
||||
{
|
||||
find_grammar (set);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
spirv_instruction_opcode (const char *set, const expr_t *opcode)
|
||||
{
|
||||
if (is_integral_val (opcode)) {
|
||||
return expr_integral (opcode);
|
||||
}
|
||||
if (opcode->type != ex_symbol) {
|
||||
error (opcode, "not a an integer constant or symbol");
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto grammar = find_grammar (set);
|
||||
if (!grammar) {
|
||||
error (opcode, "unrecognized grammar set %s", set);
|
||||
return 0;
|
||||
|
@ -518,18 +523,8 @@ spirv_intrinsic_symbol (const char *name, symtab_t *symtab)
|
|||
bool
|
||||
spirv_setup_intrinsic_symtab (symtab_t *symtab)
|
||||
{
|
||||
if (!built) {
|
||||
build_grammars ();
|
||||
built = true;
|
||||
}
|
||||
const char *set = "core";
|
||||
spirv_grammar_t *grammar = nullptr;
|
||||
for (int i = 0; builtin_json[i].name; i++) {
|
||||
if (strcmp (builtin_json[i].name, set) == 0) {
|
||||
grammar = builtin_json[i].grammar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto grammar = find_grammar (set);
|
||||
if (!grammar) {
|
||||
error (0, "unrecognized grammar set %s", set);
|
||||
return false;
|
||||
|
@ -538,3 +533,26 @@ spirv_setup_intrinsic_symtab (symtab_t *symtab)
|
|||
symtab->procsymbol_data = grammar;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
spirv_execution_model (const char *model)
|
||||
{
|
||||
const char *set = "core";
|
||||
auto grammar = find_grammar (set);
|
||||
if (!grammar) {
|
||||
error (0, "unrecognized grammar set %s", set);
|
||||
return false;
|
||||
}
|
||||
symtab_t symtab = { .procsymbol_data = grammar };
|
||||
auto model_enum = spirv_intrinsic_symbol ("ExecutionModel", &symtab);
|
||||
if (!model_enum) {
|
||||
error (0, "ExecutionModel not found");
|
||||
return 0;
|
||||
}
|
||||
auto model_val = symtab_lookup (model_enum->namespace, model);
|
||||
if (!model_val) {
|
||||
error (0, "Execution model %s not found", model);
|
||||
return 0;
|
||||
}
|
||||
return model_val->value->uint_val;
|
||||
}
|
||||
|
|
|
@ -837,6 +837,63 @@ spirv_EntryPoint (entrypoint_t *entrypoint, spirvctx_t *ctx)
|
|||
}
|
||||
|
||||
auto exec_modes = ctx->module->exec_modes;
|
||||
if (entrypoint->invocations) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 4, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = SpvExecutionModeInvocations;
|
||||
INSN (insn, 3) = expr_integral (entrypoint->invocations);
|
||||
}
|
||||
// assume that if 1 is set, all are set
|
||||
if (entrypoint->local_size[0]) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 6, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
//FIXME LocalSizeId
|
||||
INSN (insn, 2) = SpvExecutionModeLocalSize;
|
||||
INSN (insn, 3) = expr_integral (entrypoint->local_size[0]);
|
||||
INSN (insn, 4) = expr_integral (entrypoint->local_size[1]);
|
||||
INSN (insn, 5) = expr_integral (entrypoint->local_size[2]);
|
||||
}
|
||||
if (entrypoint->primitive_in) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = expr_integral (entrypoint->primitive_in);
|
||||
}
|
||||
if (entrypoint->primitive_out) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = expr_integral (entrypoint->primitive_out);
|
||||
}
|
||||
if (entrypoint->max_vertices) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 4, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = SpvExecutionModeOutputVertices;
|
||||
INSN (insn, 3) = expr_integral (entrypoint->max_vertices);
|
||||
}
|
||||
if (entrypoint->spacing) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = expr_integral (entrypoint->spacing);
|
||||
}
|
||||
if (entrypoint->order) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = expr_integral (entrypoint->order);
|
||||
}
|
||||
if (entrypoint->frag_depth) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = expr_integral (entrypoint->frag_depth);
|
||||
}
|
||||
if (entrypoint->point_mode) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = SpvExecutionModePointMode;
|
||||
}
|
||||
if (entrypoint->early_fragment_tests) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
INSN (insn, 2) = SpvExecutionModeEarlyFragmentTests;
|
||||
}
|
||||
for (auto m = entrypoint->modes; m; m = m->next) {
|
||||
insn = spirv_new_insn (SpvOpExecutionMode, 3, exec_modes);
|
||||
INSN (insn, 1) = func_id;
|
||||
|
@ -2069,22 +2126,13 @@ static void
|
|||
spirv_build_code (function_t *func, const expr_t *statements)
|
||||
{
|
||||
func->exprs = statements;
|
||||
if (strcmp ("main", func->o_name) == 0) {
|
||||
attribute_t *mode = nullptr;
|
||||
if (pr.module->default_model == SpvExecutionModelFragment) {
|
||||
mode = new_attribute ("mode",
|
||||
new_int_expr (SpvExecutionModeOriginUpperLeft, false));
|
||||
for (auto ep = pr.module->entry_points; ep; ep = ep->next) {
|
||||
if (strcmp (ep->name, func->o_name) == 0) {
|
||||
if (ep->func && ep->func != func) {
|
||||
error (statements, "entry point %s redefined", ep->name);
|
||||
}
|
||||
ep->func = func;
|
||||
}
|
||||
entrypoint_t *ep = malloc (sizeof (entrypoint_t));
|
||||
*(ep) = (entrypoint_t) {
|
||||
.next = pr.module->entry_points,
|
||||
.model = pr.module->default_model,
|
||||
.name = "main",
|
||||
.modes = mode,
|
||||
.interface_syms = DARRAY_STATIC_INIT (16),
|
||||
.func = func,
|
||||
};
|
||||
pr.module->entry_points = ep;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2123,6 +2171,33 @@ spirv_declare_sym (specifier_t spec, const expr_t *init, symtab_t *symtab,
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
spirv_create_entry_point (const char *name, const char *model_name)
|
||||
{
|
||||
for (auto ep = pr.module->entry_points; ep; ep = ep->next) {
|
||||
if (strcmp (ep->name, name) == 0) {
|
||||
error (0, "entry point %s already exists", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
attribute_t *mode = nullptr;
|
||||
unsigned model = spirv_execution_model (model_name);
|
||||
if (model == SpvExecutionModelFragment) {
|
||||
mode = new_attribute ("mode",
|
||||
new_int_expr (SpvExecutionModeOriginUpperLeft, false));
|
||||
}
|
||||
entrypoint_t *ep = malloc (sizeof (entrypoint_t));
|
||||
*(ep) = (entrypoint_t) {
|
||||
.next = pr.module->entry_points,
|
||||
.model = model,
|
||||
.name = save_string (name),
|
||||
.modes = mode,
|
||||
.interface_syms = DARRAY_STATIC_INIT (16),
|
||||
};
|
||||
pr.module->entry_points = ep;
|
||||
return true;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
spirv_build_element_chain (element_chain_t *element_chain, const type_t *type,
|
||||
const expr_t *eles)
|
||||
|
@ -2274,6 +2349,7 @@ target_t spirv_target = {
|
|||
.build_scope = spirv_build_scope,
|
||||
.build_code = spirv_build_code,
|
||||
.declare_sym = spirv_declare_sym,
|
||||
.create_entry_point = spirv_create_entry_point,
|
||||
.initialized_temp = spirv_initialized_temp,
|
||||
.assign_vector = spirv_assign_vector,
|
||||
.setup_intrinsic_symtab = spirv_setup_intrinsic_symtab,
|
||||
|
|
Loading…
Reference in a new issue