[qfcc] Make image handles independent of glsl

It has come time to get image handle type creation into Ruamoko. This
commit only gets the functions and types independent of glsl, @image (my
plan for dealing with the handles) isn't implemented yet.
This commit is contained in:
Bill Currie 2025-02-11 15:51:20 +09:00
parent c18d1b5629
commit 1c20316c9a
9 changed files with 401 additions and 301 deletions

View file

@ -20,6 +20,7 @@ EXTRA_DIST += \
tools/qfcc/include/glsl-lang.h \
tools/qfcc/include/grab.h \
tools/qfcc/include/idstuff.h \
tools/qfcc/include/image.h \
tools/qfcc/include/linker.h \
tools/qfcc/include/mat_types.h \
tools/qfcc/include/method.h \

View file

@ -84,37 +84,6 @@ typedef struct glsl_block_s {
symbol_t *instance_name;
} glsl_block_t;
typedef enum : unsigned {
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;
uint32_t id;
} glsl_image_t;
typedef struct glsl_sampled_image_s {
const type_t *image_type;
} glsl_sampled_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;
extern type_t type_glsl_sampled_image;
typedef struct glsl_sublang_s {
const char *name;
const char **interface_default_names;
@ -146,7 +115,4 @@ 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

View file

@ -0,0 +1,73 @@
/*
image.h
Ruamoko image support code
Copyright (C) 2025 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __image_h
#define __image_h
#include "QF/darray.h"
typedef struct type_s type_t;
typedef struct expr_s expr_t;
typedef struct symbol_s symbol_t;
typedef enum : unsigned {
img_1d,
img_2d,
img_3d,
img_cube,
img_rect,
img_buffer,
img_subpassdata,
} imagedim_t;
typedef struct image_s {
const type_t *sample_type;
imagedim_t dim;
char depth;
bool arrayed;
bool multisample;
char sampled;
unsigned format;
uint32_t id;
} image_t;
typedef struct sampled_image_s {
const type_t *image_type;
} sampled_image_t;
typedef struct DARRAY_TYPE (image_t) imageset_t;
extern imageset_t imageset;
extern type_t type_image;
extern type_t type_sampler;
extern type_t type_sampled_image;
void image_init_types (void);
symbol_t *named_image_type (image_t *image, const type_t *htype,
const char *name);
#endif//__image_h

View file

@ -59,6 +59,7 @@ qfcc_SOURCES = \
tools/qfcc/source/glsl-sub_vert.c \
tools/qfcc/source/grab.c \
tools/qfcc/source/idstuff.c \
tools/qfcc/source/image.c \
tools/qfcc/source/linker.c \
tools/qfcc/source/method.c \
tools/qfcc/source/obj_file.c \

View file

@ -38,6 +38,7 @@
#include "tools/qfcc/include/attribute.h"
#include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/glsl-lang.h"
#include "tools/qfcc/include/image.h"
#include "tools/qfcc/include/qfcc.h"
#include "tools/qfcc/include/rua-lang.h"
#include "tools/qfcc/include/spirv.h"
@ -47,184 +48,6 @@
#include "tools/qfcc/include/type.h"
glsl_sublang_t glsl_sublang;
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
{}
};
static struct_def_t glsl_sampled_image_struct[] = {
{"image_type", &type_ptr},
{}
};
static int dim_widths[7] = { 1, 2, 3, 3, 2, 1, 0 };
static int size_widths[7] = { 1, 2, 3, 2, 2, 1, 0 };
static int shadow_widths[7] = { 3, 3, 0, 4, 3, 0, 0 };
static const char *shadow_swizzle[7][2] = {
{ "x", "xy" },
{ "xy", "xyz" },
{},
{ "xyz", "xyzw" },
{ "xy", "xyz" },
{},
{},
};
static const char *shadow_comp_swizzle[7][2] = {
{ "z", "z" }, // glsl braindeadery for 1d (non-arrayed) images
{ "z", "w" },
{},
{ "w", "" }, // cubemap array shadows get comp from a param
{ "z", "w" },
{},
{},
};
static const expr_t *
image_property (const type_t *type, const attribute_t *property)
{
auto image = &glsl_imageset.a[type->handle.extra];
if (image->dim > glid_subpassdata) {
internal_error (0, "image has bogus dimension");
}
if (strcmp (property->name, "sample_type") == 0) {
return new_type_expr (image->sample_type);
} else if (strcmp (property->name, "image_coord") == 0) {
int width = dim_widths[image->dim];
if (image->dim == glid_subpassdata) {
width = 2;
}
if (!width) {
return new_type_expr (&type_void);
}
if (image->dim < glid_3d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_int, width));
} else if (strcmp (property->name, "size_type") == 0) {
int width = size_widths[image->dim];
if (!width) {
return new_type_expr (&type_void);
}
if (width < 3 && image->dim <= glid_cube) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_int, width));
}
return error (0, "no property %s on %s", property->name, type->name + 4);
}
static const expr_t *
sampled_shadow_swizzle (const attribute_t *property, const char *swizzle[7][2],
glsl_image_t *image)
{
int count = list_count (&property->params->list);
if (count != 1) {
return error (property->params, "wrong number of params");
}
const expr_t *params[count];
list_scatter (&property->params->list, params);
const char *swiz = swizzle[image->dim][image->arrayed];
if (!swiz) {
return error (property->params, "image does not support"
" shadow sampling");
}
if (!swiz[0]) {
// cube map array
return error (property->params, "cube map array shadow compare is not"
" in the coordinate vector");
}
if (strcmp (swiz, "xyzw") == 0) {
// no-op swizzle
return params[0];
}
if (!swiz[1]) {
auto ptype = get_type (params[0]);
auto member = new_name_expr (swiz);
auto field = get_struct_field (ptype, params[0], member);
if (!field) {
return error (params[0], "invalid shadow coord");
}
member = new_symbol_expr (field);
auto expr = new_field_expr (params[0], member);
expr->field.type = member->symbol->type;
return expr;
}
return new_swizzle_expr (params[0], swiz);
}
static const expr_t *
sampled_image_property (const type_t *type, const attribute_t *property)
{
auto image = &glsl_imageset.a[type->handle.extra];
if (image->dim > glid_subpassdata) {
internal_error (0, "image has bogus dimension");
}
if (strcmp (property->name, "tex_coord") == 0) {
int width = dim_widths[image->dim];
if (!width) {
return new_type_expr (&type_void);
}
if (image->dim < glid_3d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_float, width));
} else if (strcmp (property->name, "shadow_coord") == 0) {
if (property->params) {
return sampled_shadow_swizzle (property, shadow_swizzle, image);
} else {
int width = shadow_widths[image->dim];
if (!image->depth || !width) {
return new_type_expr (&type_void);
}
if (image->dim == glid_2d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_float, width));
}
} else if (strcmp (property->name, "comp") == 0) {
if (property->params) {
return sampled_shadow_swizzle (property, shadow_comp_swizzle,
image);
} else {
int width = shadow_widths[image->dim];
if (!image->depth || !width) {
return new_type_expr (&type_void);
}
if (image->dim == glid_2d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_float, width));
}
}
return image_property (type, property);
}
type_t type_glsl_image = {
.type = ev_invalid,
.meta = ty_struct,
.property = image_property,
};
type_t type_glsl_sampled_image = {
.type = ev_invalid,
.meta = ty_struct,
.property = sampled_image_property,
};
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)
@ -1449,15 +1272,7 @@ glsl_init_common (rua_ctx_t *ctx)
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);
make_handle ("@sampler", &type_glsl_sampler);
chain_type (&type_glsl_image);
chain_type (&type_glsl_sampler);
chain_type (&type_glsl_sampled_image);
DARRAY_RESIZE (&glsl_imageset, 0);
image_init_types ();
ctx->language->initialized = true;
glsl_block_clear ();

View file

@ -40,6 +40,7 @@
#include "tools/qfcc/include/def.h"
#include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/glsl-lang.h"
#include "tools/qfcc/include/image.h"
#include "tools/qfcc/include/qfcc.h"
#include "tools/qfcc/include/shared.h"
#include "tools/qfcc/include/spirv.h"
@ -204,12 +205,12 @@ set_image_format (const type_t *type, const char *format)
type = set_image_format (type, format);
} else {
if (!is_handle (type)
&& type->handle.type != &type_glsl_sampled_image
&& type->handle.type != &type_glsl_image) {
&& type->handle.type != &type_sampled_image
&& type->handle.type != &type_image) {
internal_error (0, "not an image type");
}
auto htype = type->handle.type;
auto image = glsl_imageset.a[type->handle.extra];
auto image = imageset.a[type->handle.extra];
if (image.format == SpvImageFormatUnknown) {
image.format = spirv_enum_val ("ImageFormat", format);
} else {
@ -220,7 +221,7 @@ set_image_format (const type_t *type, const char *format)
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));
auto sym = named_image_type (&image, htype, va (0, ".image:%s", fmt));
type = sym->type;
}
if (array) {
@ -1183,13 +1184,13 @@ layout_check_qualifier (const layout_qual_t *qual, specifier_t spec)
// images are opaque types, but certain qualifiers support
// only images and not other opaque types, but qualifiers that
// support opaque types in general also support images
glsl_image_t *image = nullptr;
//FIXME nicer type check (and remove glsl)
if (type->handle.type == &type_glsl_image) {
image = &glsl_imageset.a[type->handle.extra];
image_t *image = nullptr;
//FIXME nicer type check
if (type->handle.type == &type_image) {
image = &imageset.a[type->handle.extra];
}
if (qual->var_type != var_opaque && image) {
if (image->dim == glid_subpassdata) {
if (image->dim == img_subpassdata) {
var_type = var_subpass;
} else {
var_type = var_image;

View file

@ -67,6 +67,7 @@
#include "tools/qfcc/include/expr.h"
#include "tools/qfcc/include/function.h"
#include "tools/qfcc/include/glsl-lang.h"
#include "tools/qfcc/include/image.h"
#include "tools/qfcc/include/method.h"
#include "tools/qfcc/include/options.h"
#include "tools/qfcc/include/qfcc.h"
@ -1534,7 +1535,7 @@ static keyword_t glsl_keywords[] = {
{"textureBuffer", GLSL_TYPE_SPEC},
{"itextureBuffer", GLSL_TYPE_SPEC},
{"utextureBuffer", GLSL_TYPE_SPEC},
{"sampler", GLSL_TYPE_SPEC, .spec = {.type = &type_glsl_sampler}},
{"sampler", GLSL_TYPE_SPEC, .spec = {.type = &type_sampler}},
{"samplerShadow", GLSL_TYPE_SPEC},
{"subpassInput", GLSL_TYPE_SPEC},
{"isubpassInput", GLSL_TYPE_SPEC},
@ -1633,86 +1634,45 @@ find_image_sub (image_sub_t *sub, const char *str)
return nullptr;
}
static const expr_t *
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)
{
static image_sub_t image_type[] = {
static image_sub_t image_sub_type[] = {
{ .substr = "sampler", .val = 1, .type = &type_float,
.htype = &type_glsl_sampled_image },
.htype = &type_sampled_image },
{ .substr = "image", .val = 2, .type = &type_float,
.htype = &type_glsl_image },
.htype = &type_image },
{ .substr = "texture", .val = 1, .type = &type_float,
.htype = &type_glsl_image },
.htype = &type_image },
{ .substr = "isampler", .val = 1, .type = &type_int,
.htype = &type_glsl_sampled_image },
.htype = &type_sampled_image },
{ .substr = "iimage", .val = 2, .type = &type_int,
.htype = &type_glsl_image },
.htype = &type_image },
{ .substr = "itexture", .val = 1, .type = &type_int,
.htype = &type_glsl_image },
.htype = &type_image },
{ .substr = "usampler", .val = 1, .type = &type_uint,
.htype = &type_glsl_sampled_image },
.htype = &type_sampled_image },
{ .substr = "uimage", .val = 2, .type = &type_uint,
.htype = &type_glsl_image },
.htype = &type_image },
{ .substr = "utexture", .val = 1, .type = &type_uint,
.htype = &type_glsl_image },
.htype = &type_image },
// subpassInput is dimension in spir-v
{ .substr = "i", .val = 2, .type = &type_int,
.htype = &type_glsl_image },
.htype = &type_image },
{ .substr = "u", .val = 2, .type = &type_uint,
.htype = &type_glsl_image },
.htype = &type_image },
{ .substr = "", .val = 2, .type = &type_float,
.htype = &type_glsl_image },
.htype = &type_image },
{}
};
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 },
{ "2DRect", img_rect }, // so 2D doesn't falsly match
{ "1D", img_1d },
{ "2D", img_2d },
{ "3D", img_3d },
{ "Cube", img_cube },
{ "Buffer", img_buffer },
{ "subpassInput", img_subpassdata },
{}
};
static image_sub_t image_ms[] = {
@ -1732,7 +1692,8 @@ glsl_parse_image (const char *token, rua_ctx_t *ctx)
};
int offset = 0;
auto type = *find_image_sub (image_type, token + offset);// always succeeds
// always succeeds
auto type = *find_image_sub (image_sub_type, token + offset);
offset += strlen (type.substr);
auto dim = find_image_sub (image_dim, token + offset);
if (!dim) {
@ -1742,7 +1703,7 @@ glsl_parse_image (const char *token, rua_ctx_t *ctx)
if (!is_float (type.type)) {
type.substr++; // skip over type char
}
if (dim->val == glid_subpassdata) {
if (dim->val == img_subpassdata) {
type.substr = dim->substr;
}
auto ms = *find_image_sub (image_ms, token + offset);
@ -1750,7 +1711,7 @@ glsl_parse_image (const char *token, rua_ctx_t *ctx)
auto array = *find_image_sub (image_array, token + offset);
offset += strlen (array.substr);
glsl_image_t image = {
image_t image = {
.sample_type = type.type,
.dim = dim->val,
.depth = 0, //set below for shadow samplers
@ -1768,7 +1729,7 @@ glsl_parse_image (const char *token, rua_ctx_t *ctx)
goto invalid;
}
return glsl_image_type (&image, type.htype, token);
return named_image_type (&image, type.htype, token);
invalid:
internal_error (0, "invalid image type: %s", token);
}

281
tools/qfcc/source/image.c Normal file
View file

@ -0,0 +1,281 @@
/*
image.c
Ruamoko image support code
Copyright (C) 2025 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h>
#include <string.h>
#include "QF/darray.h"
#include "QF/dstring.h"
#include "QF/mathlib.h"
#include "QF/va.h"
#include "QF/math/bitop.h"
#include "tools/qfcc/include/attribute.h"
#include "tools/qfcc/include/expr.h"
#include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/image.h"
#include "tools/qfcc/include/struct.h"
#include "tools/qfcc/include/symtab.h"
#include "tools/qfcc/include/type.h"
imageset_t imageset = DARRAY_STATIC_INIT (16);
static struct_def_t 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
{}
};
static struct_def_t sampled_image_struct[] = {
{"image_type", &type_ptr},
{}
};
static int dim_widths[7] = { 1, 2, 3, 3, 2, 1, 0 };
static int size_widths[7] = { 1, 2, 3, 2, 2, 1, 0 };
static int shadow_widths[7] = { 3, 3, 0, 4, 3, 0, 0 };
static const char *shadow_swizzle[7][2] = {
{ "x", "xy" },
{ "xy", "xyz" },
{},
{ "xyz", "xyzw" },
{ "xy", "xyz" },
{},
{},
};
static const char *shadow_comp_swizzle[7][2] = {
{ "z", "z" }, // glsl braindeadery for 1d (non-arrayed) images
{ "z", "w" },
{},
{ "w", "" }, // cubemap array shadows get comp from a param
{ "z", "w" },
{},
{},
};
static const expr_t *
image_property (const type_t *type, const attribute_t *property)
{
auto image = &imageset.a[type->handle.extra];
if (image->dim > img_subpassdata) {
internal_error (0, "image has bogus dimension");
}
if (strcmp (property->name, "sample_type") == 0) {
return new_type_expr (image->sample_type);
} else if (strcmp (property->name, "image_coord") == 0) {
int width = dim_widths[image->dim];
if (image->dim == img_subpassdata) {
width = 2;
}
if (!width) {
return new_type_expr (&type_void);
}
if (image->dim < img_3d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_int, width));
} else if (strcmp (property->name, "size_type") == 0) {
int width = size_widths[image->dim];
if (!width) {
return new_type_expr (&type_void);
}
if (width < 3 && image->dim <= img_cube) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_int, width));
}
return error (0, "no property %s on %s", property->name, type->name + 4);
}
static const expr_t *
sampled_shadow_swizzle (const attribute_t *property, const char *swizzle[7][2],
image_t *image)
{
int count = list_count (&property->params->list);
if (count != 1) {
return error (property->params, "wrong number of params");
}
const expr_t *params[count];
list_scatter (&property->params->list, params);
const char *swiz = swizzle[image->dim][image->arrayed];
if (!swiz) {
return error (property->params, "image does not support"
" shadow sampling");
}
if (!swiz[0]) {
// cube map array
return error (property->params, "cube map array shadow compare is not"
" in the coordinate vector");
}
if (strcmp (swiz, "xyzw") == 0) {
// no-op swizzle
return params[0];
}
if (!swiz[1]) {
auto ptype = get_type (params[0]);
auto member = new_name_expr (swiz);
auto field = get_struct_field (ptype, params[0], member);
if (!field) {
return error (params[0], "invalid shadow coord");
}
member = new_symbol_expr (field);
auto expr = new_field_expr (params[0], member);
expr->field.type = member->symbol->type;
return expr;
}
return new_swizzle_expr (params[0], swiz);
}
static const expr_t *
sampled_image_property (const type_t *type, const attribute_t *property)
{
auto image = &imageset.a[type->handle.extra];
if (image->dim > img_subpassdata) {
internal_error (0, "image has bogus dimension");
}
if (strcmp (property->name, "tex_coord") == 0) {
int width = dim_widths[image->dim];
if (!width) {
return new_type_expr (&type_void);
}
if (image->dim < img_3d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_float, width));
} else if (strcmp (property->name, "shadow_coord") == 0) {
if (property->params) {
return sampled_shadow_swizzle (property, shadow_swizzle, image);
} else {
int width = shadow_widths[image->dim];
if (!image->depth || !width) {
return new_type_expr (&type_void);
}
if (image->dim == img_2d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_float, width));
}
} else if (strcmp (property->name, "comp") == 0) {
if (property->params) {
return sampled_shadow_swizzle (property, shadow_comp_swizzle,
image);
} else {
int width = shadow_widths[image->dim];
if (!image->depth || !width) {
return new_type_expr (&type_void);
}
if (image->dim == img_2d) {
width += image->arrayed;
}
return new_type_expr (vector_type (&type_float, width));
}
}
return image_property (type, property);
}
type_t type_image = {
.type = ev_invalid,
.meta = ty_struct,
.property = image_property,
};
type_t type_sampled_image = {
.type = ev_invalid,
.meta = ty_struct,
.property = sampled_image_property,
};
type_t type_sampler = {
.type = ev_int,
.meta = ty_handle,
};
void
image_init_types (void)
{
make_structure ("@image", 's', image_struct, &type_image);
make_structure ("@sampled_image", 's', sampled_image_struct,
&type_sampled_image);
make_handle ("@sampler", &type_sampler);
chain_type (&type_image);
chain_type (&type_sampler);
chain_type (&type_sampled_image);
DARRAY_RESIZE (&imageset, 0);
}
static const expr_t *
image_handle_property (const type_t *type, const attribute_t *attr)
{
return type->handle.type->property (type, attr);
}
symbol_t *
named_image_type (image_t *image, const type_t *htype, const char *name)
{
unsigned index = 0;
// slot 0 is never used
for (unsigned i = 1; i < imageset.size; i++) {
if (memcmp (&imageset.a[i], image, sizeof (*image)) == 0) {
index = i;
break;
}
}
if (!index) {
if (!imageset.size) {
DARRAY_APPEND (&imageset, (image_t) { } );
}
index = imageset.size;
DARRAY_APPEND (&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_handle_property;
sym->type = find_type (sym->type);
return sym;
}

View file

@ -40,6 +40,7 @@
#include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/function.h"
#include "tools/qfcc/include/glsl-lang.h"
#include "tools/qfcc/include/image.h"
#include "tools/qfcc/include/options.h"
#include "tools/qfcc/include/qfcc.h"
#include "tools/qfcc/include/spirv.h"
@ -666,7 +667,7 @@ spirv_TypeBool (const type_t *type, spirvctx_t *ctx)
}
static unsigned
spirv_TypeImage (glsl_image_t *image, spirvctx_t *ctx)
spirv_TypeImage (image_t *image, spirvctx_t *ctx)
{
if (image->id) {
return image->id;
@ -798,11 +799,11 @@ spirv_Type (const type_t *type, spirvctx_t *ctx)
} else if (is_boolean (type)) {
id = spirv_TypeBool (type, ctx);
} else if (is_handle (type)
&& (type->handle.type == &type_glsl_image
|| type->handle.type == &type_glsl_sampled_image)) {
auto image = &glsl_imageset.a[type->handle.extra];
&& (type->handle.type == &type_image
|| type->handle.type == &type_sampled_image)) {
auto image = &imageset.a[type->handle.extra];
id = spirv_TypeImage (image, ctx);
if (type->handle.type == &type_glsl_sampled_image) {
if (type->handle.type == &type_sampled_image) {
id = spirv_TypeSampledImage (id, ctx);
}
}