2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * \file slang_assemble_typeinfo.c
32 #include "slang_typeinfo.h"
33 #include "slang_compile.h"
34 #include "slang_log.h"
35 #include "prog_instruction.h"
41 * Checks if a field selector is a general swizzle (an r-value swizzle
42 * with replicated components or an l-value swizzle mask) for a
43 * vector. Returns GL_TRUE if this is the case, <swz> is filled with
44 * swizzle information. Returns GL_FALSE otherwise.
47 _slang_is_swizzle(const char *field
, GLuint rows
, slang_swizzle
* swz
)
50 GLboolean xyzw
= GL_FALSE
, rgba
= GL_FALSE
, stpq
= GL_FALSE
;
53 * We rely on undefined/nil values to distinguish between
54 * regular swizzles and writemasks.
55 * For example, the swizzle ".xNNN" is the writemask ".x".
56 * That's different than the swizzle ".xxxx".
58 for (i
= 0; i
< 4; i
++)
59 swz
->swizzle
[i
] = SWIZZLE_NIL
;
61 /* the swizzle can be at most 4-component long */
62 swz
->num_components
= slang_string_length(field
);
63 if (swz
->num_components
> 4)
66 for (i
= 0; i
< swz
->num_components
; i
++) {
67 /* mark which swizzle group is used */
91 /* collect swizzle component */
115 /* check if the component is valid for given vector's row count */
116 if (rows
<= swz
->swizzle
[i
])
120 /* only one swizzle group can be used */
121 if ((xyzw
&& rgba
) || (xyzw
&& stpq
) || (rgba
&& stpq
))
130 * Checks if a general swizzle is an l-value swizzle - these swizzles
131 * do not have duplicated fields. Returns GL_TRUE if this is a
132 * swizzle mask. Returns GL_FALSE otherwise
135 _slang_is_swizzle_mask(const slang_swizzle
* swz
, GLuint rows
)
139 /* the swizzle may not be longer than the vector dim */
140 if (swz
->num_components
> rows
)
143 /* the swizzle components cannot be duplicated */
144 for (i
= 0; i
< swz
->num_components
; i
++) {
145 if ((c
& (1 << swz
->swizzle
[i
])) != 0)
147 c
|= 1 << swz
->swizzle
[i
];
155 * Combines (multiplies) two swizzles to form single swizzle.
156 * Example: "vec.wzyx.yx" --> "vec.zw".
159 _slang_multiply_swizzles(slang_swizzle
* dst
, const slang_swizzle
* left
,
160 const slang_swizzle
* right
)
164 dst
->num_components
= right
->num_components
;
165 for (i
= 0; i
< right
->num_components
; i
++)
166 dst
->swizzle
[i
] = left
->swizzle
[right
->swizzle
[i
]];
171 slang_type_specifier_ctr(slang_type_specifier
* self
)
173 self
->type
= SLANG_SPEC_VOID
;
174 self
->_struct
= NULL
;
179 slang_type_specifier_dtr(slang_type_specifier
* self
)
181 if (self
->_struct
!= NULL
) {
182 slang_struct_destruct(self
->_struct
);
183 slang_alloc_free(self
->_struct
);
185 if (self
->_array
!= NULL
) {
186 slang_type_specifier_dtr(self
->_array
);
187 slang_alloc_free(self
->_array
);
192 slang_type_specifier_copy(slang_type_specifier
* x
,
193 const slang_type_specifier
* y
)
195 slang_type_specifier z
;
197 slang_type_specifier_ctr(&z
);
199 if (z
.type
== SLANG_SPEC_STRUCT
) {
200 z
._struct
= (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
201 if (z
._struct
== NULL
) {
202 slang_type_specifier_dtr(&z
);
205 if (!slang_struct_construct(z
._struct
)) {
206 slang_alloc_free(z
._struct
);
207 slang_type_specifier_dtr(&z
);
210 if (!slang_struct_copy(z
._struct
, y
->_struct
)) {
211 slang_type_specifier_dtr(&z
);
215 else if (z
.type
== SLANG_SPEC_ARRAY
) {
217 (slang_type_specifier
*)
218 slang_alloc_malloc(sizeof(slang_type_specifier
));
219 if (z
._array
== NULL
) {
220 slang_type_specifier_dtr(&z
);
223 slang_type_specifier_ctr(z
._array
);
224 if (!slang_type_specifier_copy(z
._array
, y
->_array
)) {
225 slang_type_specifier_dtr(&z
);
229 slang_type_specifier_dtr(x
);
236 * Test if two types are equal.
239 slang_type_specifier_equal(const slang_type_specifier
* x
,
240 const slang_type_specifier
* y
)
242 if (x
->type
!= y
->type
)
244 if (x
->type
== SLANG_SPEC_STRUCT
)
245 return slang_struct_equal(x
->_struct
, y
->_struct
);
246 if (x
->type
== SLANG_SPEC_ARRAY
)
247 return slang_type_specifier_equal(x
->_array
, y
->_array
);
253 * As above, but allow float/int casting.
256 slang_type_specifier_compatible(const slang_type_specifier
* x
,
257 const slang_type_specifier
* y
)
259 /* special case: float == int */
260 if (x
->type
== SLANG_SPEC_INT
&& y
->type
== SLANG_SPEC_FLOAT
) {
263 /* XXX may need to add bool/int compatibility, etc */
265 if (x
->type
!= y
->type
)
267 if (x
->type
== SLANG_SPEC_STRUCT
)
268 return slang_struct_equal(x
->_struct
, y
->_struct
);
269 if (x
->type
== SLANG_SPEC_ARRAY
)
270 return slang_type_specifier_compatible(x
->_array
, y
->_array
);
276 slang_typeinfo_construct(slang_typeinfo
* ti
)
278 slang_type_specifier_ctr(&ti
->spec
);
284 slang_typeinfo_destruct(slang_typeinfo
* ti
)
286 slang_type_specifier_dtr(&ti
->spec
);
291 * Determine the return type of a function.
292 * \param name name of the function
293 * \param params array of function parameters
294 * \param num_params number of parameters
295 * \param space namespace to use
296 * \param spec returns the function's type
297 * \param atoms atom pool
298 * \return GL_TRUE for success, GL_FALSE if failure
301 typeof_existing_function(const char *name
, const slang_operation
* params
,
303 const slang_name_space
* space
,
304 slang_type_specifier
* spec
,
305 slang_atom_pool
* atoms
,
311 atom
= slang_atom_pool_atom(atoms
, name
);
312 if (!_slang_typeof_function(atom
, params
, num_params
, space
, spec
,
313 &exists
, atoms
, log
))
319 _slang_typeof_operation(const slang_assemble_ctx
* A
,
320 const slang_operation
* op
,
323 return _slang_typeof_operation_(op
, &A
->space
, ti
, A
->atoms
, A
->log
);
328 * Determine the return type of an operation.
329 * \param op the operation node
330 * \param space the namespace to use
331 * \param ti the returned type
332 * \param atoms atom pool
333 * \return GL_TRUE for success, GL_FALSE if failure
336 _slang_typeof_operation_(const slang_operation
* op
,
337 const slang_name_space
* space
,
339 slang_atom_pool
* atoms
,
342 ti
->can_be_referenced
= GL_FALSE
;
343 ti
->is_swizzled
= GL_FALSE
;
346 case SLANG_OPER_BLOCK_NO_NEW_SCOPE
:
347 case SLANG_OPER_BLOCK_NEW_SCOPE
:
348 case SLANG_OPER_VARIABLE_DECL
:
350 case SLANG_OPER_BREAK
:
351 case SLANG_OPER_CONTINUE
:
352 case SLANG_OPER_DISCARD
:
353 case SLANG_OPER_RETURN
:
355 case SLANG_OPER_WHILE
:
358 case SLANG_OPER_VOID
:
359 ti
->spec
.type
= SLANG_SPEC_VOID
;
361 case SLANG_OPER_EXPRESSION
:
362 case SLANG_OPER_ASSIGN
:
363 case SLANG_OPER_ADDASSIGN
:
364 case SLANG_OPER_SUBASSIGN
:
365 case SLANG_OPER_MULASSIGN
:
366 case SLANG_OPER_DIVASSIGN
:
367 case SLANG_OPER_PREINCREMENT
:
368 case SLANG_OPER_PREDECREMENT
:
369 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
, log
))
372 case SLANG_OPER_LITERAL_BOOL
:
373 if (op
->literal_size
== 1)
374 ti
->spec
.type
= SLANG_SPEC_BOOL
;
375 else if (op
->literal_size
== 2)
376 ti
->spec
.type
= SLANG_SPEC_BVEC2
;
377 else if (op
->literal_size
== 3)
378 ti
->spec
.type
= SLANG_SPEC_BVEC3
;
379 else if (op
->literal_size
== 4)
380 ti
->spec
.type
= SLANG_SPEC_BVEC4
;
383 "Unexpected bool literal_size %d in _slang_typeof_operation()",
385 ti
->spec
.type
= SLANG_SPEC_BOOL
;
388 case SLANG_OPER_LOGICALOR
:
389 case SLANG_OPER_LOGICALXOR
:
390 case SLANG_OPER_LOGICALAND
:
391 case SLANG_OPER_EQUAL
:
392 case SLANG_OPER_NOTEQUAL
:
393 case SLANG_OPER_LESS
:
394 case SLANG_OPER_GREATER
:
395 case SLANG_OPER_LESSEQUAL
:
396 case SLANG_OPER_GREATEREQUAL
:
398 ti
->spec
.type
= SLANG_SPEC_BOOL
;
400 case SLANG_OPER_LITERAL_INT
:
401 if (op
->literal_size
== 1)
402 ti
->spec
.type
= SLANG_SPEC_INT
;
403 else if (op
->literal_size
== 2)
404 ti
->spec
.type
= SLANG_SPEC_IVEC2
;
405 else if (op
->literal_size
== 3)
406 ti
->spec
.type
= SLANG_SPEC_IVEC3
;
407 else if (op
->literal_size
== 4)
408 ti
->spec
.type
= SLANG_SPEC_IVEC4
;
411 "Unexpected int literal_size %d in _slang_typeof_operation()",
413 ti
->spec
.type
= SLANG_SPEC_INT
;
416 case SLANG_OPER_LITERAL_FLOAT
:
417 if (op
->literal_size
== 1)
418 ti
->spec
.type
= SLANG_SPEC_FLOAT
;
419 else if (op
->literal_size
== 2)
420 ti
->spec
.type
= SLANG_SPEC_VEC2
;
421 else if (op
->literal_size
== 3)
422 ti
->spec
.type
= SLANG_SPEC_VEC3
;
423 else if (op
->literal_size
== 4)
424 ti
->spec
.type
= SLANG_SPEC_VEC4
;
427 "Unexpected float literal_size %d in _slang_typeof_operation()",
429 ti
->spec
.type
= SLANG_SPEC_FLOAT
;
432 case SLANG_OPER_IDENTIFIER
:
435 var
= _slang_locate_variable(op
->locals
, op
->a_id
, GL_TRUE
);
437 slang_info_log_error(log
, "undefined variable '%s'",
441 if (!slang_type_specifier_copy(&ti
->spec
, &var
->type
.specifier
)) {
442 slang_info_log_memory(log
);
445 ti
->can_be_referenced
= GL_TRUE
;
446 ti
->array_len
= var
->array_len
;
449 case SLANG_OPER_SEQUENCE
:
450 /* TODO: check [0] and [1] if they match */
451 if (!_slang_typeof_operation_(&op
->children
[1], space
, ti
, atoms
, log
)) {
454 ti
->can_be_referenced
= GL_FALSE
;
455 ti
->is_swizzled
= GL_FALSE
;
457 /*case SLANG_OPER_MODASSIGN: */
458 /*case SLANG_OPER_LSHASSIGN: */
459 /*case SLANG_OPER_RSHASSIGN: */
460 /*case SLANG_OPER_ORASSIGN: */
461 /*case SLANG_OPER_XORASSIGN: */
462 /*case SLANG_OPER_ANDASSIGN: */
463 case SLANG_OPER_SELECT
:
464 /* TODO: check [1] and [2] if they match */
465 if (!_slang_typeof_operation_(&op
->children
[1], space
, ti
, atoms
, log
)) {
468 ti
->can_be_referenced
= GL_FALSE
;
469 ti
->is_swizzled
= GL_FALSE
;
471 /*case SLANG_OPER_BITOR: */
472 /*case SLANG_OPER_BITXOR: */
473 /*case SLANG_OPER_BITAND: */
474 /*case SLANG_OPER_LSHIFT: */
475 /*case SLANG_OPER_RSHIFT: */
477 if (!typeof_existing_function("+", op
->children
, 2, space
,
478 &ti
->spec
, atoms
, log
))
481 case SLANG_OPER_SUBTRACT
:
482 if (!typeof_existing_function("-", op
->children
, 2, space
,
483 &ti
->spec
, atoms
, log
))
486 case SLANG_OPER_MULTIPLY
:
487 if (!typeof_existing_function("*", op
->children
, 2, space
,
488 &ti
->spec
, atoms
, log
))
491 case SLANG_OPER_DIVIDE
:
492 if (!typeof_existing_function("/", op
->children
, 2, space
,
493 &ti
->spec
, atoms
, log
))
496 /*case SLANG_OPER_MODULUS: */
497 case SLANG_OPER_PLUS
:
498 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
, log
))
500 ti
->can_be_referenced
= GL_FALSE
;
501 ti
->is_swizzled
= GL_FALSE
;
503 case SLANG_OPER_MINUS
:
504 if (!typeof_existing_function("-", op
->children
, 1, space
,
505 &ti
->spec
, atoms
, log
))
508 /*case SLANG_OPER_COMPLEMENT: */
509 case SLANG_OPER_SUBSCRIPT
:
513 if (!slang_typeinfo_construct(&_ti
))
515 if (!_slang_typeof_operation_(op
->children
, space
, &_ti
, atoms
, log
)) {
516 slang_typeinfo_destruct(&_ti
);
519 ti
->can_be_referenced
= _ti
.can_be_referenced
;
520 if (_ti
.spec
.type
== SLANG_SPEC_ARRAY
) {
521 if (!slang_type_specifier_copy(&ti
->spec
, _ti
.spec
._array
)) {
522 slang_typeinfo_destruct(&_ti
);
527 if (!_slang_type_is_vector(_ti
.spec
.type
)
528 && !_slang_type_is_matrix(_ti
.spec
.type
)) {
529 slang_typeinfo_destruct(&_ti
);
530 slang_info_log_error(log
, "cannot index a non-array type");
533 ti
->spec
.type
= _slang_type_base(_ti
.spec
.type
);
535 slang_typeinfo_destruct(&_ti
);
538 case SLANG_OPER_CALL
:
542 if (!_slang_typeof_function(op
->a_id
, op
->children
, op
->num_children
,
543 space
, &ti
->spec
, &exists
, atoms
, log
))
547 slang_struct_scope_find(space
->structs
, op
->a_id
, GL_TRUE
);
549 ti
->spec
.type
= SLANG_SPEC_STRUCT
;
551 (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
552 if (ti
->spec
._struct
== NULL
)
554 if (!slang_struct_construct(ti
->spec
._struct
)) {
555 slang_alloc_free(ti
->spec
._struct
);
556 ti
->spec
._struct
= NULL
;
559 if (!slang_struct_copy(ti
->spec
._struct
, s
))
564 slang_type_specifier_type type
;
566 name
= slang_atom_pool_id(atoms
, op
->a_id
);
567 type
= slang_type_specifier_type_from_string(name
);
568 if (type
== SLANG_SPEC_VOID
) {
569 slang_info_log_error(log
, "undefined function '%s'", name
);
572 ti
->spec
.type
= type
;
577 case SLANG_OPER_FIELD
:
581 if (!slang_typeinfo_construct(&_ti
))
583 if (!_slang_typeof_operation_(op
->children
, space
, &_ti
, atoms
, log
)) {
584 slang_typeinfo_destruct(&_ti
);
587 if (_ti
.spec
.type
== SLANG_SPEC_STRUCT
) {
588 slang_variable
*field
;
590 field
= _slang_locate_variable(_ti
.spec
._struct
->fields
, op
->a_id
,
593 slang_typeinfo_destruct(&_ti
);
596 if (!slang_type_specifier_copy(&ti
->spec
, &field
->type
.specifier
)) {
597 slang_typeinfo_destruct(&_ti
);
600 ti
->can_be_referenced
= _ti
.can_be_referenced
;
605 slang_type_specifier_type base
;
607 /* determine the swizzle of the field expression */
608 if (!_slang_type_is_vector(_ti
.spec
.type
)) {
609 slang_typeinfo_destruct(&_ti
);
610 slang_info_log_error(log
, "Can't swizzle scalar expression");
613 rows
= _slang_type_dim(_ti
.spec
.type
);
614 swizzle
= slang_atom_pool_id(atoms
, op
->a_id
);
615 if (!_slang_is_swizzle(swizzle
, rows
, &ti
->swz
)) {
616 slang_typeinfo_destruct(&_ti
);
617 slang_info_log_error(log
, "bad swizzle '%s'", swizzle
);
620 ti
->is_swizzled
= GL_TRUE
;
621 ti
->can_be_referenced
= _ti
.can_be_referenced
622 && _slang_is_swizzle_mask(&ti
->swz
, rows
);
623 if (_ti
.is_swizzled
) {
626 /* swizzle the swizzle */
627 _slang_multiply_swizzles(&swz
, &_ti
.swz
, &ti
->swz
);
630 base
= _slang_type_base(_ti
.spec
.type
);
631 switch (ti
->swz
.num_components
) {
633 ti
->spec
.type
= base
;
637 case SLANG_SPEC_FLOAT
:
638 ti
->spec
.type
= SLANG_SPEC_VEC2
;
641 ti
->spec
.type
= SLANG_SPEC_IVEC2
;
643 case SLANG_SPEC_BOOL
:
644 ti
->spec
.type
= SLANG_SPEC_BVEC2
;
652 case SLANG_SPEC_FLOAT
:
653 ti
->spec
.type
= SLANG_SPEC_VEC3
;
656 ti
->spec
.type
= SLANG_SPEC_IVEC3
;
658 case SLANG_SPEC_BOOL
:
659 ti
->spec
.type
= SLANG_SPEC_BVEC3
;
667 case SLANG_SPEC_FLOAT
:
668 ti
->spec
.type
= SLANG_SPEC_VEC4
;
671 ti
->spec
.type
= SLANG_SPEC_IVEC4
;
673 case SLANG_SPEC_BOOL
:
674 ti
->spec
.type
= SLANG_SPEC_BVEC4
;
684 slang_typeinfo_destruct(&_ti
);
687 case SLANG_OPER_POSTINCREMENT
:
688 case SLANG_OPER_POSTDECREMENT
:
689 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
, log
))
691 ti
->can_be_referenced
= GL_FALSE
;
692 ti
->is_swizzled
= GL_FALSE
;
703 * Lookup a function according to name and parameter count/types.
706 _slang_locate_function(const slang_function_scope
* funcs
, slang_atom a_name
,
707 const slang_operation
* args
, GLuint num_args
,
708 const slang_name_space
* space
, slang_atom_pool
* atoms
,
713 for (i
= 0; i
< funcs
->num_functions
; i
++) {
714 slang_function
*f
= &funcs
->functions
[i
];
715 const GLuint haveRetValue
= _slang_function_has_return_value(f
);
718 if (a_name
!= f
->header
.a_name
)
720 if (f
->param_count
- haveRetValue
!= num_args
)
723 /* compare parameter / argument types */
724 for (j
= 0; j
< num_args
; j
++) {
727 if (!slang_typeinfo_construct(&ti
))
729 if (!_slang_typeof_operation_(&args
[j
], space
, &ti
, atoms
, log
)) {
730 slang_typeinfo_destruct(&ti
);
733 if (!slang_type_specifier_compatible(&ti
.spec
,
734 &f
->parameters
->variables
[j
]->type
.specifier
)) {
735 slang_typeinfo_destruct(&ti
);
738 slang_typeinfo_destruct(&ti
);
740 /* "out" and "inout" formal parameter requires the actual
741 * parameter to be l-value.
743 if (!ti
.can_be_referenced
&&
744 (f
->parameters
->variables
[j
]->type
.qualifier
== SLANG_QUAL_OUT
||
745 f
->parameters
->variables
[j
]->type
.qualifier
== SLANG_QUAL_INOUT
))
751 if (funcs
->outer_scope
!= NULL
)
752 return _slang_locate_function(funcs
->outer_scope
, a_name
, args
,
753 num_args
, space
, atoms
, log
);
760 * Determine the return type of a function.
761 * \param a_name the function name
762 * \param param function parameters (overloading)
763 * \param num_params number of parameters to function
764 * \param space namespace to search
765 * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
766 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
769 _slang_typeof_function(slang_atom a_name
, const slang_operation
* params
,
771 const slang_name_space
* space
,
772 slang_type_specifier
* spec
, GLboolean
* exists
,
773 slang_atom_pool
*atoms
, slang_info_log
*log
)
775 slang_function
*fun
= _slang_locate_function(space
->funcs
, a_name
, params
,
776 num_params
, space
, atoms
, log
);
777 *exists
= fun
!= NULL
;
779 return GL_TRUE
; /* yes, not false */
780 return slang_type_specifier_copy(spec
, &fun
->header
.type
.specifier
);
786 * Determine if a type is a matrix.
787 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
790 _slang_type_is_matrix(slang_type_specifier_type ty
)
793 case SLANG_SPEC_MAT2
:
794 case SLANG_SPEC_MAT3
:
795 case SLANG_SPEC_MAT4
:
804 * Determine if a type is a vector.
805 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
808 _slang_type_is_vector(slang_type_specifier_type ty
)
811 case SLANG_SPEC_VEC2
:
812 case SLANG_SPEC_VEC3
:
813 case SLANG_SPEC_VEC4
:
814 case SLANG_SPEC_IVEC2
:
815 case SLANG_SPEC_IVEC3
:
816 case SLANG_SPEC_IVEC4
:
817 case SLANG_SPEC_BVEC2
:
818 case SLANG_SPEC_BVEC3
:
819 case SLANG_SPEC_BVEC4
:
828 * Given a vector type, return the type of the vector's elements
830 slang_type_specifier_type
831 _slang_type_base(slang_type_specifier_type ty
)
834 case SLANG_SPEC_FLOAT
:
835 case SLANG_SPEC_VEC2
:
836 case SLANG_SPEC_VEC3
:
837 case SLANG_SPEC_VEC4
:
838 return SLANG_SPEC_FLOAT
;
840 case SLANG_SPEC_IVEC2
:
841 case SLANG_SPEC_IVEC3
:
842 case SLANG_SPEC_IVEC4
:
843 return SLANG_SPEC_INT
;
844 case SLANG_SPEC_BOOL
:
845 case SLANG_SPEC_BVEC2
:
846 case SLANG_SPEC_BVEC3
:
847 case SLANG_SPEC_BVEC4
:
848 return SLANG_SPEC_BOOL
;
849 case SLANG_SPEC_MAT2
:
850 return SLANG_SPEC_VEC2
;
851 case SLANG_SPEC_MAT3
:
852 return SLANG_SPEC_VEC3
;
853 case SLANG_SPEC_MAT4
:
854 return SLANG_SPEC_VEC4
;
856 return SLANG_SPEC_VOID
;
862 * Return the dimensionality of a vector or matrix type.
865 _slang_type_dim(slang_type_specifier_type ty
)
868 case SLANG_SPEC_FLOAT
:
870 case SLANG_SPEC_BOOL
:
872 case SLANG_SPEC_VEC2
:
873 case SLANG_SPEC_IVEC2
:
874 case SLANG_SPEC_BVEC2
:
875 case SLANG_SPEC_MAT2
:
877 case SLANG_SPEC_VEC3
:
878 case SLANG_SPEC_IVEC3
:
879 case SLANG_SPEC_BVEC3
:
880 case SLANG_SPEC_MAT3
:
882 case SLANG_SPEC_VEC4
:
883 case SLANG_SPEC_IVEC4
:
884 case SLANG_SPEC_BVEC4
:
885 case SLANG_SPEC_MAT4
: