mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/hlsl: Parse packoffset().
This commit is contained in:
committed by
Alexandre Julliard
parent
9b70971696
commit
4aca335f42
Notes:
Alexandre Julliard
2023-04-04 22:35:22 +02:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Zebediah Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/106
@@ -342,12 +342,17 @@ struct hlsl_attribute
|
|||||||
|
|
||||||
#define HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT 0
|
#define HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT 0
|
||||||
|
|
||||||
/* Reservation of a specific register to a variable, field, or buffer, written in the HLSL source
|
/* Reservation of a register and/or an offset for objects inside constant buffers, to be used as a
|
||||||
* using the register(·) syntax */
|
* starting point of their allocation. They are available through the register(·) and the
|
||||||
|
* packoffset(·) syntaxes, respectivelly.
|
||||||
|
* The costant buffer offset is measured register components. */
|
||||||
struct hlsl_reg_reservation
|
struct hlsl_reg_reservation
|
||||||
{
|
{
|
||||||
char reg_type;
|
char reg_type;
|
||||||
unsigned int reg_index;
|
unsigned int reg_index;
|
||||||
|
|
||||||
|
char offset_type;
|
||||||
|
unsigned int offset_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hlsl_ir_var
|
struct hlsl_ir_var
|
||||||
@@ -360,8 +365,7 @@ struct hlsl_ir_var
|
|||||||
struct hlsl_buffer *buffer;
|
struct hlsl_buffer *buffer;
|
||||||
/* Bitfield for storage modifiers (type modifiers are stored in data_type->modifiers). */
|
/* Bitfield for storage modifiers (type modifiers are stored in data_type->modifiers). */
|
||||||
unsigned int storage_modifiers;
|
unsigned int storage_modifiers;
|
||||||
/* Optional register to be used as a starting point for the variable allocation, specified
|
/* Optional reservations of registers and/or offsets for variables within constant buffers. */
|
||||||
* by the user via the register(·) syntax. */
|
|
||||||
struct hlsl_reg_reservation reg_reservation;
|
struct hlsl_reg_reservation reg_reservation;
|
||||||
|
|
||||||
/* Item entry in hlsl_scope.vars. Specifically hlsl_ctx.globals.vars if the variable is global. */
|
/* Item entry in hlsl_scope.vars. Specifically hlsl_ctx.globals.vars if the variable is global. */
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ matrix {return KW_MATRIX; }
|
|||||||
namespace {return KW_NAMESPACE; }
|
namespace {return KW_NAMESPACE; }
|
||||||
nointerpolation {return KW_NOINTERPOLATION; }
|
nointerpolation {return KW_NOINTERPOLATION; }
|
||||||
out {return KW_OUT; }
|
out {return KW_OUT; }
|
||||||
|
packoffset {return KW_PACKOFFSET; }
|
||||||
pass {return KW_PASS; }
|
pass {return KW_PASS; }
|
||||||
PixelShader {return KW_PIXELSHADER; }
|
PixelShader {return KW_PIXELSHADER; }
|
||||||
precise {return KW_PRECISE; }
|
precise {return KW_PRECISE; }
|
||||||
|
|||||||
@@ -983,6 +983,9 @@ static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields,
|
|||||||
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Illegal initializer on a struct field.");
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Illegal initializer on a struct field.");
|
||||||
free_parse_initializer(&v->initializer);
|
free_parse_initializer(&v->initializer);
|
||||||
}
|
}
|
||||||
|
if (v->reg_reservation.offset_type)
|
||||||
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"packoffset() is not allowed inside struct definitions.");
|
||||||
vkd3d_free(v);
|
vkd3d_free(v);
|
||||||
}
|
}
|
||||||
vkd3d_free(defs);
|
vkd3d_free(defs);
|
||||||
@@ -1063,7 +1066,12 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters
|
|||||||
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
||||||
"Parameter '%s' is declared as both \"out\" and \"uniform\".", param->name);
|
"Parameter '%s' is declared as both \"out\" and \"uniform\".", param->name);
|
||||||
|
|
||||||
if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers, ¶m->reg_reservation)))
|
if (param->reg_reservation.offset_type)
|
||||||
|
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"packoffset() is not allowed on function parameters.");
|
||||||
|
|
||||||
|
if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers,
|
||||||
|
¶m->reg_reservation)))
|
||||||
return false;
|
return false;
|
||||||
var->is_param = 1;
|
var->is_param = 1;
|
||||||
|
|
||||||
@@ -1093,6 +1101,52 @@ static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string)
|
|||||||
return reservation;
|
return reservation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct hlsl_reg_reservation parse_packoffset(struct hlsl_ctx *ctx, const char *reg_string,
|
||||||
|
const char *swizzle, const struct vkd3d_shader_location *loc)
|
||||||
|
{
|
||||||
|
struct hlsl_reg_reservation reservation = {0};
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
reservation.offset_index = strtoul(reg_string + 1, &endptr, 10);
|
||||||
|
if (*endptr)
|
||||||
|
{
|
||||||
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"Invalid packoffset() syntax.");
|
||||||
|
return reservation;
|
||||||
|
}
|
||||||
|
|
||||||
|
reservation.offset_type = reg_string[0];
|
||||||
|
if (reservation.offset_type != 'c')
|
||||||
|
{
|
||||||
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"Only 'c' registers are allowed in packoffset().");
|
||||||
|
return reservation;
|
||||||
|
}
|
||||||
|
|
||||||
|
reservation.offset_index *= 4;
|
||||||
|
|
||||||
|
if (swizzle)
|
||||||
|
{
|
||||||
|
if (strlen(swizzle) != 1)
|
||||||
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"Invalid packoffset() component \"%s\".", swizzle);
|
||||||
|
|
||||||
|
if (swizzle[0] == 'x' || swizzle[0] == 'r')
|
||||||
|
reservation.offset_index += 0;
|
||||||
|
else if (swizzle[0] == 'y' || swizzle[0] == 'g')
|
||||||
|
reservation.offset_index += 1;
|
||||||
|
else if (swizzle[0] == 'z' || swizzle[0] == 'b')
|
||||||
|
reservation.offset_index += 2;
|
||||||
|
else if (swizzle[0] == 'w' || swizzle[0] == 'a')
|
||||||
|
reservation.offset_index += 3;
|
||||||
|
else
|
||||||
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"Invalid packoffset() component \"%s\".", swizzle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reservation;
|
||||||
|
}
|
||||||
|
|
||||||
static struct hlsl_ir_function_decl *get_func_decl(struct rb_tree *funcs,
|
static struct hlsl_ir_function_decl *get_func_decl(struct rb_tree *funcs,
|
||||||
const char *name, const struct hlsl_func_parameters *parameters)
|
const char *name, const struct hlsl_func_parameters *parameters)
|
||||||
{
|
{
|
||||||
@@ -2043,6 +2097,13 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
|
|||||||
|
|
||||||
var->buffer = ctx->cur_buffer;
|
var->buffer = ctx->cur_buffer;
|
||||||
|
|
||||||
|
if (var->buffer == ctx->globals_buffer)
|
||||||
|
{
|
||||||
|
if (var->reg_reservation.offset_type)
|
||||||
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"packoffset() is only allowed inside constant buffer declarations.");
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->cur_scope == ctx->globals)
|
if (ctx->cur_scope == ctx->globals)
|
||||||
{
|
{
|
||||||
local = false;
|
local = false;
|
||||||
@@ -3846,6 +3907,7 @@ static void validate_texture_format_type(struct hlsl_ctx *ctx, struct hlsl_type
|
|||||||
%token KW_NAMESPACE
|
%token KW_NAMESPACE
|
||||||
%token KW_NOINTERPOLATION
|
%token KW_NOINTERPOLATION
|
||||||
%token KW_OUT
|
%token KW_OUT
|
||||||
|
%token KW_PACKOFFSET
|
||||||
%token KW_PASS
|
%token KW_PASS
|
||||||
%token KW_PIXELSHADER
|
%token KW_PIXELSHADER
|
||||||
%token KW_PRECISE
|
%token KW_PRECISE
|
||||||
@@ -3999,6 +4061,7 @@ static void validate_texture_format_type(struct hlsl_ctx *ctx, struct hlsl_type
|
|||||||
%type <parameters> parameters
|
%type <parameters> parameters
|
||||||
|
|
||||||
%type <reg_reservation> register_opt
|
%type <reg_reservation> register_opt
|
||||||
|
%type <reg_reservation> packoffset_opt
|
||||||
|
|
||||||
%type <sampler_dim> texture_type texture_ms_type uav_type
|
%type <sampler_dim> texture_type texture_ms_type uav_type
|
||||||
|
|
||||||
@@ -4351,6 +4414,9 @@ func_prototype_no_attrs:
|
|||||||
|
|
||||||
if ($7.reg_reservation.reg_type)
|
if ($7.reg_reservation.reg_type)
|
||||||
FIXME("Unexpected register reservation for a function.\n");
|
FIXME("Unexpected register reservation for a function.\n");
|
||||||
|
if ($7.reg_reservation.offset_type)
|
||||||
|
hlsl_error(ctx, &@5, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
||||||
|
"packoffset() is not allowed on functions.");
|
||||||
|
|
||||||
if (($$.decl = get_func_decl(&ctx->functions, $3, &$5)))
|
if (($$.decl = get_func_decl(&ctx->functions, $3, &$5)))
|
||||||
{
|
{
|
||||||
@@ -4478,17 +4544,24 @@ colon_attribute:
|
|||||||
{
|
{
|
||||||
$$.semantic.name = NULL;
|
$$.semantic.name = NULL;
|
||||||
$$.reg_reservation.reg_type = 0;
|
$$.reg_reservation.reg_type = 0;
|
||||||
|
$$.reg_reservation.offset_type = 0;
|
||||||
}
|
}
|
||||||
| semantic
|
| semantic
|
||||||
{
|
{
|
||||||
$$.semantic = $1;
|
$$.semantic = $1;
|
||||||
$$.reg_reservation.reg_type = 0;
|
$$.reg_reservation.reg_type = 0;
|
||||||
|
$$.reg_reservation.offset_type = 0;
|
||||||
}
|
}
|
||||||
| register_opt
|
| register_opt
|
||||||
{
|
{
|
||||||
$$.semantic.name = NULL;
|
$$.semantic.name = NULL;
|
||||||
$$.reg_reservation = $1;
|
$$.reg_reservation = $1;
|
||||||
}
|
}
|
||||||
|
| packoffset_opt
|
||||||
|
{
|
||||||
|
$$.semantic.name = NULL;
|
||||||
|
$$.reg_reservation = $1;
|
||||||
|
}
|
||||||
|
|
||||||
semantic:
|
semantic:
|
||||||
':' any_identifier
|
':' any_identifier
|
||||||
@@ -4518,6 +4591,21 @@ register_opt:
|
|||||||
vkd3d_free($6);
|
vkd3d_free($6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packoffset_opt:
|
||||||
|
':' KW_PACKOFFSET '(' any_identifier ')'
|
||||||
|
{
|
||||||
|
$$ = parse_packoffset(ctx, $4, NULL, &@$);
|
||||||
|
|
||||||
|
vkd3d_free($4);
|
||||||
|
}
|
||||||
|
| ':' KW_PACKOFFSET '(' any_identifier '.' any_identifier ')'
|
||||||
|
{
|
||||||
|
$$ = parse_packoffset(ctx, $4, $6, &@$);
|
||||||
|
|
||||||
|
vkd3d_free($4);
|
||||||
|
vkd3d_free($6);
|
||||||
|
}
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
scope_start
|
scope_start
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,6 +23,18 @@ probe all rgba (1.0, 2.0, 3.0, 4.0)
|
|||||||
shader model >= 4.0
|
shader model >= 4.0
|
||||||
|
|
||||||
|
|
||||||
|
[pixel shader fail]
|
||||||
|
cbuffer buffer
|
||||||
|
{
|
||||||
|
float4 a : packoffset(c1invalid_extra_chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main() : sv_target
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
% Respect register boundaries
|
% Respect register boundaries
|
||||||
[pixel shader]
|
[pixel shader]
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
@@ -94,7 +106,7 @@ draw quad
|
|||||||
probe all rgba (0.0, 4.0, 5.0, 6.0)
|
probe all rgba (0.0, 4.0, 5.0, 6.0)
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// Elements cannot overlap if buffer is used.
|
// Elements cannot overlap if buffer is used.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -109,7 +121,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader todo]
|
[pixel shader]
|
||||||
// Elements can overlap if buffer is not used.
|
// Elements can overlap if buffer is not used.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -123,7 +135,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader todo]
|
[pixel shader]
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
float4 a : packoffset(c1);
|
float4 a : packoffset(c1);
|
||||||
@@ -139,11 +151,11 @@ float4 main() : sv_target
|
|||||||
uniform 0 float4 1.0 2.0 3.0 4.0
|
uniform 0 float4 1.0 2.0 3.0 4.0
|
||||||
uniform 4 float4 5.0 6.0 7.0 8.0
|
uniform 4 float4 5.0 6.0 7.0 8.0
|
||||||
uniform 8 float4 9.0 10.0 11.0 12.0
|
uniform 8 float4 9.0 10.0 11.0 12.0
|
||||||
todo draw quad
|
draw quad
|
||||||
todo probe all rgba (509, 610, 711, 812)
|
todo probe all rgba (509, 610, 711, 812)
|
||||||
|
|
||||||
|
|
||||||
[pixel shader todo]
|
[pixel shader]
|
||||||
struct apple
|
struct apple
|
||||||
{
|
{
|
||||||
float2 a;
|
float2 a;
|
||||||
@@ -167,11 +179,11 @@ uniform 0 float4 0.0 1.0 2.0 3.0
|
|||||||
uniform 4 float4 4.0 5.0 6.0 7.0
|
uniform 4 float4 4.0 5.0 6.0 7.0
|
||||||
uniform 8 float4 8.0 9.0 10.0 11.0
|
uniform 8 float4 8.0 9.0 10.0 11.0
|
||||||
uniform 12 float4 12.0 13.0 14.0 15.0
|
uniform 12 float4 12.0 13.0 14.0 15.0
|
||||||
todo draw quad
|
draw quad
|
||||||
todo probe all rgba (12468.0, 13509.0, 14010.0, 15011.0)
|
todo probe all rgba (12468.0, 13509.0, 14010.0, 15011.0)
|
||||||
|
|
||||||
|
|
||||||
[pixel shader todo]
|
[pixel shader]
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
float2 c : packoffset(c0.y);
|
float2 c : packoffset(c0.y);
|
||||||
@@ -184,11 +196,11 @@ float4 main() : sv_target
|
|||||||
|
|
||||||
[test]
|
[test]
|
||||||
uniform 0 float4 1.0 2.0 3.0 4.0
|
uniform 0 float4 1.0 2.0 3.0 4.0
|
||||||
todo draw quad
|
draw quad
|
||||||
todo probe all rgba (2.0, 3.0, 2.0, 3.0)
|
todo probe all rgba (2.0, 3.0, 2.0, 3.0)
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// Elements must respect register boundaries.
|
// Elements must respect register boundaries.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -201,7 +213,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// Matrices must be aligned.
|
// Matrices must be aligned.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -214,7 +226,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// Arrays must be aligned.
|
// Arrays must be aligned.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -227,7 +239,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// Structs must be aligned.
|
// Structs must be aligned.
|
||||||
struct apple
|
struct apple
|
||||||
{
|
{
|
||||||
@@ -245,7 +257,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// Invalid offset on unused buffer.
|
// Invalid offset on unused buffer.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -258,7 +270,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// Invalid offset on unused variable.
|
// Invalid offset on unused variable.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -272,7 +284,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader todo]
|
[pixel shader]
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
float4 a : packoffset(c1);
|
float4 a : packoffset(c1);
|
||||||
@@ -289,11 +301,11 @@ float4 main() : sv_target
|
|||||||
uniform 0 float 1.0
|
uniform 0 float 1.0
|
||||||
uniform 1 float 2.0
|
uniform 1 float 2.0
|
||||||
uniform 4 float4 5.0 6.0 7.0 8.0
|
uniform 4 float4 5.0 6.0 7.0 8.0
|
||||||
todo draw quad
|
draw quad
|
||||||
todo probe all rgba (512.0, 612.0, 712.0, 812.0)
|
todo probe all rgba (512.0, 612.0, 712.0, 812.0)
|
||||||
|
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
// packoffset cannot be used unless all elements use it.
|
// packoffset cannot be used unless all elements use it.
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
@@ -307,7 +319,7 @@ float4 main() : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[pixel shader todo]
|
[pixel shader]
|
||||||
cbuffer buffer
|
cbuffer buffer
|
||||||
{
|
{
|
||||||
float2 c : packoffset(c0.b);
|
float2 c : packoffset(c0.b);
|
||||||
@@ -320,7 +332,7 @@ float4 main() : sv_target
|
|||||||
|
|
||||||
[test]
|
[test]
|
||||||
uniform 0 float4 1.0 2.0 3.0 4.0
|
uniform 0 float4 1.0 2.0 3.0 4.0
|
||||||
todo draw quad
|
draw quad
|
||||||
todo probe all rgba (3.0, 4.0, 3.0, 4.0)
|
todo probe all rgba (3.0, 4.0, 3.0, 4.0)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user