mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Updated vkd3d-latest patchset
Squash to previous wine-staging release.
This commit is contained in:
parent
a442564f05
commit
577974c563
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,206 +0,0 @@
|
||||
From f9d3eae7971ce35994e20546183c7147d33c1d4a Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Sun, 23 Jun 2024 15:40:43 +1000
|
||||
Subject: [PATCH] Updated vkd3d to ccb6150aabc7cce9e26a39366c611f5a7da789e4.
|
||||
|
||||
---
|
||||
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 2 +-
|
||||
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 110 ++++++++++++++++++--
|
||||
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 4 +-
|
||||
3 files changed, 108 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||||
index 2290385da76..3665b99aed7 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||||
@@ -2582,7 +2582,7 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_
|
||||
|
||||
.srcs[0].type = D3DSPR_TEMP,
|
||||
.srcs[0].reg = coords->reg.id,
|
||||
- .srcs[0].swizzle = hlsl_swizzle_from_writemask(VKD3DSP_WRITEMASK_ALL),
|
||||
+ .srcs[0].swizzle = hlsl_swizzle_from_writemask(coords->reg.writemask),
|
||||
|
||||
.srcs[1].type = D3DSPR_SAMPLER,
|
||||
.srcs[1].reg = reg_id,
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||||
index a2c89b15e4a..9c75c87d36e 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||||
@@ -1878,12 +1878,57 @@ static bool invert_swizzle(uint32_t *swizzle, unsigned int *writemask, unsigned
|
||||
return true;
|
||||
}
|
||||
|
||||
+static bool invert_swizzle_matrix(uint32_t *swizzle, unsigned int *writemask, unsigned int *ret_width)
|
||||
+{
|
||||
+ /* swizzle is 8 bits per component, each component is (from LSB) 4 bits X, then 4 bits Y.
|
||||
+ * components are indexed by their sources. i.e. the first component comes from the first
|
||||
+ * component of the rhs. */
|
||||
+ unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0;
|
||||
+
|
||||
+ /* First, we filter the swizzle to remove components that aren't enabled by writemask. */
|
||||
+ for (i = 0; i < 4; ++i)
|
||||
+ {
|
||||
+ if (*writemask & (1 << i))
|
||||
+ {
|
||||
+ unsigned int s = (*swizzle >> (i * 8)) & 0xff;
|
||||
+ unsigned int x = s & 0xf, y = (s >> 4) & 0xf;
|
||||
+ unsigned int idx = x + y * 4;
|
||||
+ new_swizzle |= s << (bit++ * 8);
|
||||
+ if (new_writemask & (1 << idx))
|
||||
+ return false;
|
||||
+ new_writemask |= 1 << idx;
|
||||
+ }
|
||||
+ }
|
||||
+ width = bit;
|
||||
+
|
||||
+ /* Then we invert the swizzle. The resulting swizzle has 2 bits per component, because it's for the
|
||||
+ * incoming vector. */
|
||||
+ bit = 0;
|
||||
+ for (i = 0; i < 16; ++i)
|
||||
+ {
|
||||
+ for (j = 0; j < width; ++j)
|
||||
+ {
|
||||
+ unsigned int s = (new_swizzle >> (j * 8)) & 0xff;
|
||||
+ unsigned int x = s & 0xf, y = (s >> 4) & 0xf;
|
||||
+ unsigned int idx = x + y * 4;
|
||||
+ if (idx == i)
|
||||
+ inverted |= j << (bit++ * 2);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ *swizzle = inverted;
|
||||
+ *writemask = new_writemask;
|
||||
+ *ret_width = width;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs,
|
||||
enum parse_assign_op assign_op, struct hlsl_ir_node *rhs)
|
||||
{
|
||||
struct hlsl_type *lhs_type = lhs->data_type;
|
||||
struct hlsl_ir_node *copy;
|
||||
- unsigned int writemask = 0;
|
||||
+ unsigned int writemask = 0, width = 0;
|
||||
+ bool matrix_writemask = false;
|
||||
|
||||
if (assign_op == ASSIGN_OP_SUB)
|
||||
{
|
||||
@@ -1901,7 +1946,10 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
|
||||
}
|
||||
|
||||
if (hlsl_is_numeric_type(lhs_type))
|
||||
+ {
|
||||
writemask = (1 << lhs_type->dimx) - 1;
|
||||
+ width = lhs_type->dimx;
|
||||
+ }
|
||||
|
||||
if (!(rhs = add_implicit_conversion(ctx, block, rhs, lhs_type, &rhs->loc)))
|
||||
return NULL;
|
||||
@@ -1918,12 +1966,24 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
|
||||
struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs);
|
||||
struct hlsl_ir_node *new_swizzle;
|
||||
uint32_t s = swizzle->swizzle;
|
||||
- unsigned int width;
|
||||
|
||||
- if (lhs->data_type->class == HLSL_CLASS_MATRIX)
|
||||
- hlsl_fixme(ctx, &lhs->loc, "Matrix assignment with a writemask.");
|
||||
+ assert(!matrix_writemask);
|
||||
|
||||
- if (!invert_swizzle(&s, &writemask, &width))
|
||||
+ if (swizzle->val.node->data_type->class == HLSL_CLASS_MATRIX)
|
||||
+ {
|
||||
+ if (swizzle->val.node->type != HLSL_IR_LOAD && swizzle->val.node->type != HLSL_IR_INDEX)
|
||||
+ {
|
||||
+ hlsl_fixme(ctx, &lhs->loc, "Unhandled source of matrix swizzle.");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (!invert_swizzle_matrix(&s, &writemask, &width))
|
||||
+ {
|
||||
+ hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask for matrix.");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ matrix_writemask = true;
|
||||
+ }
|
||||
+ else if (!invert_swizzle(&s, &writemask, &width))
|
||||
{
|
||||
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask.");
|
||||
return NULL;
|
||||
@@ -1971,7 +2031,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
|
||||
|
||||
dim_count = hlsl_sampler_dim_count(resource_type->sampler_dim);
|
||||
|
||||
- if (writemask != ((1u << resource_type->e.resource.format->dimx) - 1))
|
||||
+ if (width != resource_type->e.resource.format->dimx * resource_type->e.resource.format->dimy)
|
||||
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK,
|
||||
"Resource store expressions must write to all components.");
|
||||
|
||||
@@ -1987,12 +2047,50 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
|
||||
hlsl_block_add_instr(block, store);
|
||||
hlsl_cleanup_deref(&resource_deref);
|
||||
}
|
||||
+ else if (matrix_writemask)
|
||||
+ {
|
||||
+ struct hlsl_deref deref;
|
||||
+ unsigned int i, j, k = 0;
|
||||
+
|
||||
+ hlsl_init_deref_from_index_chain(ctx, &deref, lhs);
|
||||
+
|
||||
+ for (i = 0; i < lhs->data_type->dimy; ++i)
|
||||
+ {
|
||||
+ for (j = 0; j < lhs->data_type->dimx; ++j)
|
||||
+ {
|
||||
+ struct hlsl_ir_node *load;
|
||||
+ struct hlsl_block store_block;
|
||||
+ const unsigned int idx = i * 4 + j;
|
||||
+ const unsigned int component = i * lhs->data_type->dimx + j;
|
||||
+
|
||||
+ if (!(writemask & (1 << idx)))
|
||||
+ continue;
|
||||
+
|
||||
+ if (!(load = hlsl_add_load_component(ctx, block, rhs, k++, &rhs->loc)))
|
||||
+ {
|
||||
+ hlsl_cleanup_deref(&deref);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (!hlsl_new_store_component(ctx, &store_block, &deref, component, load))
|
||||
+ {
|
||||
+ hlsl_cleanup_deref(&deref);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ hlsl_block_add_block(block, &store_block);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ hlsl_cleanup_deref(&deref);
|
||||
+ }
|
||||
else if (lhs->type == HLSL_IR_INDEX && hlsl_index_is_noncontiguous(hlsl_ir_index(lhs)))
|
||||
{
|
||||
struct hlsl_ir_index *row = hlsl_ir_index(lhs);
|
||||
struct hlsl_ir_node *mat = row->val.node;
|
||||
unsigned int i, k = 0;
|
||||
|
||||
+ assert(!matrix_writemask);
|
||||
+
|
||||
for (i = 0; i < mat->data_type->dimx; ++i)
|
||||
{
|
||||
struct hlsl_ir_node *cell, *load, *store, *c;
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||||
index 09066a6191a..36270b159a5 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||||
@@ -4188,8 +4188,10 @@ static struct hlsl_reg allocate_numeric_registers_for_type(struct hlsl_ctx *ctx,
|
||||
{
|
||||
unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC];
|
||||
|
||||
+ /* FIXME: We could potentially pack structs or arrays more efficiently... */
|
||||
+
|
||||
if (type->class <= HLSL_CLASS_VECTOR)
|
||||
- return allocate_register(ctx, allocator, first_write, last_read, reg_size, type->dimx);
|
||||
+ return allocate_register(ctx, allocator, first_write, last_read, type->dimx, type->dimx);
|
||||
else
|
||||
return allocate_range(ctx, allocator, first_write, last_read, reg_size);
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,960 +0,0 @@
|
||||
From e940aca803c12bbd55ebe3fb26920373a56a0fab Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Thu, 11 Jul 2024 09:52:56 +1000
|
||||
Subject: [PATCH] Updated vkd3d to c792114a6a58c7c97abf827d154d7ecd22d81536.
|
||||
|
||||
---
|
||||
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 4 +-
|
||||
libs/vkd3d/libs/vkd3d-shader/fx.c | 2 +-
|
||||
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 13 +-
|
||||
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 12 +-
|
||||
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 197 +++++----
|
||||
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 390 +++++++++++++++---
|
||||
libs/vkd3d/libs/vkd3d-shader/tpf.c | 29 ++
|
||||
.../libs/vkd3d-shader/vkd3d_shader_private.h | 1 +
|
||||
libs/vkd3d/libs/vkd3d/resource.c | 6 +-
|
||||
9 files changed, 510 insertions(+), 144 deletions(-)
|
||||
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||||
index ea9fe77532d..4522d56c5c9 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||||
@@ -2670,11 +2670,11 @@ static void d3dbc_write_resource_load(struct d3dbc_compiler *d3dbc, const struct
|
||||
case HLSL_RESOURCE_SAMPLE_GRAD:
|
||||
sm1_instr.opcode = D3DSIO_TEXLDD;
|
||||
|
||||
- sm1_instr.srcs[2].type = D3DSPR_TEMP;
|
||||
+ sm1_instr.srcs[2].type = VKD3DSPR_TEMP;
|
||||
sm1_instr.srcs[2].reg = ddx->reg.id;
|
||||
sm1_instr.srcs[2].swizzle = hlsl_swizzle_from_writemask(ddx->reg.writemask);
|
||||
|
||||
- sm1_instr.srcs[3].type = D3DSPR_TEMP;
|
||||
+ sm1_instr.srcs[3].type = VKD3DSPR_TEMP;
|
||||
sm1_instr.srcs[3].reg = ddy->reg.id;
|
||||
sm1_instr.srcs[3].swizzle = hlsl_swizzle_from_writemask(ddy->reg.writemask);
|
||||
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
||||
index 0857ebb65d5..bd2ad1290cd 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/fx.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
||||
@@ -830,7 +830,7 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n
|
||||
}
|
||||
|
||||
name_offset = write_string(name, fx);
|
||||
- semantic_offset = write_string(semantic->raw_name, fx);
|
||||
+ semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0;
|
||||
|
||||
offset = put_u32(buffer, hlsl_sm1_base_type(type));
|
||||
put_u32(buffer, hlsl_sm1_class(type));
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
||||
index a157590c97a..acf50869a40 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
||||
@@ -1810,7 +1810,8 @@ struct hlsl_ir_node *hlsl_new_jump(struct hlsl_ctx *ctx, enum hlsl_ir_jump_type
|
||||
}
|
||||
|
||||
struct hlsl_ir_node *hlsl_new_loop(struct hlsl_ctx *ctx,
|
||||
- struct hlsl_block *block, const struct vkd3d_shader_location *loc)
|
||||
+ struct hlsl_block *block, enum hlsl_ir_loop_unroll_type unroll_type,
|
||||
+ unsigned int unroll_limit, const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
struct hlsl_ir_loop *loop;
|
||||
|
||||
@@ -1819,6 +1820,9 @@ struct hlsl_ir_node *hlsl_new_loop(struct hlsl_ctx *ctx,
|
||||
init_node(&loop->node, HLSL_IR_LOOP, NULL, loc);
|
||||
hlsl_block_init(&loop->body);
|
||||
hlsl_block_add_block(&loop->body, block);
|
||||
+
|
||||
+ loop->unroll_type = unroll_type;
|
||||
+ loop->unroll_limit = unroll_limit;
|
||||
return &loop->node;
|
||||
}
|
||||
|
||||
@@ -1881,9 +1885,7 @@ static struct hlsl_ir_node *map_instr(const struct clone_instr_map *map, struct
|
||||
return map->instrs[i].dst;
|
||||
}
|
||||
|
||||
- /* The block passed to hlsl_clone_block() should have been free of external
|
||||
- * references. */
|
||||
- vkd3d_unreachable();
|
||||
+ return src;
|
||||
}
|
||||
|
||||
static bool clone_deref(struct hlsl_ctx *ctx, struct clone_instr_map *map,
|
||||
@@ -1980,7 +1982,7 @@ static struct hlsl_ir_node *clone_loop(struct hlsl_ctx *ctx, struct clone_instr_
|
||||
if (!clone_block(ctx, &body, &src->body, map))
|
||||
return NULL;
|
||||
|
||||
- if (!(dst = hlsl_new_loop(ctx, &body, &src->node.loc)))
|
||||
+ if (!(dst = hlsl_new_loop(ctx, &body, src->unroll_type, src->unroll_limit, &src->node.loc)))
|
||||
{
|
||||
hlsl_block_cleanup(&body);
|
||||
return NULL;
|
||||
@@ -2791,6 +2793,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op)
|
||||
static const char *const op_names[] =
|
||||
{
|
||||
[HLSL_OP0_VOID] = "void",
|
||||
+ [HLSL_OP0_RASTERIZER_SAMPLE_COUNT] = "GetRenderTargetSampleCount",
|
||||
|
||||
[HLSL_OP1_ABS] = "abs",
|
||||
[HLSL_OP1_BIT_NOT] = "~",
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
||||
index a79d2b064cf..5832958712a 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
||||
@@ -602,12 +602,21 @@ struct hlsl_ir_if
|
||||
struct hlsl_block else_block;
|
||||
};
|
||||
|
||||
+enum hlsl_ir_loop_unroll_type
|
||||
+{
|
||||
+ HLSL_IR_LOOP_UNROLL,
|
||||
+ HLSL_IR_LOOP_FORCE_UNROLL,
|
||||
+ HLSL_IR_LOOP_FORCE_LOOP
|
||||
+};
|
||||
+
|
||||
struct hlsl_ir_loop
|
||||
{
|
||||
struct hlsl_ir_node node;
|
||||
/* loop condition is stored in the body (as "if (!condition) break;") */
|
||||
struct hlsl_block body;
|
||||
unsigned int next_index; /* liveness index of the end of the loop */
|
||||
+ unsigned int unroll_limit;
|
||||
+ enum hlsl_ir_loop_unroll_type unroll_type;
|
||||
};
|
||||
|
||||
struct hlsl_ir_switch_case
|
||||
@@ -629,6 +638,7 @@ struct hlsl_ir_switch
|
||||
enum hlsl_ir_expr_op
|
||||
{
|
||||
HLSL_OP0_VOID,
|
||||
+ HLSL_OP0_RASTERIZER_SAMPLE_COUNT,
|
||||
|
||||
HLSL_OP1_ABS,
|
||||
HLSL_OP1_BIT_NOT,
|
||||
@@ -1390,7 +1400,7 @@ bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index);
|
||||
struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *val,
|
||||
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc);
|
||||
struct hlsl_ir_node *hlsl_new_loop(struct hlsl_ctx *ctx,
|
||||
- struct hlsl_block *block, const struct vkd3d_shader_location *loc);
|
||||
+ struct hlsl_block *block, enum hlsl_ir_loop_unroll_type unroll_type, unsigned int unroll_limit, const struct vkd3d_shader_location *loc);
|
||||
struct hlsl_ir_node *hlsl_new_resource_load(struct hlsl_ctx *ctx,
|
||||
const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc);
|
||||
struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct hlsl_deref *resource,
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||||
index ed6b41bf403..7b058a65bc1 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||||
@@ -573,12 +573,91 @@ static void check_loop_attributes(struct hlsl_ctx *ctx, const struct parse_attri
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unroll attribute can't be used with 'fastopt' attribute.");
|
||||
}
|
||||
|
||||
+static union hlsl_constant_value_component evaluate_static_expression(struct hlsl_ctx *ctx,
|
||||
+ struct hlsl_block *block, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc)
|
||||
+{
|
||||
+ union hlsl_constant_value_component ret = {0};
|
||||
+ struct hlsl_ir_constant *constant;
|
||||
+ struct hlsl_ir_node *node;
|
||||
+ struct hlsl_block expr;
|
||||
+ struct hlsl_src src;
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY(node, &block->instrs, struct hlsl_ir_node, entry)
|
||||
+ {
|
||||
+ switch (node->type)
|
||||
+ {
|
||||
+ case HLSL_IR_CONSTANT:
|
||||
+ case HLSL_IR_EXPR:
|
||||
+ case HLSL_IR_SWIZZLE:
|
||||
+ case HLSL_IR_LOAD:
|
||||
+ case HLSL_IR_INDEX:
|
||||
+ continue;
|
||||
+ case HLSL_IR_STORE:
|
||||
+ if (hlsl_ir_store(node)->lhs.var->is_synthetic)
|
||||
+ break;
|
||||
+ /* fall-through */
|
||||
+ case HLSL_IR_CALL:
|
||||
+ case HLSL_IR_IF:
|
||||
+ case HLSL_IR_LOOP:
|
||||
+ case HLSL_IR_JUMP:
|
||||
+ case HLSL_IR_RESOURCE_LOAD:
|
||||
+ case HLSL_IR_RESOURCE_STORE:
|
||||
+ case HLSL_IR_SWITCH:
|
||||
+ case HLSL_IR_STATEBLOCK_CONSTANT:
|
||||
+ hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
||||
+ "Expected literal expression.");
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!hlsl_clone_block(ctx, &expr, &ctx->static_initializers))
|
||||
+ return ret;
|
||||
+ hlsl_block_add_block(&expr, block);
|
||||
+
|
||||
+ if (!add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc))
|
||||
+ {
|
||||
+ hlsl_block_cleanup(&expr);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Wrap the node into a src to allow the reference to survive the multiple const passes. */
|
||||
+ hlsl_src_from_node(&src, node_from_block(&expr));
|
||||
+ hlsl_run_const_passes(ctx, &expr);
|
||||
+ node = src.node;
|
||||
+ hlsl_src_remove(&src);
|
||||
+
|
||||
+ if (node->type == HLSL_IR_CONSTANT)
|
||||
+ {
|
||||
+ constant = hlsl_ir_constant(node);
|
||||
+ ret = constant->value.u[0];
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
||||
+ "Failed to evaluate constant expression.");
|
||||
+ }
|
||||
+
|
||||
+ hlsl_block_cleanup(&expr);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, struct hlsl_block *block,
|
||||
+ const struct vkd3d_shader_location *loc)
|
||||
+{
|
||||
+ union hlsl_constant_value_component res;
|
||||
+
|
||||
+ res = evaluate_static_expression(ctx, block, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc);
|
||||
+ return res.u;
|
||||
+}
|
||||
+
|
||||
static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type,
|
||||
const struct parse_attribute_list *attributes, struct hlsl_block *init, struct hlsl_block *cond,
|
||||
struct hlsl_block *iter, struct hlsl_block *body, const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
+ enum hlsl_ir_loop_unroll_type unroll_type = HLSL_IR_LOOP_UNROLL;
|
||||
+ unsigned int i, unroll_limit = 0;
|
||||
struct hlsl_ir_node *loop;
|
||||
- unsigned int i;
|
||||
|
||||
if (attribute_list_has_duplicates(attributes))
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Found duplicate attribute.");
|
||||
@@ -591,18 +670,29 @@ static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type,
|
||||
const struct hlsl_attribute *attr = attributes->attrs[i];
|
||||
if (!strcmp(attr->name, "unroll"))
|
||||
{
|
||||
- if (attr->args_count)
|
||||
+ if (attr->args_count > 1)
|
||||
{
|
||||
- hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_IMPLEMENTED, "Unroll attribute with iteration count.");
|
||||
+ hlsl_warning(ctx, &attr->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_ATTRIBUTE,
|
||||
+ "Ignoring 'unroll' attribute with more than 1 argument.");
|
||||
+ continue;
|
||||
}
|
||||
- else
|
||||
+
|
||||
+ if (attr->args_count == 1)
|
||||
{
|
||||
- hlsl_warning(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_IMPLEMENTED, "Loop unrolling is not implemented.");
|
||||
+ struct hlsl_block expr;
|
||||
+ hlsl_block_init(&expr);
|
||||
+ if (!hlsl_clone_block(ctx, &expr, &attr->instrs))
|
||||
+ return NULL;
|
||||
+
|
||||
+ unroll_limit = evaluate_static_expression_as_uint(ctx, &expr, loc);
|
||||
+ hlsl_block_cleanup(&expr);
|
||||
}
|
||||
+
|
||||
+ unroll_type = HLSL_IR_LOOP_FORCE_UNROLL;
|
||||
}
|
||||
else if (!strcmp(attr->name, "loop"))
|
||||
{
|
||||
- /* TODO: this attribute will be used to disable unrolling, once it's implememented. */
|
||||
+ unroll_type = HLSL_IR_LOOP_FORCE_LOOP;
|
||||
}
|
||||
else if (!strcmp(attr->name, "fastopt")
|
||||
|| !strcmp(attr->name, "allow_uav_condition"))
|
||||
@@ -631,7 +721,7 @@ static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type,
|
||||
else
|
||||
list_move_head(&body->instrs, &cond->instrs);
|
||||
|
||||
- if (!(loop = hlsl_new_loop(ctx, body, loc)))
|
||||
+ if (!(loop = hlsl_new_loop(ctx, body, unroll_type, unroll_limit, loc)))
|
||||
goto oom;
|
||||
hlsl_block_add_instr(init, loop);
|
||||
|
||||
@@ -1320,84 +1410,6 @@ static struct hlsl_block *make_block(struct hlsl_ctx *ctx, struct hlsl_ir_node *
|
||||
return block;
|
||||
}
|
||||
|
||||
-static union hlsl_constant_value_component evaluate_static_expression(struct hlsl_ctx *ctx,
|
||||
- struct hlsl_block *block, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc)
|
||||
-{
|
||||
- union hlsl_constant_value_component ret = {0};
|
||||
- struct hlsl_ir_constant *constant;
|
||||
- struct hlsl_ir_node *node;
|
||||
- struct hlsl_block expr;
|
||||
- struct hlsl_src src;
|
||||
-
|
||||
- LIST_FOR_EACH_ENTRY(node, &block->instrs, struct hlsl_ir_node, entry)
|
||||
- {
|
||||
- switch (node->type)
|
||||
- {
|
||||
- case HLSL_IR_CONSTANT:
|
||||
- case HLSL_IR_EXPR:
|
||||
- case HLSL_IR_SWIZZLE:
|
||||
- case HLSL_IR_LOAD:
|
||||
- case HLSL_IR_INDEX:
|
||||
- continue;
|
||||
- case HLSL_IR_STORE:
|
||||
- if (hlsl_ir_store(node)->lhs.var->is_synthetic)
|
||||
- break;
|
||||
- /* fall-through */
|
||||
- case HLSL_IR_CALL:
|
||||
- case HLSL_IR_IF:
|
||||
- case HLSL_IR_LOOP:
|
||||
- case HLSL_IR_JUMP:
|
||||
- case HLSL_IR_RESOURCE_LOAD:
|
||||
- case HLSL_IR_RESOURCE_STORE:
|
||||
- case HLSL_IR_SWITCH:
|
||||
- case HLSL_IR_STATEBLOCK_CONSTANT:
|
||||
- hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
||||
- "Expected literal expression.");
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (!hlsl_clone_block(ctx, &expr, &ctx->static_initializers))
|
||||
- return ret;
|
||||
- hlsl_block_add_block(&expr, block);
|
||||
-
|
||||
- if (!add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc))
|
||||
- {
|
||||
- hlsl_block_cleanup(&expr);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- /* Wrap the node into a src to allow the reference to survive the multiple const passes. */
|
||||
- hlsl_src_from_node(&src, node_from_block(&expr));
|
||||
- hlsl_run_const_passes(ctx, &expr);
|
||||
- node = src.node;
|
||||
- hlsl_src_remove(&src);
|
||||
-
|
||||
- if (node->type == HLSL_IR_CONSTANT)
|
||||
- {
|
||||
- constant = hlsl_ir_constant(node);
|
||||
- ret = constant->value.u[0];
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
||||
- "Failed to evaluate constant expression.");
|
||||
- }
|
||||
-
|
||||
- hlsl_block_cleanup(&expr);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, struct hlsl_block *block,
|
||||
- const struct vkd3d_shader_location *loc)
|
||||
-{
|
||||
- union hlsl_constant_value_component res;
|
||||
-
|
||||
- res = evaluate_static_expression(ctx, block, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc);
|
||||
- return res.u;
|
||||
-}
|
||||
-
|
||||
static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
|
||||
{
|
||||
/* Scalar vars can be converted to pretty much everything */
|
||||
@@ -4676,6 +4688,20 @@ static bool intrinsic_d3dcolor_to_ubyte4(struct hlsl_ctx *ctx,
|
||||
return true;
|
||||
}
|
||||
|
||||
+static bool intrinsic_GetRenderTargetSampleCount(struct hlsl_ctx *ctx,
|
||||
+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
||||
+{
|
||||
+ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0};
|
||||
+ struct hlsl_ir_node *expr;
|
||||
+
|
||||
+ if (!(expr = hlsl_new_expr(ctx, HLSL_OP0_RASTERIZER_SAMPLE_COUNT,
|
||||
+ operands, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc)))
|
||||
+ return false;
|
||||
+ hlsl_block_add_instr(params->instrs, expr);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static const struct intrinsic_function
|
||||
{
|
||||
const char *name;
|
||||
@@ -4688,6 +4714,7 @@ intrinsic_functions[] =
|
||||
{
|
||||
/* Note: these entries should be kept in alphabetical order. */
|
||||
{"D3DCOLORtoUBYTE4", 1, true, intrinsic_d3dcolor_to_ubyte4},
|
||||
+ {"GetRenderTargetSampleCount", 0, true, intrinsic_GetRenderTargetSampleCount},
|
||||
{"abs", 1, true, intrinsic_abs},
|
||||
{"acos", 1, true, intrinsic_acos},
|
||||
{"all", 1, true, intrinsic_all},
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||||
index f9f5c8ed58a..7e4f168675e 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||||
@@ -1981,6 +1981,76 @@ bool hlsl_copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *bloc
|
||||
return progress;
|
||||
}
|
||||
|
||||
+enum validation_result
|
||||
+{
|
||||
+ DEREF_VALIDATION_OK,
|
||||
+ DEREF_VALIDATION_OUT_OF_BOUNDS,
|
||||
+ DEREF_VALIDATION_NOT_CONSTANT,
|
||||
+};
|
||||
+
|
||||
+static enum validation_result validate_component_index_range_from_deref(struct hlsl_ctx *ctx,
|
||||
+ const struct hlsl_deref *deref)
|
||||
+{
|
||||
+ struct hlsl_type *type = deref->var->data_type;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < deref->path_len; ++i)
|
||||
+ {
|
||||
+ struct hlsl_ir_node *path_node = deref->path[i].node;
|
||||
+ unsigned int idx = 0;
|
||||
+
|
||||
+ assert(path_node);
|
||||
+ if (path_node->type != HLSL_IR_CONSTANT)
|
||||
+ return DEREF_VALIDATION_NOT_CONSTANT;
|
||||
+
|
||||
+ /* We should always have generated a cast to UINT. */
|
||||
+ assert(path_node->data_type->class == HLSL_CLASS_SCALAR
|
||||
+ && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT);
|
||||
+
|
||||
+ idx = hlsl_ir_constant(path_node)->value.u[0].u;
|
||||
+
|
||||
+ switch (type->class)
|
||||
+ {
|
||||
+ case HLSL_CLASS_VECTOR:
|
||||
+ if (idx >= type->dimx)
|
||||
+ {
|
||||
+ hlsl_error(ctx, &path_node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
|
||||
+ "Vector index is out of bounds. %u/%u", idx, type->dimx);
|
||||
+ return DEREF_VALIDATION_OUT_OF_BOUNDS;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case HLSL_CLASS_MATRIX:
|
||||
+ if (idx >= hlsl_type_major_size(type))
|
||||
+ {
|
||||
+ hlsl_error(ctx, &path_node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
|
||||
+ "Matrix index is out of bounds. %u/%u", idx, hlsl_type_major_size(type));
|
||||
+ return DEREF_VALIDATION_OUT_OF_BOUNDS;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case HLSL_CLASS_ARRAY:
|
||||
+ if (idx >= type->e.array.elements_count)
|
||||
+ {
|
||||
+ hlsl_error(ctx, &path_node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
|
||||
+ "Array index is out of bounds. %u/%u", idx, type->e.array.elements_count);
|
||||
+ return DEREF_VALIDATION_OUT_OF_BOUNDS;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case HLSL_CLASS_STRUCT:
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ vkd3d_unreachable();
|
||||
+ }
|
||||
+
|
||||
+ type = hlsl_get_element_type_from_path_index(ctx, type, path_node);
|
||||
+ }
|
||||
+
|
||||
+ return DEREF_VALIDATION_OK;
|
||||
+}
|
||||
+
|
||||
static void note_non_static_deref_expressions(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
|
||||
const char *usage)
|
||||
{
|
||||
@@ -1998,60 +2068,77 @@ static void note_non_static_deref_expressions(struct hlsl_ctx *ctx, const struct
|
||||
}
|
||||
}
|
||||
|
||||
-static bool validate_static_object_references(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
|
||||
+static bool validate_dereferences(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
|
||||
void *context)
|
||||
{
|
||||
- unsigned int start, count;
|
||||
-
|
||||
- if (instr->type == HLSL_IR_RESOURCE_LOAD)
|
||||
+ switch (instr->type)
|
||||
{
|
||||
- struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr);
|
||||
-
|
||||
- if (!load->resource.var->is_uniform)
|
||||
+ case HLSL_IR_RESOURCE_LOAD:
|
||||
{
|
||||
- hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
- "Loaded resource must have a single uniform source.");
|
||||
+ struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr);
|
||||
+
|
||||
+ if (!load->resource.var->is_uniform)
|
||||
+ {
|
||||
+ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
+ "Loaded resource must have a single uniform source.");
|
||||
+ }
|
||||
+ else if (validate_component_index_range_from_deref(ctx, &load->resource) == DEREF_VALIDATION_NOT_CONSTANT)
|
||||
+ {
|
||||
+ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
+ "Loaded resource from \"%s\" must be determinable at compile time.",
|
||||
+ load->resource.var->name);
|
||||
+ note_non_static_deref_expressions(ctx, &load->resource, "loaded resource");
|
||||
+ }
|
||||
+
|
||||
+ if (load->sampler.var)
|
||||
+ {
|
||||
+ if (!load->sampler.var->is_uniform)
|
||||
+ {
|
||||
+ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
+ "Resource load sampler must have a single uniform source.");
|
||||
+ }
|
||||
+ else if (validate_component_index_range_from_deref(ctx, &load->sampler) == DEREF_VALIDATION_NOT_CONSTANT)
|
||||
+ {
|
||||
+ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
+ "Resource load sampler from \"%s\" must be determinable at compile time.",
|
||||
+ load->sampler.var->name);
|
||||
+ note_non_static_deref_expressions(ctx, &load->sampler, "resource load sampler");
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
}
|
||||
- else if (!hlsl_component_index_range_from_deref(ctx, &load->resource, &start, &count))
|
||||
+ case HLSL_IR_RESOURCE_STORE:
|
||||
{
|
||||
- hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
- "Loaded resource from \"%s\" must be determinable at compile time.",
|
||||
- load->resource.var->name);
|
||||
- note_non_static_deref_expressions(ctx, &load->resource, "loaded resource");
|
||||
- }
|
||||
+ struct hlsl_ir_resource_store *store = hlsl_ir_resource_store(instr);
|
||||
|
||||
- if (load->sampler.var)
|
||||
- {
|
||||
- if (!load->sampler.var->is_uniform)
|
||||
+ if (!store->resource.var->is_uniform)
|
||||
{
|
||||
hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
- "Resource load sampler must have a single uniform source.");
|
||||
+ "Accessed resource must have a single uniform source.");
|
||||
}
|
||||
- else if (!hlsl_component_index_range_from_deref(ctx, &load->sampler, &start, &count))
|
||||
+ else if (validate_component_index_range_from_deref(ctx, &store->resource) == DEREF_VALIDATION_NOT_CONSTANT)
|
||||
{
|
||||
hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
- "Resource load sampler from \"%s\" must be determinable at compile time.",
|
||||
- load->sampler.var->name);
|
||||
- note_non_static_deref_expressions(ctx, &load->sampler, "resource load sampler");
|
||||
+ "Accessed resource from \"%s\" must be determinable at compile time.",
|
||||
+ store->resource.var->name);
|
||||
+ note_non_static_deref_expressions(ctx, &store->resource, "accessed resource");
|
||||
}
|
||||
+ break;
|
||||
}
|
||||
- }
|
||||
- else if (instr->type == HLSL_IR_RESOURCE_STORE)
|
||||
- {
|
||||
- struct hlsl_ir_resource_store *store = hlsl_ir_resource_store(instr);
|
||||
-
|
||||
- if (!store->resource.var->is_uniform)
|
||||
+ case HLSL_IR_LOAD:
|
||||
{
|
||||
- hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
- "Accessed resource must have a single uniform source.");
|
||||
+ struct hlsl_ir_load *load = hlsl_ir_load(instr);
|
||||
+ validate_component_index_range_from_deref(ctx, &load->src);
|
||||
+ break;
|
||||
}
|
||||
- else if (!hlsl_component_index_range_from_deref(ctx, &store->resource, &start, &count))
|
||||
+ case HLSL_IR_STORE:
|
||||
{
|
||||
- hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF,
|
||||
- "Accessed resource from \"%s\" must be determinable at compile time.",
|
||||
- store->resource.var->name);
|
||||
- note_non_static_deref_expressions(ctx, &store->resource, "accessed resource");
|
||||
+ struct hlsl_ir_store *store = hlsl_ir_store(instr);
|
||||
+ validate_component_index_range_from_deref(ctx, &store->lhs);
|
||||
+ break;
|
||||
}
|
||||
+ default:
|
||||
+ break;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -5203,21 +5290,13 @@ bool hlsl_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hl
|
||||
{
|
||||
case HLSL_CLASS_VECTOR:
|
||||
if (idx >= type->dimx)
|
||||
- {
|
||||
- hlsl_error(ctx, &path_node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
|
||||
- "Vector index is out of bounds. %u/%u", idx, type->dimx);
|
||||
return false;
|
||||
- }
|
||||
*start += idx;
|
||||
break;
|
||||
|
||||
case HLSL_CLASS_MATRIX:
|
||||
if (idx >= hlsl_type_major_size(type))
|
||||
- {
|
||||
- hlsl_error(ctx, &path_node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
|
||||
- "Matrix index is out of bounds. %u/%u", idx, hlsl_type_major_size(type));
|
||||
return false;
|
||||
- }
|
||||
if (hlsl_type_is_row_major(type))
|
||||
*start += idx * type->dimx;
|
||||
else
|
||||
@@ -5226,11 +5305,7 @@ bool hlsl_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hl
|
||||
|
||||
case HLSL_CLASS_ARRAY:
|
||||
if (idx >= type->e.array.elements_count)
|
||||
- {
|
||||
- hlsl_error(ctx, &path_node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
|
||||
- "Array index is out of bounds. %u/%u", idx, type->e.array.elements_count);
|
||||
return false;
|
||||
- }
|
||||
*start += idx * hlsl_type_component_count(type->e.array.type);
|
||||
break;
|
||||
|
||||
@@ -5635,6 +5710,222 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
|
||||
sm1_generate_vsir_signature(ctx, program);
|
||||
}
|
||||
|
||||
+static struct hlsl_ir_jump *loop_unrolling_find_jump(struct hlsl_block *block, struct hlsl_ir_node *stop_point,
|
||||
+ struct hlsl_block **found_block)
|
||||
+{
|
||||
+ struct hlsl_ir_node *node;
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY(node, &block->instrs, struct hlsl_ir_node, entry)
|
||||
+ {
|
||||
+ if (node == stop_point)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (node->type == HLSL_IR_IF)
|
||||
+ {
|
||||
+ struct hlsl_ir_if *iff = hlsl_ir_if(node);
|
||||
+ struct hlsl_ir_jump *jump = NULL;
|
||||
+
|
||||
+ if ((jump = loop_unrolling_find_jump(&iff->then_block, stop_point, found_block)))
|
||||
+ return jump;
|
||||
+ if ((jump = loop_unrolling_find_jump(&iff->else_block, stop_point, found_block)))
|
||||
+ return jump;
|
||||
+ }
|
||||
+ else if (node->type == HLSL_IR_JUMP)
|
||||
+ {
|
||||
+ struct hlsl_ir_jump *jump = hlsl_ir_jump(node);
|
||||
+
|
||||
+ if (jump->type == HLSL_IR_JUMP_BREAK || jump->type == HLSL_IR_JUMP_CONTINUE)
|
||||
+ {
|
||||
+ *found_block = block;
|
||||
+ return jump;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static unsigned int loop_unrolling_get_max_iterations(struct hlsl_ctx *ctx, struct hlsl_ir_loop *loop)
|
||||
+{
|
||||
+ /* Always use the explicit limit if it has been passed. */
|
||||
+ if (loop->unroll_limit)
|
||||
+ return loop->unroll_limit;
|
||||
+
|
||||
+ /* All SMs will default to 1024 if [unroll] has been specified without an explicit limit. */
|
||||
+ if (loop->unroll_type == HLSL_IR_LOOP_FORCE_UNROLL)
|
||||
+ return 1024;
|
||||
+
|
||||
+ /* SM4 limits implicit unrolling to 254 iterations. */
|
||||
+ if (hlsl_version_ge(ctx, 4, 0))
|
||||
+ return 254;
|
||||
+
|
||||
+ /* SM<3 implicitly unrolls up to 1024 iterations. */
|
||||
+ return 1024;
|
||||
+}
|
||||
+
|
||||
+static bool loop_unrolling_unroll_loop(struct hlsl_ctx *ctx, struct hlsl_block *block,
|
||||
+ struct hlsl_block *loop_parent, struct hlsl_ir_loop *loop)
|
||||
+{
|
||||
+ unsigned int max_iterations, i;
|
||||
+
|
||||
+ max_iterations = loop_unrolling_get_max_iterations(ctx, loop);
|
||||
+
|
||||
+ for (i = 0; i < max_iterations; ++i)
|
||||
+ {
|
||||
+ struct hlsl_block tmp_dst, *jump_block;
|
||||
+ struct hlsl_ir_jump *jump = NULL;
|
||||
+
|
||||
+ if (!hlsl_clone_block(ctx, &tmp_dst, &loop->body))
|
||||
+ return false;
|
||||
+ list_move_before(&loop->node.entry, &tmp_dst.instrs);
|
||||
+ hlsl_block_cleanup(&tmp_dst);
|
||||
+
|
||||
+ hlsl_run_const_passes(ctx, block);
|
||||
+
|
||||
+ if ((jump = loop_unrolling_find_jump(loop_parent, &loop->node, &jump_block)))
|
||||
+ {
|
||||
+ enum hlsl_ir_jump_type type = jump->type;
|
||||
+
|
||||
+ if (jump_block != loop_parent)
|
||||
+ {
|
||||
+ if (loop->unroll_type == HLSL_IR_LOOP_FORCE_UNROLL)
|
||||
+ hlsl_error(ctx, &jump->node.loc, VKD3D_SHADER_ERROR_HLSL_FAILED_FORCED_UNROLL,
|
||||
+ "Unable to unroll loop, unrolling loops with conditional jumps is currently not supported.");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ list_move_slice_tail(&tmp_dst.instrs, &jump->node.entry, list_prev(&loop_parent->instrs, &loop->node.entry));
|
||||
+ hlsl_block_cleanup(&tmp_dst);
|
||||
+
|
||||
+ if (type == HLSL_IR_JUMP_BREAK)
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Native will not emit an error if max_iterations has been reached with an
|
||||
+ * explicit limit. It also will not insert a loop if there are iterations left
|
||||
+ * i.e [unroll(4)] for (i = 0; i < 8; ++i)) */
|
||||
+ if (!loop->unroll_limit && i == max_iterations)
|
||||
+ {
|
||||
+ if (loop->unroll_type == HLSL_IR_LOOP_FORCE_UNROLL)
|
||||
+ hlsl_error(ctx, &loop->node.loc, VKD3D_SHADER_ERROR_HLSL_FAILED_FORCED_UNROLL,
|
||||
+ "Unable to unroll loop, maximum iterations reached (%u).", max_iterations);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ list_remove(&loop->node.entry);
|
||||
+ hlsl_free_instr(&loop->node);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * loop_unrolling_find_unrollable_loop() is not the normal way to do things;
|
||||
+ * normal passes simply iterate over the whole block and apply a transformation
|
||||
+ * to every relevant instruction. However, loop unrolling can fail, and we want
|
||||
+ * to leave the loop in its previous state in that case. That isn't a problem by
|
||||
+ * itself, except that loop unrolling needs copy-prop in order to work properly,
|
||||
+ * and copy-prop state at the time of the loop depends on the rest of the program
|
||||
+ * up to that point. This means we need to clone the whole program, and at that
|
||||
+ * point we have to search it again anyway to find the clone of the loop we were
|
||||
+ * going to unroll.
|
||||
+ *
|
||||
+ * FIXME: Ideally we wouldn't clone the whole program; instead we would run copyprop
|
||||
+ * up until the loop instruction, clone just that loop, then use copyprop again
|
||||
+ * with the saved state after unrolling. However, copyprop currently isn't built
|
||||
+ * for that yet [notably, it still relies on indices]. Note also this still doesn't
|
||||
+ * really let us use transform_ir() anyway [since we don't have a good way to say
|
||||
+ * "copyprop from the beginning of the program up to the instruction we're
|
||||
+ * currently processing" from the callback]; we'd have to use a dedicated
|
||||
+ * recursive function instead. */
|
||||
+static struct hlsl_ir_loop *loop_unrolling_find_unrollable_loop(struct hlsl_ctx *ctx, struct hlsl_block *block,
|
||||
+ struct hlsl_block **containing_block)
|
||||
+{
|
||||
+ struct hlsl_ir_node *instr;
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
|
||||
+ {
|
||||
+ switch (instr->type)
|
||||
+ {
|
||||
+ case HLSL_IR_LOOP:
|
||||
+ {
|
||||
+ struct hlsl_ir_loop *nested_loop;
|
||||
+ struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
|
||||
+
|
||||
+ if ((nested_loop = loop_unrolling_find_unrollable_loop(ctx, &loop->body, containing_block)))
|
||||
+ return nested_loop;
|
||||
+
|
||||
+ if (loop->unroll_type == HLSL_IR_LOOP_UNROLL || loop->unroll_type == HLSL_IR_LOOP_FORCE_UNROLL)
|
||||
+ {
|
||||
+ *containing_block = block;
|
||||
+ return loop;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ case HLSL_IR_IF:
|
||||
+ {
|
||||
+ struct hlsl_ir_loop *loop;
|
||||
+ struct hlsl_ir_if *iff = hlsl_ir_if(instr);
|
||||
+
|
||||
+ if ((loop = loop_unrolling_find_unrollable_loop(ctx, &iff->then_block, containing_block)))
|
||||
+ return loop;
|
||||
+ if ((loop = loop_unrolling_find_unrollable_loop(ctx, &iff->else_block, containing_block)))
|
||||
+ return loop;
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ case HLSL_IR_SWITCH:
|
||||
+ {
|
||||
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
|
||||
+ struct hlsl_ir_switch_case *c;
|
||||
+ struct hlsl_ir_loop *loop;
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||
+ {
|
||||
+ if ((loop = loop_unrolling_find_unrollable_loop(ctx, &c->body, containing_block)))
|
||||
+ return loop;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void transform_unroll_loops(struct hlsl_ctx *ctx, struct hlsl_block *block)
|
||||
+{
|
||||
+ while (true)
|
||||
+ {
|
||||
+ struct hlsl_block clone, *containing_block;
|
||||
+ struct hlsl_ir_loop *loop, *cloned_loop;
|
||||
+
|
||||
+ if (!(loop = loop_unrolling_find_unrollable_loop(ctx, block, &containing_block)))
|
||||
+ return;
|
||||
+
|
||||
+ if (!hlsl_clone_block(ctx, &clone, block))
|
||||
+ return;
|
||||
+
|
||||
+ cloned_loop = loop_unrolling_find_unrollable_loop(ctx, &clone, &containing_block);
|
||||
+ assert(cloned_loop);
|
||||
+
|
||||
+ if (!loop_unrolling_unroll_loop(ctx, &clone, containing_block, cloned_loop))
|
||||
+ {
|
||||
+ hlsl_block_cleanup(&clone);
|
||||
+ loop->unroll_type = HLSL_IR_LOOP_FORCE_LOOP;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ hlsl_block_cleanup(block);
|
||||
+ hlsl_block_init(block);
|
||||
+ hlsl_block_add_block(block, &clone);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
|
||||
enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out)
|
||||
{
|
||||
@@ -5721,6 +6012,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
|
||||
hlsl_transform_ir(ctx, lower_discard_neg, body, NULL);
|
||||
}
|
||||
|
||||
+ transform_unroll_loops(ctx, body);
|
||||
hlsl_run_const_passes(ctx, body);
|
||||
|
||||
remove_unreachable_code(ctx, body);
|
||||
@@ -5730,7 +6022,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
|
||||
lower_ir(ctx, lower_casts_to_bool, body);
|
||||
lower_ir(ctx, lower_int_dot, body);
|
||||
|
||||
- hlsl_transform_ir(ctx, validate_static_object_references, body, NULL);
|
||||
+ hlsl_transform_ir(ctx, validate_dereferences, body, NULL);
|
||||
hlsl_transform_ir(ctx, track_object_components_sampler_dim, body, NULL);
|
||||
if (profile->major_version >= 4)
|
||||
hlsl_transform_ir(ctx, lower_combined_samples, body, NULL);
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
||||
index ca7cdfd5217..a7c37215e5e 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
||||
@@ -2762,6 +2762,7 @@ bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem
|
||||
{"depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3DSPR_DEPTHOUT, false},
|
||||
{"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3DSPR_DEPTHOUT, false},
|
||||
{"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, VKD3DSPR_OUTPUT, true},
|
||||
+ {"sv_coverage", true, VKD3D_SHADER_TYPE_PIXEL, VKD3DSPR_SAMPLEMASK, false},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(register_table); ++i)
|
||||
@@ -2817,6 +2818,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant
|
||||
{"depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH},
|
||||
{"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET},
|
||||
{"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH},
|
||||
+ {"sv_coverage", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_COVERAGE},
|
||||
|
||||
{"sv_position", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_UNDEFINED},
|
||||
{"sv_vertexid", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_VERTEX_ID},
|
||||
@@ -5042,6 +5044,25 @@ static void write_sm4_store_uav_typed(const struct tpf_writer *tpf, const struct
|
||||
write_sm4_instruction(tpf, &instr);
|
||||
}
|
||||
|
||||
+static void write_sm4_rasterizer_sample_count(const struct tpf_writer *tpf, const struct hlsl_ir_node *dst)
|
||||
+{
|
||||
+ struct sm4_instruction instr;
|
||||
+
|
||||
+ memset(&instr, 0, sizeof(instr));
|
||||
+ instr.opcode = VKD3D_SM4_OP_SAMPLE_INFO;
|
||||
+ instr.extra_bits |= VKD3DSI_SAMPLE_INFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT;
|
||||
+
|
||||
+ sm4_dst_from_node(&instr.dsts[0], dst);
|
||||
+ instr.dst_count = 1;
|
||||
+
|
||||
+ instr.srcs[0].reg.type = VKD3DSPR_RASTERIZER;
|
||||
+ instr.srcs[0].reg.dimension = VSIR_DIMENSION_VEC4;
|
||||
+ instr.srcs[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
|
||||
+ instr.src_count = 1;
|
||||
+
|
||||
+ write_sm4_instruction(tpf, &instr);
|
||||
+}
|
||||
+
|
||||
static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_expr *expr)
|
||||
{
|
||||
const struct hlsl_ir_node *arg1 = expr->operands[0].node;
|
||||
@@ -5057,6 +5078,14 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
|
||||
|
||||
switch (expr->op)
|
||||
{
|
||||
+ case HLSL_OP0_RASTERIZER_SAMPLE_COUNT:
|
||||
+ if (tpf->ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL && hlsl_version_ge(tpf->ctx, 4, 1))
|
||||
+ write_sm4_rasterizer_sample_count(tpf, &expr->node);
|
||||
+ else
|
||||
+ hlsl_error(tpf->ctx, &expr->node.loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE,
|
||||
+ "GetRenderTargetSampleCount() can only be used from a pixel shader using version 4.1 or higher.");
|
||||
+ break;
|
||||
+
|
||||
case HLSL_OP1_ABS:
|
||||
switch (dst_type->e.numeric.type)
|
||||
{
|
||||
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
||||
index c79f845b675..96e613669a6 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
||||
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
||||
@@ -152,6 +152,7 @@ enum vkd3d_shader_error
|
||||
VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE = 5029,
|
||||
VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER = 5030,
|
||||
VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY = 5031,
|
||||
+ VKD3D_SHADER_ERROR_HLSL_FAILED_FORCED_UNROLL = 5032,
|
||||
|
||||
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
|
||||
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
|
||||
diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c
|
||||
index db2d87428bb..7d7f40c0953 100644
|
||||
--- a/libs/vkd3d/libs/vkd3d/resource.c
|
||||
+++ b/libs/vkd3d/libs/vkd3d/resource.c
|
||||
@@ -4349,7 +4349,11 @@ static HRESULT d3d12_descriptor_heap_init(struct d3d12_descriptor_heap *descript
|
||||
return hr;
|
||||
|
||||
descriptor_heap->use_vk_heaps = device->use_vk_heaps && (desc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
|
||||
- d3d12_descriptor_heap_vk_descriptor_sets_init(descriptor_heap, device, desc);
|
||||
+ if (FAILED(hr = d3d12_descriptor_heap_vk_descriptor_sets_init(descriptor_heap, device, desc)))
|
||||
+ {
|
||||
+ vkd3d_private_store_destroy(&descriptor_heap->private_store);
|
||||
+ return hr;
|
||||
+ }
|
||||
vkd3d_mutex_init(&descriptor_heap->vk_sets_mutex);
|
||||
|
||||
d3d12_device_add_ref(descriptor_heap->device = device);
|
||||
--
|
||||
2.43.0
|
||||
|
Loading…
Reference in New Issue
Block a user