[qfcc] Extend handles to support image types

Images are just handles, but they have additional type data like
dimensionality, array, etc that distinguishes between the image types.
This commit is contained in:
Bill Currie 2024-11-21 08:33:29 +09:00
parent 03c47f8af7
commit c16a8411bc
6 changed files with 203 additions and 3 deletions

View file

@ -28,6 +28,8 @@
#ifndef __glsl_lang_h
#define __glsl_lang_h
#include "QF/darray.h"
typedef struct specifier_s specifier_t;
typedef struct attribute_s attribute_t;
typedef struct expr_s expr_t;
@ -78,6 +80,31 @@ typedef struct glsl_block_s {
symbol_t *instance_name;
} glsl_block_t;
typedef enum {
glid_1d,
glid_2d,
glid_3d,
glid_cube,
glid_rect,
glid_buffer,
glid_subpassdata,
} glsl_imagedim_t;
typedef struct glsl_image_s {
const type_t *sample_type;
glsl_imagedim_t dim;
char depth;
bool arrayed;
bool multisample;
char sampled;
unsigned format;
} glsl_image_t;
typedef struct DARRAY_TYPE (glsl_image_t) glsl_imageset_t;
extern glsl_imageset_t glsl_imageset;
extern type_t type_glsl_image;
extern type_t type_glsl_sampler;
typedef struct glsl_sublang_s {
const char *name;
const char **interface_default_names;

View file

@ -68,4 +68,6 @@ struct def_s * emit_structure (const char *name, int su, struct_def_t *defs,
struct defspace_s *space,
enum storage_class_e storage);
struct symbol_s *make_handle (const char *name, type_t *type);
#endif//__struct_h

View file

@ -68,6 +68,11 @@ typedef struct ty_alias_s {
const struct type_s *full_type; ///< full alias chain
} ty_alias_t;
typedef struct ty_handle_s {
const type_t *type; ///< descriptor for extra
unsigned extra; ///< handle for extra
} ty_handle_t;
typedef struct type_s {
etype_t type; ///< ev_invalid means structure/array etc
unsigned id; ///< internal id for registerd types
@ -90,6 +95,7 @@ typedef struct type_s {
struct algebra_s *algebra;
struct multivector_s *multivec;
ty_alias_t alias;
ty_handle_t handle;
};
attribute_t *attributes;
struct type_s *next;

View file

@ -33,6 +33,30 @@
#include "tools/qfcc/include/qfcc.h"
#include "tools/qfcc/include/rua-lang.h"
#include "tools/qfcc/include/spirv.h"
#include "tools/qfcc/include/struct.h"
#include "tools/qfcc/include/type.h"
glsl_imageset_t glsl_imageset = DARRAY_STATIC_INIT (16);
static struct_def_t glsl_image_struct[] = {
{"type", &type_ptr},
{"dim", &type_uint}, //FIXME enum
{"depth", &type_uint}, //FIXME enum
{"arrayed", &type_bool},
{"multisample", &type_bool},
{"sampled", &type_uint}, //FIXME enum
{"format", &type_uint}, //FIXME enum
{}
};
type_t type_glsl_image = {
.type = ev_invalid,
.meta = ty_struct,
};
type_t type_glsl_sampler = {
.type = ev_int,
.meta = ty_handle,
};
#define SRC_LINE_EXP2(l,f) "#line " #l " " #f "\n"
#define SRC_LINE_EXP(l,f) SRC_LINE_EXP2(l,f)
@ -921,6 +945,13 @@ glsl_init_common (void)
static module_t module; //FIXME probably not what I want
pr.module = &module;
make_structure ("@image", 's', glsl_image_struct, &type_glsl_image);
make_handle ("@sampler", &type_glsl_sampler);
chain_type (&type_glsl_image);
chain_type (&type_glsl_sampler);
DARRAY_RESIZE (&glsl_imageset, 0);
spirv_set_addressing_model (pr.module, SpvAddressingModelLogical);
spirv_set_memory_model (pr.module, SpvMemoryModelGLSL450);

View file

@ -1554,7 +1554,7 @@ static keyword_t glsl_keywords[] = {
{"textureBuffer", GLSL_TYPE_SPEC},
{"itextureBuffer", GLSL_TYPE_SPEC},
{"utextureBuffer", GLSL_TYPE_SPEC},
{"sampler", GLSL_TYPE_SPEC},
{"sampler", GLSL_TYPE_SPEC, .spec = {.type = &type_glsl_sampler}},
{"samplerShadow", GLSL_TYPE_SPEC},
{"subpassInput", GLSL_TYPE_SPEC},
{"isubpassInput", GLSL_TYPE_SPEC},
@ -1635,14 +1635,141 @@ glsl_directive (const char *token)
return directive;
}
typedef struct {
const char *substr;
int val;
const type_t *type;
} image_sub_t;
static image_sub_t * __attribute__((pure))
find_image_sub (image_sub_t *sub, const char *str)
{
for (; sub->substr; sub++) {
if (strncmp (sub->substr, str, strlen(sub->substr)) == 0) {
return sub;
}
}
return nullptr;
}
static symbol_t *
glsl_parse_image (const char *token)
{
static image_sub_t image_type[] = {
{ .substr = "sampler", .val = 0, .type = &type_float },
{ .substr = "image", .val = 1, .type = &type_float },
{ .substr = "texture", .val = 2, .type = &type_float },
{ .substr = "isampler", .val = 0, .type = &type_int },
{ .substr = "iimage", .val = 1, .type = &type_int },
{ .substr = "itexture", .val = 2, .type = &type_int },
{ .substr = "usampler", .val = 0, .type = &type_uint },
{ .substr = "uimage", .val = 1, .type = &type_uint },
{ .substr = "utexture", .val = 2, .type = &type_uint },
{ .substr = "i", .val = 1, .type = &type_int },
{ .substr = "u", .val = 1, .type = &type_uint },
{ .substr = "", .val = 1, .type = &type_float },
// subpassInput is dimension in spir-v
{}
};
static image_sub_t image_dim[] = {
{ "2DRect", glid_rect }, // so 2D doesn't falsly match
{ "1D", glid_1d },
{ "2D", glid_2d },
{ "3D", glid_3d },
{ "Cube", glid_cube },
{ "Buffer", glid_buffer },
{ "subpassInput", glid_subpassdata },
{}
};
static image_sub_t image_ms[] = {
{ "MS", true },
{ "", false },
{}
};
static image_sub_t image_array[] = {
{ "Array", true },
{ "", false },
{}
};
static image_sub_t image_shadow[] = {
{ "Shadow", true },
{ "", false },
{}
};
int offset = 0;
auto type = *find_image_sub (image_type, token + offset);// always succeeds
offset += strlen (type.substr);
auto dim = find_image_sub (image_dim, token + offset);
if (!dim) {
goto invalid;
}
offset += strlen (dim->substr);
if (!is_float (type.type)) {
type.substr++; // skip over type char
}
if (dim->val == glid_subpassdata) {
type.substr = dim->substr;
}
auto ms = *find_image_sub (image_ms, token + offset);
offset += strlen (ms.substr);
auto array = *find_image_sub (image_array, token + offset);
offset += strlen (array.substr);
glsl_image_t image = {
.sample_type = type.type,
.dim = dim->val,
.depth = 0, //XXX what sets this?
.arrayed = array.val,
.multisample = ms.val,
.format = 0, //unknown (comes from layout)
};
if (type.val == 0) { // sampler
auto shad = *find_image_sub (image_shadow, token + offset);
offset += strlen (shad.substr);
if (shad.val) {
type.substr = "samplerShadow";
}
}
if (token[offset]) {
goto invalid;
}
unsigned index = 0;
// slot 0 is never used
for (unsigned i = 1; i < glsl_imageset.size; i++) {
if (memcmp (&glsl_imageset.a[i], &image, sizeof (image)) == 0) {
index = i;
break;
}
}
if (!index) {
index = glsl_imageset.size;
DARRAY_APPEND (&glsl_imageset, image);
}
auto sym = new_symbol (token);
sym = find_handle (sym, &type_int);
//FIXME the type isn't chained yet and so doesn't need to be const, but
// symbols keep the type in a const pointer.
auto t = (type_t *) sym->type;
if (t->handle.extra) {
internal_error (0, "image type handle alread set");
}
t->handle.extra = index;
return sym;
invalid:
internal_error (0, "invalid image type: %s", token);
}
static int
glsl_process_keyword (rua_val_t *lval, keyword_t *keyword, const char *token)
{
if (keyword->value == GLSL_STRUCT) {
lval->op = token[0];
} else if (keyword->value == GLSL_TYPE_SPEC && !keyword->spec.type) {
auto sym = new_symbol (token);
sym = find_handle (sym, &type_int);
auto sym = glsl_parse_image (token);
keyword->spec.type = sym->type;
lval->spec = keyword->spec;
} else if (keyword->use_name) {

View file

@ -441,3 +441,10 @@ emit_structure (const char *name, int su, struct_def_t *defs,
}
return struct_def;
}
symbol_t *
make_handle (const char *name, type_t *type)
{
auto tag = new_symbol (name);
return find_tag (ty_handle, tag, type);
}