diff --git a/tools/qfcc/include/glsl-lang.h b/tools/qfcc/include/glsl-lang.h index f4424b604..8d5622753 100644 --- a/tools/qfcc/include/glsl-lang.h +++ b/tools/qfcc/include/glsl-lang.h @@ -146,4 +146,7 @@ bool glsl_on_include (const char *name, rua_ctx_t *ctx); void glsl_include (int behavior, void *scanner); void glsl_multiview (int behavior, void *scanner); +symbol_t *glsl_image_type (glsl_image_t *image, const type_t *htype, + const char *name); + #endif//__glsl_lang_h diff --git a/tools/qfcc/source/glsl-layout.c b/tools/qfcc/source/glsl-layout.c index f192bec5f..701e3a60c 100644 --- a/tools/qfcc/source/glsl-layout.c +++ b/tools/qfcc/source/glsl-layout.c @@ -28,6 +28,7 @@ # include "config.h" #endif +#include #include #include "QF/alloc.h" @@ -182,10 +183,62 @@ glsl_layout_set (const layout_qual_t *qual, specifier_t spec, set_attribute (&spec.sym->attributes, name, val); } +static const type_t * +set_image_format (const type_t *type, const char *format) +{ + bool reference = false; + unsigned tag = 0; + if (is_reference (type)) { + reference = true; + tag = type->fldptr.tag; + type = dereference_type (type); + } + bool array = false; + int count = 0; + if (is_array (type)) { + array = true; + count = type_count (type); + type = dereference_type (type); + } + if (is_array (type)) { + type = set_image_format (type, format); + } else { + if (!is_handle (type) + && type->handle.type != &type_glsl_sampled_image + && type->handle.type != &type_glsl_image) { + internal_error (0, "not an image type"); + } + auto htype = type->handle.type; + auto image = glsl_imageset.a[type->handle.extra]; + if (image.format == SpvImageFormatUnknown) { + image.format = spirv_enum_val ("ImageFormat", format); + } else { + error (0, "format already set"); + } + int len = strlen (format); + char fmt[len + 1]; + for (int i = 0; i < len + 1; i++) { + fmt[i] = tolower (format[i]); + } + auto sym = glsl_image_type (&image, htype, va (0, ".image:%s", fmt)); + type = sym->type; + } + if (array) { + type = array_type (type, count); + } + if (reference) { + type = tagged_reference_type (tag, type); + } + return type; +} + static void glsl_layout_format (const layout_qual_t *qual, specifier_t spec, const expr_t *qual_name) { + auto type = spec.sym->type; + type = set_image_format (type, qual->name); + spec.sym->type = type; } static void diff --git a/tools/qfcc/source/glsl-parse.y b/tools/qfcc/source/glsl-parse.y index e735316c7..9ca375cb1 100644 --- a/tools/qfcc/source/glsl-parse.y +++ b/tools/qfcc/source/glsl-parse.y @@ -1639,6 +1639,41 @@ image_property (const type_t *type, const attribute_t *attr) return type->handle.type->property (type, attr); } +symbol_t * +glsl_image_type (glsl_image_t *image, const type_t *htype, const char *name) +{ + 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) { + if (!glsl_imageset.size) { + DARRAY_APPEND (&glsl_imageset, (glsl_image_t) { } ); + } + index = glsl_imageset.size; + DARRAY_APPEND (&glsl_imageset, *image); + } + + auto sym = new_symbol (name); + 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 already set"); + } + t->handle.type = htype; + t->handle.extra = index; + t->property = image_property; + sym->type = find_type (sym->type); + + return sym; +} + static symbol_t * glsl_parse_image (const char *token, rua_ctx_t *ctx) { @@ -1733,36 +1768,7 @@ glsl_parse_image (const char *token, rua_ctx_t *ctx) 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) { - if (!glsl_imageset.size) { - DARRAY_APPEND (&glsl_imageset, (glsl_image_t) { } ); - } - index = glsl_imageset.size; - DARRAY_APPEND (&glsl_imageset, image); - } - - auto sym = new_symbol (token); - sym = find_handle (sym, &type_int); - sym->type = find_type (sym->type); - //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 already set"); - } - t->handle.type = type.htype; - t->handle.extra = index; - t->property = image_property; - - return sym; + return glsl_image_type (&image, type.htype, token); invalid: internal_error (0, "invalid image type: %s", token); }