You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-12-15 08:03:15 -08:00
2196 lines
87 KiB
Diff
2196 lines
87 KiB
Diff
From b499bbecc02660828dc953befe392dd7e9bcf273 Mon Sep 17 00:00:00 2001
|
|
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
|
Date: Sat, 13 Dec 2025 18:48:15 +1100
|
|
Subject: [PATCH] Updated vkd3d to 47a1d150c360aa94a141056263c8765cdf64deb7.
|
|
|
|
---
|
|
libs/vkd3d/libs/vkd3d-shader/dxil.c | 346 ++++++++++++------
|
|
libs/vkd3d/libs/vkd3d-shader/fx.c | 341 +++++++++++++----
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 179 ++++-----
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 46 ++-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 234 ++++++++----
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 21 +-
|
|
.../libs/vkd3d-shader/vkd3d_shader_main.c | 25 +-
|
|
.../libs/vkd3d-shader/vkd3d_shader_private.h | 3 +
|
|
8 files changed, 823 insertions(+), 372 deletions(-)
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
index f73106d79b2..928a79a7300 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
@@ -5270,20 +5270,31 @@ static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op,
|
|
}
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_binary(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_params;
|
|
uint32_t type_flags;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type, &type_flags));
|
|
- if (!(src_params = instruction_src_params_alloc(ins, 2, sm6)))
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
+ return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, map_dx_binary_op(op, operands[0]->type, &type_flags));
|
|
+
|
|
+ if (!(src_params = instruction_src_params_alloc(ins, 2, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
- src_param_init_from_value(&src_params[0], operands[0], type_flags, sm6);
|
|
- src_param_init_from_value(&src_params[1], operands[1], type_flags, sm6);
|
|
+ }
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, type_flags, sm6);
|
|
+ src_param_init_from_value(&src_params[0], operands[0], type_flags, dxil);
|
|
+ src_param_init_from_value(&src_params[1], operands[1], type_flags, dxil);
|
|
+
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, type_flags, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6)
|
|
@@ -5567,28 +5578,39 @@ static void sm6_parser_dcl_register_builtin(struct sm6_parser *dxil, enum vkd3d_
|
|
}
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, struct vkd3d_shader_instruction *ins,
|
|
+static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *dxil, struct function_emission_state *state,
|
|
enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, bool scalar)
|
|
{
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_param;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV);
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
+ return;
|
|
|
|
- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_MOV);
|
|
+
|
|
+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, reg_type, data_type, 1);
|
|
+ }
|
|
+
|
|
+ sm6_parser_dcl_register_builtin(dxil, VSIR_OP_DCL_INPUT, reg_type, data_type, 1);
|
|
vsir_register_init(&src_param->reg, reg_type, data_type, 0);
|
|
if (!scalar)
|
|
src_param->reg.dimension = VSIR_DIMENSION_VEC4;
|
|
src_param_init(src_param);
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_coverage(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_coverage(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_COVERAGE, VSIR_DATA_U32, false);
|
|
+ sm6_parser_emit_dx_input_register_mov(dxil, state, VKD3DSPR_COVERAGE, VSIR_DATA_U32, false);
|
|
}
|
|
|
|
static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6,
|
|
@@ -5619,7 +5641,6 @@ static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_pa
|
|
static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
enum vkd3d_shader_descriptor_type type;
|
|
const struct sm6_descriptor_info *d;
|
|
struct sm6_value *dst;
|
|
@@ -5629,7 +5650,6 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int
|
|
id = sm6_value_get_constant_uint(operands[1], sm6);
|
|
if (!(d = sm6_parser_get_descriptor(sm6, type, id, operands[2])))
|
|
{
|
|
- WARN("Failed to find resource type %#x, id %#x.\n", type, id);
|
|
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
"Descriptor for resource type %#x, id %#x was not found.", type, id);
|
|
return;
|
|
@@ -5641,81 +5661,103 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int
|
|
dst->u.handle.index = operands[2];
|
|
dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3], sm6);
|
|
|
|
- /* NOP is used to flag no instruction emitted. */
|
|
- ins->opcode = VSIR_OP_NOP;
|
|
+ /* Well, not really, but the point here is that we pushed all the
|
|
+ * instructions we had to (i.e., none), and sm6_parser_function_init()
|
|
+ * doesn't have to do it for us. */
|
|
+ state->pushed_instruction = true;
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_stream(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_param;
|
|
unsigned int i;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, (op == DX_CUT_STREAM) ? VSIR_OP_CUT_STREAM : VSIR_OP_EMIT_STREAM);
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
+ return;
|
|
|
|
- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, (op == DX_CUT_STREAM) ? VSIR_OP_CUT_STREAM : VSIR_OP_EMIT_STREAM);
|
|
+
|
|
+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
|
|
- i = sm6_value_get_constant_uint(operands[0], sm6);
|
|
+ i = sm6_value_get_constant_uint(operands[0], dxil);
|
|
if (i >= MAX_GS_OUTPUT_STREAMS)
|
|
- {
|
|
- WARN("Invalid stream index %u.\n", i);
|
|
- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
"Output stream index %u is invalid.", i);
|
|
- }
|
|
|
|
register_init_with_id(&src_param->reg, VKD3DSPR_STREAM, VSIR_DATA_UNUSED, i);
|
|
src_param_init(src_param);
|
|
|
|
if (op == DX_EMIT_THEN_CUT_STREAM)
|
|
- {
|
|
- ++state->ins;
|
|
- ++state->function->instructions.count;
|
|
- sm6_parser_emit_dx_stream(sm6, DX_CUT_STREAM, operands, state);
|
|
- }
|
|
+ sm6_parser_emit_dx_stream(dxil, DX_CUT_STREAM, operands, state);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_discard(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_param;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DISCARD);
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
+ return;
|
|
|
|
- if ((src_param = instruction_src_params_alloc(ins, 1, sm6)))
|
|
- src_param_init_from_value(src_param, operands[0], 0, sm6);
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_DISCARD);
|
|
+
|
|
+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ src_param_init_from_value(src_param, operands[0], 0, dxil);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_domain_location(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_param;
|
|
unsigned int component_idx;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV);
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
+ return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_MOV);
|
|
|
|
- if ((component_idx = sm6_value_get_constant_uint(operands[0], sm6)) >= 3)
|
|
+ if ((component_idx = sm6_value_get_constant_uint(operands[0], dxil)) >= 3)
|
|
{
|
|
- WARN("Invalid component index %u.\n", component_idx);
|
|
- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
"Invalid domain location component index %u.", component_idx);
|
|
component_idx = 0;
|
|
}
|
|
|
|
- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 3);
|
|
+ }
|
|
+
|
|
+ sm6_parser_dcl_register_builtin(dxil, VSIR_OP_DCL_INPUT, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 3);
|
|
vsir_register_init(&src_param->reg, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 0);
|
|
src_param->reg.dimension = VSIR_DIMENSION_VEC4;
|
|
src_param_init_scalar(src_param, component_idx);
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_dot(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
struct vkd3d_shader_instruction *ins;
|
|
@@ -5742,26 +5784,36 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc
|
|
vkd3d_unreachable();
|
|
}
|
|
|
|
- if (!sm6_parser_emit_composite_construct(sm6, &operands[0], component_count, state, ®s[0]))
|
|
+ if (!sm6_parser_emit_composite_construct(dxil, &operands[0], component_count, state, ®s[0]))
|
|
return;
|
|
- if (!sm6_parser_emit_composite_construct(sm6, &operands[component_count], component_count, state, ®s[1]))
|
|
+ if (!sm6_parser_emit_composite_construct(dxil, &operands[component_count], component_count, state, ®s[1]))
|
|
return;
|
|
|
|
- ins = state->ins;
|
|
- vsir_instruction_init(ins, &sm6->p.location, opcode);
|
|
- if (!(src_params = instruction_src_params_alloc(ins, 2, sm6)))
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, opcode);
|
|
+
|
|
+ if (!(src_params = instruction_src_params_alloc(ins, 2, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
+ return;
|
|
+ }
|
|
+
|
|
src_param_init_vector_from_reg(&src_params[0], ®s[0]);
|
|
src_param_init_vector_from_reg(&src_params[1], ®s[1]);
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
const struct shader_signature *signature;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
unsigned int row_index, column_index;
|
|
struct vsir_src_operand *src_params;
|
|
const struct signature_element *e;
|
|
@@ -5772,7 +5824,6 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri
|
|
signature = &sm6->program->input_signature;
|
|
if (row_index >= signature->element_count)
|
|
{
|
|
- WARN("Invalid row index %u.\n", row_index);
|
|
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
"Invalid input row index %u for an attribute evaluation.", row_index);
|
|
return;
|
|
@@ -5781,17 +5832,24 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri
|
|
e = &signature->elements[row_index];
|
|
if (column_index >= VKD3D_VEC4_SIZE || !(e->mask & (1 << column_index)))
|
|
{
|
|
- WARN("Invalid column index %u.\n", column_index);
|
|
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
"Invalid input column index %u for an attribute evaluation.", column_index);
|
|
return;
|
|
}
|
|
|
|
+ if (!(ins = sm6_parser_add_function_instruction(sm6, state)))
|
|
+ return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
vsir_instruction_init(ins, &sm6->p.location, (op == DX_EVAL_CENTROID)
|
|
? VSIR_OP_EVAL_CENTROID : VSIR_OP_EVAL_SAMPLE_INDEX);
|
|
|
|
if (!(src_params = instruction_src_params_alloc(ins, 1 + (op == DX_EVAL_SAMPLE_INDEX), sm6)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
|
|
src_params[0].reg = sm6->input_params[row_index].reg;
|
|
src_param_init_scalar(&src_params[0], column_index);
|
|
@@ -5801,29 +5859,41 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri
|
|
if (op == DX_EVAL_SAMPLE_INDEX)
|
|
src_param_init_from_value(&src_params[1], operands[3], 0, sm6);
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, sm6))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_fabs(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_param;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_ABS);
|
|
- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
return;
|
|
- src_param_init_from_value(src_param, operands[0], 0, sm6);
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_ABS);
|
|
+
|
|
+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ src_param_init_from_value(src_param, operands[0], 0, dxil);
|
|
+
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
unsigned int component_count = 3, component_idx = 0;
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
enum vkd3d_shader_register_type reg_type;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_param;
|
|
|
|
switch (op)
|
|
@@ -5845,17 +5915,29 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i
|
|
vkd3d_unreachable();
|
|
}
|
|
|
|
- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, reg_type, VSIR_DATA_U32, component_count);
|
|
- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV);
|
|
- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ sm6_parser_dcl_register_builtin(dxil, VSIR_OP_DCL_INPUT, reg_type, VSIR_DATA_U32, component_count);
|
|
+
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_MOV);
|
|
+
|
|
+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
+ return;
|
|
+ }
|
|
+
|
|
vsir_register_init(&src_param->reg, reg_type, VSIR_DATA_U32, 0);
|
|
src_param->reg.dimension = VSIR_DIMENSION_VEC4;
|
|
if (component_count > 1)
|
|
- component_idx = sm6_value_get_constant_uint(operands[0], sm6);
|
|
+ component_idx = sm6_value_get_constant_uint(operands[0], dxil);
|
|
src_param_init_scalar(src_param, component_idx);
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, const struct sm6_type *type)
|
|
@@ -5874,30 +5956,41 @@ static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, co
|
|
}
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_ma(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_params;
|
|
unsigned int i;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_ma_op(op, operands[0]->type));
|
|
- if (!(src_params = instruction_src_params_alloc(ins, 3, sm6)))
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
+ return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, sm6_dx_map_ma_op(op, operands[0]->type));
|
|
+
|
|
+ if (!(src_params = instruction_src_params_alloc(ins, 3, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
+
|
|
for (i = 0; i < 3; ++i)
|
|
{
|
|
- src_param_init_from_value(&src_params[i], operands[i], 0, sm6);
|
|
+ src_param_init_from_value(&src_params[i], operands[i], 0, dxil);
|
|
}
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
unsigned int is_texture, component_count;
|
|
enum dxil_resource_kind resource_kind;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_params;
|
|
const struct sm6_value *resource;
|
|
struct vsir_dst_operand *dst;
|
|
@@ -5908,10 +6001,19 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in
|
|
is_texture = resource->u.handle.d->resource_type != VKD3D_SHADER_RESOURCE_BUFFER;
|
|
resource_kind = resource->u.handle.d->kind;
|
|
|
|
+ if (!(ins = sm6_parser_add_function_instruction(sm6, state)))
|
|
+ return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
instruction_init_with_resource(ins, is_texture ? VSIR_OP_RESINFO : VSIR_OP_BUFINFO, resource, sm6);
|
|
|
|
if (!(src_params = instruction_src_params_alloc(ins, 1 + is_texture, sm6)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
+
|
|
src_param_init_vector_from_handle(sm6, &src_params[is_texture], &resource->u.handle);
|
|
|
|
if (is_texture)
|
|
@@ -5922,30 +6024,53 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in
|
|
|
|
if (resource_kind_is_multisampled(resource_kind))
|
|
{
|
|
- instruction_dst_param_init_uint_temp_vector(ins++, sm6);
|
|
+ if (!instruction_dst_param_init_uint_temp_vector(ins, sm6))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
+ return;
|
|
+ }
|
|
+
|
|
state->temp_idx = 1;
|
|
|
|
+ if (!(ins = sm6_parser_add_function_instruction(sm6, state)))
|
|
+ return;
|
|
+
|
|
/* DXIL does not have an intrinsic for sample info, and resinfo is expected to return
|
|
* the sample count in .w for MS textures. The result is always a struct of 4 x uint32. */
|
|
vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_SAMPLE_INFO);
|
|
ins->flags = VKD3DSI_SAMPLE_INFO_UINT;
|
|
|
|
if (!(src_params = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
+
|
|
src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle);
|
|
src_params[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
|
|
|
|
if (!instruction_dst_param_init_uint_temp_vector(ins, sm6))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
+
|
|
dst = ins->dst;
|
|
dst->write_mask = VKD3DSP_WRITEMASK_3;
|
|
|
|
/* Move the result to an SSA in case another instruction overwrites r0 before
|
|
* the components are extracted for use. */
|
|
- ++ins;
|
|
+ if (!(ins = sm6_parser_add_function_instruction(sm6, state)))
|
|
+ return;
|
|
+
|
|
vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV);
|
|
+
|
|
if (!(src_params = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
+
|
|
src_param_init_vector_from_reg(&src_params[0], &dst->reg);
|
|
|
|
state->ins = ins;
|
|
@@ -5955,15 +6080,13 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in
|
|
else
|
|
{
|
|
if (operands[1]->value_type != VALUE_TYPE_UNDEFINED)
|
|
- {
|
|
- WARN("Ignoring unexpected operand.\n");
|
|
vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS,
|
|
"Ignoring an unexpected defined LOD value for buffer GetDimensions.");
|
|
- }
|
|
component_count = 1 + (resource_kind == RESOURCE_KIND_STRUCTUREDBUFFER);
|
|
}
|
|
|
|
- instruction_dst_param_init_ssa_vector(ins, component_count, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_vector(ins, component_count, sm6))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode op)
|
|
@@ -5979,22 +6102,33 @@ static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode
|
|
}
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_tertiary(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_params;
|
|
unsigned int i;
|
|
|
|
- vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_tertiary_op(op));
|
|
- if (!(src_params = instruction_src_params_alloc(ins, 3, sm6)))
|
|
+ if (!(ins = sm6_parser_add_function_instruction(dxil, state)))
|
|
return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &dxil->p.location, sm6_dx_map_tertiary_op(op));
|
|
+
|
|
+ if (!(src_params = instruction_src_params_alloc(ins, 3, dxil)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
+ return;
|
|
+ }
|
|
+
|
|
for (i = 0; i < 3; ++i)
|
|
{
|
|
- src_param_init_from_value(&src_params[i], operands[i], 0, sm6);
|
|
+ src_param_init_from_value(&src_params[i], operands[i], 0, dxil);
|
|
}
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
@@ -6002,11 +6136,11 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin
|
|
{
|
|
bool is_control_point = op == DX_LOAD_OUTPUT_CONTROL_POINT;
|
|
bool is_patch_constant = op == DX_LOAD_PATCH_CONSTANT;
|
|
- struct vkd3d_shader_instruction *ins = state->ins;
|
|
struct vsir_program *program = sm6->program;
|
|
unsigned int count, row_index, column_index;
|
|
const struct shader_signature *signature;
|
|
const struct vsir_dst_operand *params;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
struct vsir_src_operand *src_param;
|
|
const struct signature_element *e;
|
|
|
|
@@ -6014,14 +6148,9 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin
|
|
column_index = sm6_value_get_constant_uint(operands[2], sm6);
|
|
|
|
if (is_control_point && operands[3]->value_type == VALUE_TYPE_UNDEFINED)
|
|
- {
|
|
/* dxcompiler will compile source which does this, so let it pass. */
|
|
- WARN("Control point id is undefined.\n");
|
|
vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND,
|
|
"The index for a control point load is undefined.");
|
|
- }
|
|
-
|
|
- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV);
|
|
|
|
if (is_patch_constant)
|
|
{
|
|
@@ -6040,15 +6169,25 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin
|
|
}
|
|
if (row_index >= signature->element_count)
|
|
{
|
|
- WARN("Invalid row index %u.\n", row_index);
|
|
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
"Invalid input row index %u.", row_index);
|
|
return;
|
|
}
|
|
e = &signature->elements[row_index];
|
|
|
|
+ if (!(ins = sm6_parser_add_function_instruction(sm6, state)))
|
|
+ return;
|
|
+
|
|
+ state->pushed_instruction = true;
|
|
+
|
|
+ vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV);
|
|
+
|
|
if (!(src_param = instruction_src_params_alloc(ins, 1, sm6)))
|
|
+ {
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
return;
|
|
+ }
|
|
+
|
|
src_param->reg = params[row_index].reg;
|
|
src_param_init_scalar(src_param, column_index);
|
|
count = 0;
|
|
@@ -6062,7 +6201,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin
|
|
register_index_address_init(&src_param->reg.idx[count], operands[3], sm6);
|
|
}
|
|
|
|
- instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
+ if (!instruction_dst_param_init_ssa_scalar(ins, 0, sm6))
|
|
+ vkd3d_shader_instruction_make_nop(ins);
|
|
}
|
|
|
|
static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
@@ -6085,16 +6225,16 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri
|
|
instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, true);
|
|
+ sm6_parser_emit_dx_input_register_mov(dxil, state, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, true);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_PRIMID, VSIR_DATA_U32, true);
|
|
+ sm6_parser_emit_dx_input_register_mov(dxil, state, VKD3DSPR_PRIMID, VSIR_DATA_U32, true);
|
|
}
|
|
|
|
static enum vkd3d_shader_opcode dx_map_quad_op(enum dxil_quad_op_kind op)
|
|
@@ -6915,7 +7055,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic
|
|
instruction_dst_param_init_ssa_scalar(ins, 0, sm6);
|
|
}
|
|
|
|
-static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *dxil, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
enum vkd3d_shader_register_type type;
|
|
@@ -6932,7 +7072,7 @@ static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intr
|
|
vkd3d_unreachable();
|
|
}
|
|
|
|
- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, type, VSIR_DATA_U32, true);
|
|
+ sm6_parser_emit_dx_input_register_mov(dxil, state, type, VSIR_DATA_U32, true);
|
|
}
|
|
|
|
struct sm6_dx_opcode_info
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
index 4848c531ced..67706bba902 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
@@ -107,6 +107,14 @@ struct fx_5_shader
|
|
uint32_t iface_bindings;
|
|
};
|
|
|
|
+enum fx_shader_type
|
|
+{
|
|
+ FX_SHADER_NONE,
|
|
+ FX4_SHADER,
|
|
+ FX4_SHADER_SO,
|
|
+ FX5_SHADER
|
|
+};
|
|
+
|
|
struct string_entry
|
|
{
|
|
struct rb_entry entry;
|
|
@@ -119,9 +127,12 @@ struct type_entry
|
|
{
|
|
struct list entry;
|
|
const char *name;
|
|
+ const struct hlsl_type *element_type;
|
|
uint32_t elements_count;
|
|
+ uint32_t unpacked_size;
|
|
uint32_t modifiers;
|
|
uint32_t offset;
|
|
+ enum fx_shader_type shader_type;
|
|
};
|
|
|
|
static int string_storage_compare(const void *key, const struct rb_entry *entry)
|
|
@@ -293,6 +304,7 @@ struct fx_write_context
|
|
uint32_t rasterizer_state_count;
|
|
uint32_t blend_state_count;
|
|
uint32_t string_count;
|
|
+ uint32_t inline_shader_count;
|
|
int status;
|
|
|
|
bool child_effect;
|
|
@@ -360,46 +372,30 @@ static void write_fx_4_annotations(struct hlsl_scope *scope, struct fx_write_con
|
|
set_u32(buffer, count_offset, count);
|
|
}
|
|
|
|
-static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx);
|
|
+static uint32_t write_fx_4_type(const struct type_entry *type, struct fx_write_context *fx);
|
|
static const char * get_fx_4_type_name(const struct hlsl_type *type);
|
|
static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx);
|
|
|
|
-static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx)
|
|
+static uint32_t write_type(const struct type_entry *type, struct fx_write_context *fx)
|
|
{
|
|
- unsigned int elements_count, modifiers;
|
|
- const struct hlsl_type *element_type;
|
|
struct type_entry *type_entry;
|
|
- const char *name;
|
|
-
|
|
- VKD3D_ASSERT(fx->ctx->profile->major_version >= 4);
|
|
-
|
|
- if (type->class == HLSL_CLASS_ARRAY)
|
|
- {
|
|
- elements_count = hlsl_get_multiarray_size(type);
|
|
- element_type = hlsl_get_multiarray_element_type(type);
|
|
- }
|
|
- else
|
|
- {
|
|
- elements_count = 0;
|
|
- element_type = type;
|
|
- }
|
|
-
|
|
- name = get_fx_4_type_name(element_type);
|
|
- modifiers = element_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK;
|
|
|
|
/* We don't try to reuse nameless types; they will get the same
|
|
* "<unnamed>" name, but are not available for the type cache. */
|
|
- if (name)
|
|
+ if (type->name)
|
|
{
|
|
LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry)
|
|
{
|
|
- if (strcmp(type_entry->name, name))
|
|
+ if (strcmp(type_entry->name, type->name))
|
|
+ continue;
|
|
+
|
|
+ if (type_entry->elements_count != type->elements_count)
|
|
continue;
|
|
|
|
- if (type_entry->elements_count != elements_count)
|
|
+ if (type_entry->modifiers != type->modifiers)
|
|
continue;
|
|
|
|
- if (type_entry->modifiers != modifiers)
|
|
+ if (type_entry->shader_type != type->shader_type)
|
|
continue;
|
|
|
|
return type_entry->offset;
|
|
@@ -409,17 +405,90 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context
|
|
if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry))))
|
|
return 0;
|
|
|
|
+ *type_entry = *type;
|
|
type_entry->offset = write_fx_4_type(type, fx);
|
|
- type_entry->name = name;
|
|
- type_entry->elements_count = elements_count;
|
|
- type_entry->modifiers = modifiers;
|
|
|
|
- if (name)
|
|
+ if (type_entry->name)
|
|
list_add_tail(&fx->types, &type_entry->entry);
|
|
|
|
return type_entry->offset;
|
|
}
|
|
|
|
+static void type_entry_from_type(struct type_entry *e, const struct hlsl_type *type, const struct fx_write_context *fx)
|
|
+{
|
|
+ const struct hlsl_type *element_type = hlsl_get_multiarray_element_type(type);
|
|
+
|
|
+ VKD3D_ASSERT(fx->ctx->profile->major_version >= 4);
|
|
+
|
|
+ *e = (struct type_entry)
|
|
+ {
|
|
+ .elements_count = type->class == HLSL_CLASS_ARRAY ? hlsl_get_multiarray_size(type) : 0,
|
|
+ /* Structures can only contain numeric fields, this is validated
|
|
+ * during variable declaration. */
|
|
+ .unpacked_size = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float),
|
|
+ .modifiers = element_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK,
|
|
+ .name = get_fx_4_type_name(element_type),
|
|
+ .element_type = element_type,
|
|
+ };
|
|
+}
|
|
+
|
|
+static enum fx_shader_type get_shader_type(struct hlsl_ir_var *shader, struct fx_write_context *fx)
|
|
+{
|
|
+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(shader->data_type);
|
|
+ uint32_t elements_count = hlsl_get_multiarray_size(shader->data_type);
|
|
+ enum fx_shader_type shader_type = FX4_SHADER;
|
|
+ struct hlsl_ctx *ctx = fx->ctx;
|
|
+
|
|
+ switch (type->class)
|
|
+ {
|
|
+ case HLSL_CLASS_PIXEL_SHADER:
|
|
+ case HLSL_CLASS_VERTEX_SHADER:
|
|
+ return FX4_SHADER;
|
|
+
|
|
+ case HLSL_CLASS_HULL_SHADER:
|
|
+ case HLSL_CLASS_COMPUTE_SHADER:
|
|
+ case HLSL_CLASS_DOMAIN_SHADER:
|
|
+ return FX5_SHADER;
|
|
+
|
|
+ case HLSL_CLASS_GEOMETRY_SHADER:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return FX_SHADER_NONE;
|
|
+ }
|
|
+
|
|
+ for (size_t i = 0; i < elements_count; ++i)
|
|
+ {
|
|
+ struct hlsl_ir_compile *compile;
|
|
+
|
|
+ if (!shader->default_values || !(compile = shader->default_values[i].shader) || !compile->output.count)
|
|
+ continue;
|
|
+
|
|
+ if (compile->output.count > 1)
|
|
+ {
|
|
+ shader_type = FX5_SHADER;
|
|
+ break;
|
|
+ }
|
|
+ shader_type = FX4_SHADER_SO;
|
|
+ }
|
|
+
|
|
+ if (shader_type == FX5_SHADER && hlsl_version_lt(ctx, 5, 0))
|
|
+ hlsl_error(ctx, &shader->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE,
|
|
+ "Multi-stream output is not supported by the fx_4_0 profile.");
|
|
+
|
|
+ return shader_type;
|
|
+}
|
|
+
|
|
+static uint32_t write_var_type(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
+{
|
|
+ struct type_entry entry;
|
|
+
|
|
+ type_entry_from_type(&entry, var->data_type, fx);
|
|
+
|
|
+ entry.shader_type = get_shader_type(var, fx);
|
|
+ return write_type(&entry, fx);
|
|
+}
|
|
+
|
|
static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_context_ops *ops,
|
|
struct fx_write_context *fx)
|
|
{
|
|
@@ -1244,7 +1313,7 @@ static bool is_numeric_fx_4_type(const struct hlsl_type *type)
|
|
return type->class == HLSL_CLASS_STRUCT || hlsl_is_numeric_type(type);
|
|
}
|
|
|
|
-static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx)
|
|
+static uint32_t write_fx_4_type(const struct type_entry *type, struct fx_write_context *fx)
|
|
{
|
|
struct field_offsets
|
|
{
|
|
@@ -1253,21 +1322,16 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
uint32_t offset;
|
|
uint32_t type;
|
|
};
|
|
- uint32_t name_offset, offset, unpacked_size, packed_size, stride, numeric_desc;
|
|
+ uint32_t name_offset, offset, packed_size, stride, numeric_desc;
|
|
+ const struct hlsl_type *element_type = type->element_type;
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
+ uint32_t elements_count = type->elements_count;
|
|
+ uint32_t unpacked_size = type->unpacked_size;
|
|
struct field_offsets *field_offsets = NULL;
|
|
- const struct hlsl_type *element_type;
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
- uint32_t elements_count = 0;
|
|
- const char *name;
|
|
+ const char *name = type->name;
|
|
size_t i;
|
|
|
|
- if (type->class == HLSL_CLASS_ARRAY)
|
|
- elements_count = hlsl_get_multiarray_size(type);
|
|
- element_type = hlsl_get_multiarray_element_type(type);
|
|
-
|
|
- name = get_fx_4_type_name(element_type);
|
|
-
|
|
name_offset = write_string(name ? name : "<unnamed>", fx);
|
|
if (element_type->class == HLSL_CLASS_STRUCT)
|
|
{
|
|
@@ -1277,11 +1341,13 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
for (i = 0; i < element_type->e.record.field_count; ++i)
|
|
{
|
|
const struct hlsl_struct_field *field = &element_type->e.record.fields[i];
|
|
+ struct type_entry entry;
|
|
|
|
+ type_entry_from_type(&entry, field->type, fx);
|
|
field_offsets[i].name = write_string(field->name, fx);
|
|
field_offsets[i].semantic = write_string(field->semantic.raw_name, fx);
|
|
field_offsets[i].offset = field->reg_offset[HLSL_REGSET_NUMERIC] * sizeof(float);
|
|
- field_offsets[i].type = write_type(field->type, fx);
|
|
+ field_offsets[i].type = write_type(&entry, fx);
|
|
}
|
|
}
|
|
|
|
@@ -1333,9 +1399,6 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
return 0;
|
|
}
|
|
|
|
- /* Structures can only contain numeric fields, this is validated during variable declaration. */
|
|
- unpacked_size = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float);
|
|
-
|
|
packed_size = 0;
|
|
if (is_numeric_fx_4_type(element_type))
|
|
packed_size = hlsl_type_component_count(element_type) * sizeof(float);
|
|
@@ -1423,6 +1486,23 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
{
|
|
put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_VERTEX_SHADER);
|
|
}
|
|
+ else if (element_type->class == HLSL_CLASS_GEOMETRY_SHADER)
|
|
+ {
|
|
+ switch (type->shader_type)
|
|
+ {
|
|
+ case FX4_SHADER:
|
|
+ put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_GEOMETRY_SHADER);
|
|
+ break;
|
|
+ case FX4_SHADER_SO:
|
|
+ put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO);
|
|
+ break;
|
|
+ case FX5_SHADER:
|
|
+ put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_GEOMETRY_SHADER);
|
|
+ break;
|
|
+ case FX_SHADER_NONE:
|
|
+ vkd3d_unreachable();
|
|
+ }
|
|
+ }
|
|
else if (element_type->class == HLSL_CLASS_RASTERIZER_STATE)
|
|
{
|
|
put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_RASTERIZER_STATE);
|
|
@@ -2181,7 +2261,7 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st
|
|
if (var->has_explicit_bind_point)
|
|
flags |= FX_4_HAS_EXPLICIT_BIND_POINT;
|
|
|
|
- type_offset = write_type(var->data_type, fx);
|
|
+ type_offset = write_var_type(var, fx);
|
|
name_offset = write_string(var->name, fx);
|
|
semantic_offset = write_string(var->semantic.raw_name, fx);
|
|
|
|
@@ -2216,7 +2296,7 @@ static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_conte
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
name_offset = write_string(var->name, fx);
|
|
- type_offset = write_type(var->data_type, fx);
|
|
+ type_offset = write_var_type(var, fx);
|
|
|
|
put_u32(buffer, name_offset);
|
|
put_u32(buffer, type_offset);
|
|
@@ -2285,6 +2365,109 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s
|
|
return offset;
|
|
}
|
|
|
|
+static uint32_t write_shader_blob(const struct hlsl_ir_compile *compile, struct fx_write_context *fx)
|
|
+{
|
|
+ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
+ struct vkd3d_shader_code source = {0}, rdef = {0};
|
|
+ const struct hlsl_profile_info *profile;
|
|
+ struct vkd3d_shader_version version;
|
|
+ struct hlsl_ctx *ctx = fx->ctx;
|
|
+ struct vsir_program program;
|
|
+ uint32_t offset;
|
|
+ int ret = 0;
|
|
+
|
|
+ static const struct vkd3d_shader_compile_option version_option =
|
|
+ {
|
|
+ .name = VKD3D_SHADER_COMPILE_OPTION_API_VERSION,
|
|
+ .value = VKD3D_SHADER_API_VERSION_CURRENT,
|
|
+ };
|
|
+ static const struct vkd3d_shader_compile_info compile_info =
|
|
+ {
|
|
+ .type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO,
|
|
+ .target_type = VKD3D_SHADER_TARGET_DXBC_TPF,
|
|
+ .options = &version_option,
|
|
+ .option_count = 1,
|
|
+ };
|
|
+
|
|
+ version = (struct vkd3d_shader_version)
|
|
+ {
|
|
+ .type = compile->profile->type,
|
|
+ .major = compile->profile->major_version,
|
|
+ .minor = compile->profile->minor_version,
|
|
+ };
|
|
+
|
|
+ if (!vsir_program_init(&program, &compile_info, &version, 0, VSIR_CF_STRUCTURED, VSIR_NORMALISED_SM4))
|
|
+ return 0;
|
|
+
|
|
+ profile = ctx->profile;
|
|
+ ctx->profile = compile->profile;
|
|
+ ret = hlsl_emit_vsir(ctx, &compile_info, compile->decl, &compile->initializers, &program, &rdef);
|
|
+ ctx->profile = profile;
|
|
+ if (ret < 0)
|
|
+ return 0;
|
|
+
|
|
+ ret = vsir_program_compile(&program, &rdef, vkd3d_shader_init_config_flags(),
|
|
+ &compile_info, &source, ctx->message_context);
|
|
+
|
|
+ vkd3d_shader_free_shader_code(&rdef);
|
|
+ vsir_program_cleanup(&program);
|
|
+ if (ret < 0)
|
|
+ return 0;
|
|
+
|
|
+ offset = put_u32(buffer, source.size);
|
|
+ bytecode_put_bytes_unaligned(buffer, source.code, source.size);
|
|
+
|
|
+ vkd3d_shader_free_shader_code(&source);
|
|
+
|
|
+ return offset;
|
|
+}
|
|
+
|
|
+static uint32_t write_fx_shader(enum fx_shader_type type, const struct hlsl_ir_compile *compile,
|
|
+ struct vkd3d_bytecode_buffer *buffer, struct fx_write_context *fx)
|
|
+{
|
|
+ struct fx_5_shader shader = {0};
|
|
+ uint32_t ret;
|
|
+
|
|
+ if (compile)
|
|
+ {
|
|
+ shader = (struct fx_5_shader)
|
|
+ {
|
|
+ .offset = write_shader_blob(compile, fx),
|
|
+ .sodecl_count = compile->output.count > 1 ? 4 : 0,
|
|
+ .rast_stream = compile->output.stream,
|
|
+ };
|
|
+
|
|
+ for (size_t i = 0; i < compile->output.count; ++i)
|
|
+ {
|
|
+ shader.sodecl[i] = write_string(compile->output.decls[i], fx);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ switch (type)
|
|
+ {
|
|
+ case FX4_SHADER:
|
|
+ ret = put_u32(buffer, shader.offset);
|
|
+ break;
|
|
+
|
|
+ case FX4_SHADER_SO:
|
|
+ ret = put_u32(buffer, shader.offset);
|
|
+ put_u32(buffer, shader.sodecl[0]);
|
|
+ break;
|
|
+
|
|
+ case FX5_SHADER:
|
|
+ ret = bytecode_put_bytes(buffer, &shader, sizeof(shader));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ ret = 0;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ ++fx->inline_shader_count;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry,
|
|
struct fx_write_context *fx)
|
|
{
|
|
@@ -2379,6 +2562,24 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl
|
|
}
|
|
break;
|
|
}
|
|
+ case HLSL_IR_COMPILE:
|
|
+ {
|
|
+ enum fx_shader_type shader_type;
|
|
+
|
|
+ if (hlsl_version_lt(ctx, 5, 0))
|
|
+ {
|
|
+ assignment_type = FX_4_ASSIGNMENT_INLINE_SHADER;
|
|
+ shader_type = FX4_SHADER_SO;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ assignment_type = FX_5_ASSIGNMENT_INLINE_SHADER;
|
|
+ shader_type = FX5_SHADER;
|
|
+ }
|
|
+
|
|
+ value_offset = write_fx_shader(shader_type, hlsl_ir_compile(value), unstructured, fx);
|
|
+ break;
|
|
+ }
|
|
default:
|
|
hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name);
|
|
}
|
|
@@ -2515,6 +2716,8 @@ static inline enum hlsl_type_class hlsl_type_class_from_fx_type(enum state_prope
|
|
return HLSL_CLASS_VERTEX_SHADER;
|
|
case FX_PIXELSHADER:
|
|
return HLSL_CLASS_PIXEL_SHADER;
|
|
+ case FX_GEOMETRYSHADER:
|
|
+ return HLSL_CLASS_GEOMETRY_SHADER;
|
|
default:
|
|
vkd3d_unreachable();
|
|
}
|
|
@@ -2926,6 +3129,9 @@ static void resolve_fx_state_block_values(struct hlsl_ir_var *var,
|
|
|
|
break;
|
|
}
|
|
+ case HLSL_IR_COMPILE:
|
|
+ case HLSL_IR_INDEX:
|
|
+ break;
|
|
default:
|
|
hlsl_fixme(ctx, &ctx->location, "Unhandled node type for object-typed field.");
|
|
}
|
|
@@ -3177,35 +3383,14 @@ static void write_fx_4_state_object_initializer(struct hlsl_ir_var *var, struct
|
|
}
|
|
}
|
|
|
|
-static void write_fx_4_shader_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
+static void write_fx_shader_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
{
|
|
- struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
uint32_t elements_count = hlsl_get_multiarray_size(var->data_type);
|
|
- unsigned int i;
|
|
+ enum fx_shader_type shader_type = get_shader_type(var, fx);
|
|
|
|
- /* FIXME: write shader blobs, once parser support works. */
|
|
- for (i = 0; i < elements_count; ++i)
|
|
- put_u32(buffer, 0);
|
|
-}
|
|
-
|
|
-static void write_fx_5_shader_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
-{
|
|
- struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
- uint32_t elements_count = hlsl_get_multiarray_size(var->data_type);
|
|
- unsigned int i;
|
|
-
|
|
- /* FIXME: write shader blobs, once parser support works. */
|
|
- for (i = 0; i < elements_count; ++i)
|
|
+ for (size_t i = 0; i < elements_count; ++i)
|
|
{
|
|
- put_u32(buffer, 0); /* Blob offset */
|
|
- put_u32(buffer, 0); /* SODecl[0] offset */
|
|
- put_u32(buffer, 0); /* SODecl[1] offset */
|
|
- put_u32(buffer, 0); /* SODecl[2] offset */
|
|
- put_u32(buffer, 0); /* SODecl[3] offset */
|
|
- put_u32(buffer, 0); /* SODecl count */
|
|
- put_u32(buffer, 0); /* Rasterizer stream */
|
|
- put_u32(buffer, 0); /* Interface bindings count */
|
|
- put_u32(buffer, 0); /* Interface initializer offset */
|
|
+ write_fx_shader(shader_type, var->default_values ? var->default_values[i].shader : NULL, &fx->structured, fx);
|
|
}
|
|
}
|
|
|
|
@@ -3221,7 +3406,7 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_
|
|
if (var->reg_reservation.reg_type)
|
|
bind_point = var->reg_reservation.reg_index;
|
|
|
|
- type_offset = write_type(var->data_type, fx);
|
|
+ type_offset = write_var_type(var, fx);
|
|
name_offset = write_string(var->name, fx);
|
|
semantic_offset = write_string(var->semantic.raw_name, fx);
|
|
|
|
@@ -3252,14 +3437,11 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_
|
|
|
|
case HLSL_CLASS_PIXEL_SHADER:
|
|
case HLSL_CLASS_VERTEX_SHADER:
|
|
- write_fx_4_shader_initializer(var, fx);
|
|
- fx->shader_count += elements_count;
|
|
- break;
|
|
-
|
|
case HLSL_CLASS_HULL_SHADER:
|
|
case HLSL_CLASS_COMPUTE_SHADER:
|
|
case HLSL_CLASS_DOMAIN_SHADER:
|
|
- write_fx_5_shader_initializer(var, fx);
|
|
+ case HLSL_CLASS_GEOMETRY_SHADER:
|
|
+ write_fx_shader_initializer(var, fx);
|
|
fx->shader_count += elements_count;
|
|
break;
|
|
|
|
@@ -3402,6 +3584,7 @@ static bool is_supported_object_variable(const struct hlsl_ctx *ctx, const struc
|
|
case HLSL_CLASS_TEXTURE:
|
|
case HLSL_CLASS_BLEND_STATE:
|
|
case HLSL_CLASS_VERTEX_SHADER:
|
|
+ case HLSL_CLASS_GEOMETRY_SHADER:
|
|
case HLSL_CLASS_STRING:
|
|
return true;
|
|
case HLSL_CLASS_COMPUTE_SHADER:
|
|
@@ -3477,7 +3660,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
put_u32(&buffer, fx.rtv_count);
|
|
put_u32(&buffer, fx.dsv_count);
|
|
put_u32(&buffer, fx.shader_count);
|
|
- put_u32(&buffer, 0); /* Inline shader count. */
|
|
+ put_u32(&buffer, fx.inline_shader_count);
|
|
|
|
set_u32(&buffer, size_offset, fx.unstructured.size);
|
|
|
|
@@ -3535,7 +3718,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
put_u32(&buffer, fx.rtv_count);
|
|
put_u32(&buffer, fx.dsv_count);
|
|
put_u32(&buffer, fx.shader_count);
|
|
- put_u32(&buffer, 0); /* Inline shader count. */
|
|
+ put_u32(&buffer, fx.inline_shader_count);
|
|
put_u32(&buffer, fx.group_count); /* Group count. */
|
|
put_u32(&buffer, fx.uav_count);
|
|
put_u32(&buffer, 0); /* Interface variables count. */
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
index 641d25539a2..4e287c62080 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
@@ -156,6 +156,8 @@ void hlsl_free_state_block(struct hlsl_state_block *state_block)
|
|
void hlsl_free_default_value(struct hlsl_default_value *value)
|
|
{
|
|
vkd3d_free((void *)value->string);
|
|
+ if (value->shader)
|
|
+ hlsl_free_instr(&value->shader->node);
|
|
}
|
|
|
|
void hlsl_free_default_values(struct hlsl_ir_var *decl)
|
|
@@ -2289,61 +2291,91 @@ struct hlsl_ir_node *hlsl_new_matrix_swizzle(struct hlsl_ctx *ctx, struct hlsl_m
|
|
return &swizzle->node;
|
|
}
|
|
|
|
-struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type,
|
|
- const char *profile_name, struct hlsl_ir_node **args, unsigned int args_count,
|
|
- struct hlsl_block *args_instrs, const struct vkd3d_shader_location *loc)
|
|
+static struct hlsl_ir_compile *new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile,
|
|
+ struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, struct hlsl_type *type,
|
|
+ uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc)
|
|
{
|
|
- const struct hlsl_profile_info *profile_info = NULL;
|
|
struct hlsl_ir_compile *compile;
|
|
- struct hlsl_type *type = NULL;
|
|
- unsigned int i;
|
|
|
|
- switch (compile_type)
|
|
+ if (!(compile = hlsl_alloc(ctx, sizeof(*compile))))
|
|
+ return NULL;
|
|
+
|
|
+ init_node(&compile->node, HLSL_IR_COMPILE, type, loc);
|
|
+ hlsl_block_init(&compile->initializers);
|
|
+ hlsl_block_add_block(&compile->initializers, initializer);
|
|
+
|
|
+ compile->profile = profile;
|
|
+ compile->decl = decl;
|
|
+ compile->output.stream = stream;
|
|
+ compile->output.count = count;
|
|
+
|
|
+ for (size_t i = 0; i < count; ++i)
|
|
{
|
|
- case HLSL_COMPILE_TYPE_COMPILE:
|
|
- if (!(profile_info = hlsl_get_target_info(profile_name)))
|
|
- {
|
|
- hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Unknown profile \"%s\".", profile_name);
|
|
- return NULL;
|
|
- }
|
|
+ if (output_decls[i])
|
|
+ compile->output.decls[i] = hlsl_strdup(ctx, output_decls[i]);
|
|
+ }
|
|
|
|
- if (profile_info->type == VKD3D_SHADER_TYPE_PIXEL)
|
|
- type = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true);
|
|
- else if (profile_info->type == VKD3D_SHADER_TYPE_VERTEX)
|
|
- type = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true);
|
|
+ return compile;
|
|
+}
|
|
|
|
- if (!type)
|
|
- {
|
|
- hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Invalid profile \"%s\".", profile_name);
|
|
- return NULL;
|
|
- }
|
|
+struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile,
|
|
+ struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, const struct vkd3d_shader_location *loc)
|
|
+{
|
|
+ struct hlsl_ir_compile *compile;
|
|
+ struct hlsl_type *type = NULL;
|
|
+
|
|
+ switch (profile->type)
|
|
+ {
|
|
+ case VKD3D_SHADER_TYPE_PIXEL:
|
|
+ type = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true);
|
|
+ break;
|
|
|
|
+ case VKD3D_SHADER_TYPE_VERTEX:
|
|
+ type = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true);
|
|
break;
|
|
|
|
- case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO:
|
|
+ case VKD3D_SHADER_TYPE_GEOMETRY:
|
|
type = hlsl_get_type(ctx->cur_scope, "GeometryShader", true, true);
|
|
break;
|
|
+
|
|
+ default:
|
|
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Invalid profile \"%s\".", profile->name);
|
|
+ return NULL;
|
|
}
|
|
|
|
- if (!(compile = hlsl_alloc(ctx, sizeof(*compile))))
|
|
+ if (!(compile = new_compile(ctx, profile, decl, initializer, type, 0, 0, NULL, loc)))
|
|
return NULL;
|
|
|
|
- init_node(&compile->node, HLSL_IR_COMPILE, type, loc);
|
|
+ return &compile->node;
|
|
+}
|
|
+
|
|
+struct hlsl_ir_node *hlsl_new_compile_with_so(struct hlsl_ctx *ctx, struct hlsl_ir_compile *shader,
|
|
+ uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc)
|
|
+{
|
|
+ struct hlsl_type *type = hlsl_get_type(ctx->cur_scope, "GeometryShader", true, true);
|
|
+ const struct hlsl_profile_info *profile = NULL;
|
|
+ struct hlsl_ir_function_decl *decl = NULL;
|
|
+ struct hlsl_ir_compile *compile;
|
|
+ struct hlsl_block initializers;
|
|
|
|
- compile->compile_type = compile_type;
|
|
- compile->profile = profile_info;
|
|
+ hlsl_block_init(&initializers);
|
|
|
|
- hlsl_block_init(&compile->instrs);
|
|
- hlsl_block_add_block(&compile->instrs, args_instrs);
|
|
+ /* non-fx profiles allow ConstructGSWithSO() but do not use nor type-check
|
|
+ * its arguments, so passing in NULL for "shader" creates a dummy geometry
|
|
+ * shader without any decl or profile. */
|
|
+ if (shader)
|
|
+ {
|
|
+ decl = shader->decl;
|
|
+ profile = shader->profile;
|
|
+ if (!(hlsl_clone_block(ctx, &initializers, &shader->initializers)))
|
|
+ return NULL;
|
|
+ }
|
|
|
|
- compile->args_count = args_count;
|
|
- if (!(compile->args = hlsl_alloc(ctx, sizeof(*compile->args) * args_count)))
|
|
+ if (!(compile = new_compile(ctx, profile, decl, &initializers, type, stream, count, output_decls, loc)))
|
|
{
|
|
- vkd3d_free(compile);
|
|
+ hlsl_block_cleanup(&initializers);
|
|
return NULL;
|
|
}
|
|
- for (i = 0; i < compile->args_count; ++i)
|
|
- hlsl_src_from_node(&compile->args[i], args[i]);
|
|
|
|
return &compile->node;
|
|
}
|
|
@@ -2878,43 +2910,17 @@ static struct hlsl_ir_node *clone_sync(struct hlsl_ctx *ctx, struct hlsl_ir_sync
|
|
|
|
return &dst->node;
|
|
}
|
|
-
|
|
static struct hlsl_ir_node *clone_compile(struct hlsl_ctx *ctx,
|
|
struct clone_instr_map *map, struct hlsl_ir_compile *compile)
|
|
{
|
|
- const char *profile_name = NULL;
|
|
- struct hlsl_ir_node **args;
|
|
- struct hlsl_ir_node *node;
|
|
- struct hlsl_block block;
|
|
- unsigned int i;
|
|
-
|
|
- if (!(clone_block(ctx, &block, &compile->instrs, map)))
|
|
- return NULL;
|
|
+ struct hlsl_block initializers;
|
|
|
|
- if (!(args = hlsl_alloc(ctx, sizeof(*args) * compile->args_count)))
|
|
- {
|
|
- hlsl_block_cleanup(&block);
|
|
- return NULL;
|
|
- }
|
|
- for (i = 0; i < compile->args_count; ++i)
|
|
- {
|
|
- args[i] = map_instr(map, compile->args[i].node);
|
|
- VKD3D_ASSERT(args[i]);
|
|
- }
|
|
-
|
|
- if (compile->profile)
|
|
- profile_name = compile->profile->name;
|
|
+ hlsl_clone_block(ctx, &initializers, &compile->initializers);
|
|
+ compile = new_compile(ctx, compile->profile, compile->decl, &initializers, compile->node.data_type,
|
|
+ compile->output.stream, compile->output.count, compile->output.decls, &compile->node.loc);
|
|
+ hlsl_block_cleanup(&initializers);
|
|
|
|
- if (!(node = hlsl_new_compile(ctx, compile->compile_type, profile_name,
|
|
- args, compile->args_count, &block, &compile->node.loc)))
|
|
- {
|
|
- hlsl_block_cleanup(&block);
|
|
- vkd3d_free(args);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- vkd3d_free(args);
|
|
- return node;
|
|
+ return compile ? &compile->node : NULL;
|
|
}
|
|
|
|
static struct hlsl_ir_node *clone_sampler_state(struct hlsl_ctx *ctx,
|
|
@@ -4069,26 +4075,24 @@ static void dump_ir_sync(struct vkd3d_string_buffer *buffer, const struct hlsl_i
|
|
static void dump_ir_compile(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
|
|
const struct hlsl_ir_compile *compile)
|
|
{
|
|
- unsigned int i;
|
|
+ vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name);
|
|
|
|
- switch (compile->compile_type)
|
|
- {
|
|
- case HLSL_COMPILE_TYPE_COMPILE:
|
|
- vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name);
|
|
- break;
|
|
+ dump_block(ctx, buffer, &compile->initializers);
|
|
|
|
- case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO:
|
|
- vkd3d_string_buffer_printf(buffer, "ConstructGSWithSO {\n");
|
|
- break;
|
|
- }
|
|
+ vkd3d_string_buffer_printf(buffer, " %10s }", "");
|
|
|
|
- dump_block(ctx, buffer, &compile->instrs);
|
|
+ if (!compile->output.count)
|
|
+ return;
|
|
|
|
- vkd3d_string_buffer_printf(buffer, " %10s } (", "");
|
|
- for (i = 0; i < compile->args_count; ++i)
|
|
+ vkd3d_string_buffer_printf(buffer, "(");
|
|
+ for (size_t i = 0; i < compile->output.count; ++i)
|
|
{
|
|
- dump_src(buffer, &compile->args[i]);
|
|
- if (i + 1 < compile->args_count)
|
|
+ const char *output = compile->output.decls[i];
|
|
+
|
|
+ if (!output)
|
|
+ output = "NULL";
|
|
+ vkd3d_string_buffer_printf(buffer, "%s", output);
|
|
+ if (i + 1 < compile->output.count)
|
|
vkd3d_string_buffer_printf(buffer, ", ");
|
|
}
|
|
vkd3d_string_buffer_printf(buffer, ")");
|
|
@@ -4455,12 +4459,11 @@ static void free_ir_sync(struct hlsl_ir_sync *sync)
|
|
|
|
static void free_ir_compile(struct hlsl_ir_compile *compile)
|
|
{
|
|
- unsigned int i;
|
|
-
|
|
- for (i = 0; i < compile->args_count; ++i)
|
|
- hlsl_src_remove(&compile->args[i]);
|
|
-
|
|
- hlsl_block_cleanup(&compile->instrs);
|
|
+ hlsl_block_cleanup(&compile->initializers);
|
|
+ for (size_t i = 0; i < compile->output.count; ++i)
|
|
+ {
|
|
+ vkd3d_free((void *)compile->output.decls[i]);
|
|
+ }
|
|
vkd3d_free(compile);
|
|
}
|
|
|
|
@@ -5332,7 +5335,7 @@ int hlsl_parse(const struct vkd3d_shader_compile_info *compile_info,
|
|
return VKD3D_ERROR_INVALID_SHADER;
|
|
}
|
|
|
|
- ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, program, reflection_data);
|
|
+ ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, NULL, program, reflection_data);
|
|
hlsl_ctx_cleanup(&ctx);
|
|
if (ret < 0)
|
|
vsir_program_cleanup(program);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
index e12915f9fe6..53ace309323 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
@@ -501,6 +501,8 @@ struct hlsl_ir_var
|
|
const char *string;
|
|
/* Default value, in case the component is a numeric value. */
|
|
union hlsl_constant_value_component number;
|
|
+ /* Default value, in case the component is a shader. otherwise it is NULL. */
|
|
+ struct hlsl_ir_compile *shader;
|
|
} *default_values;
|
|
|
|
/* Pointer to the temp copy of the variable, in case it is uniform. */
|
|
@@ -957,33 +959,28 @@ struct hlsl_ir_string_constant
|
|
char *string;
|
|
};
|
|
|
|
-/* Represents shader compilation call for effects, such as "CompileShader()".
|
|
- *
|
|
- * Unlike hlsl_ir_call, it is not flattened, thus, it keeps track of its
|
|
- * arguments and maintains its own instruction block. */
|
|
+#define HLSL_STREAM_OUTPUT_MAX 4
|
|
+
|
|
+/* Represents shader compilation call for effects, such as "CompileShader()". */
|
|
struct hlsl_ir_compile
|
|
{
|
|
struct hlsl_ir_node node;
|
|
|
|
- enum hlsl_compile_type
|
|
- {
|
|
- /* A shader compilation through the CompileShader() function or the "compile" syntax. */
|
|
- HLSL_COMPILE_TYPE_COMPILE,
|
|
- /* A call to ConstructGSWithSO(), which receives a geometry shader and retrieves one as well. */
|
|
- HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO,
|
|
- } compile_type;
|
|
-
|
|
- /* Special field to store the profile argument for HLSL_COMPILE_TYPE_COMPILE. */
|
|
+ /* Special field to store the profile argument. */
|
|
const struct hlsl_profile_info *profile;
|
|
+ struct hlsl_ir_function_decl *decl;
|
|
|
|
- /* Block containing the instructions required by the arguments of the
|
|
+ /* Block containing the static initializers passed as arguments of the
|
|
* compilation call. */
|
|
- struct hlsl_block instrs;
|
|
+ struct hlsl_block initializers;
|
|
|
|
- /* Arguments to the compilation call. For HLSL_COMPILE_TYPE_COMPILE
|
|
- * args[0] is an hlsl_ir_call to the specified function. */
|
|
- struct hlsl_src *args;
|
|
- unsigned int args_count;
|
|
+ /* Stream Output constants, filled by a ConstructGSWithSO() call. */
|
|
+ struct
|
|
+ {
|
|
+ uint32_t stream;
|
|
+ unsigned count;
|
|
+ const char *decls[HLSL_STREAM_OUTPUT_MAX];
|
|
+ } output;
|
|
};
|
|
|
|
/* Represents a state block initialized with the "sampler_state" keyword. */
|
|
@@ -1657,8 +1654,8 @@ void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body);
|
|
void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body);
|
|
int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out);
|
|
int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info,
|
|
- struct hlsl_ir_function_decl *entry_func, struct vsir_program *program,
|
|
- struct vkd3d_shader_code *reflection_data);
|
|
+ struct hlsl_ir_function_decl *entry_func, const struct hlsl_block *initializers,
|
|
+ struct vsir_program *program, struct vkd3d_shader_code *reflection_data);
|
|
|
|
bool hlsl_init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int path_len);
|
|
bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain);
|
|
@@ -1745,9 +1742,10 @@ bool hlsl_index_is_resource_access(struct hlsl_ir_index *index);
|
|
bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index);
|
|
bool hlsl_index_chain_has_tgsm_access(struct hlsl_ir_index *index);
|
|
|
|
-struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type,
|
|
- const char *profile_name, struct hlsl_ir_node **args, unsigned int args_count,
|
|
- struct hlsl_block *args_instrs, const struct vkd3d_shader_location *loc);
|
|
+struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile,
|
|
+ struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, const struct vkd3d_shader_location *loc);
|
|
+struct hlsl_ir_node *hlsl_new_compile_with_so(struct hlsl_ctx *ctx, struct hlsl_ir_compile *shader,
|
|
+ uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc);
|
|
struct hlsl_ir_node *hlsl_new_interlocked(struct hlsl_ctx *ctx, enum hlsl_interlocked_op op, struct hlsl_type *type,
|
|
const struct hlsl_deref *dst, struct hlsl_ir_node *coords, struct hlsl_ir_node *cmp_value,
|
|
struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
index d5dcc775a00..3e872ecc13a 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
@@ -623,6 +623,11 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx
|
|
if (!(ret.string = vkd3d_strdup(string->string)))
|
|
return ret;
|
|
}
|
|
+ else if (node->type == HLSL_IR_COMPILE)
|
|
+ {
|
|
+ list_remove(&node->entry);
|
|
+ ret.shader = hlsl_ir_compile(node);
|
|
+ }
|
|
else
|
|
{
|
|
hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
|
@@ -2253,19 +2258,17 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i
|
|
{
|
|
struct hlsl_default_value default_value = {0};
|
|
|
|
- if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE)
|
|
+ if ((src->type == HLSL_IR_SAMPLER_STATE || src->type == HLSL_IR_COMPILE)
|
|
+ && hlsl_is_numeric_type(dst_comp_type) && dst->default_values)
|
|
{
|
|
/* Default values are discarded if they contain an object
|
|
* literal expression for a numeric component. */
|
|
- if (hlsl_is_numeric_type(dst_comp_type) && dst->default_values)
|
|
- {
|
|
- hlsl_warning(ctx, &src->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE,
|
|
- "Component %u in variable '%s' initializer is object literal. Default values discarded.",
|
|
- k, dst->name);
|
|
- hlsl_free_default_values(dst);
|
|
- }
|
|
+ hlsl_warning(ctx, &src->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE,
|
|
+ "Component %u in variable '%s' initializer is an object literal. Default values discarded.",
|
|
+ k, dst->name);
|
|
+ hlsl_free_default_values(dst);
|
|
}
|
|
- else
|
|
+ else if (src->type != HLSL_IR_SAMPLER_STATE)
|
|
{
|
|
if (!hlsl_clone_block(ctx, &block, instrs))
|
|
return;
|
|
@@ -2708,8 +2711,6 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var
|
|
|| ctx->cur_scope->annotations;
|
|
if (hlsl_get_multiarray_element_type(type)->class == HLSL_CLASS_SAMPLER)
|
|
is_default_values_initializer = false;
|
|
- if (hlsl_type_is_shader(type))
|
|
- is_default_values_initializer = false;
|
|
|
|
static_initialization = var->storage_modifiers & HLSL_STORAGE_STATIC
|
|
|| (var->data_type->modifiers & HLSL_MODIFIER_CONST
|
|
@@ -3015,11 +3016,9 @@ static void add_void_expr(struct hlsl_ctx *ctx, struct hlsl_block *block,
|
|
hlsl_block_add_expr(ctx, block, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, loc);
|
|
}
|
|
|
|
-static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx,
|
|
- struct hlsl_ir_function_decl *func, const struct parse_initializer *args,
|
|
- bool is_compile, const struct vkd3d_shader_location *loc)
|
|
+static bool parse_function_call_arguments(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func,
|
|
+ const struct parse_initializer *args, bool is_compile, const struct vkd3d_shader_location *loc)
|
|
{
|
|
- struct hlsl_ir_node *call;
|
|
unsigned int i, j, k;
|
|
|
|
VKD3D_ASSERT(args->args_count <= func->parameters.count);
|
|
@@ -3077,12 +3076,22 @@ static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx,
|
|
}
|
|
}
|
|
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func,
|
|
+ const struct parse_initializer *args, const struct vkd3d_shader_location *loc)
|
|
+{
|
|
+ struct hlsl_ir_node *call;
|
|
+ unsigned int i;
|
|
+
|
|
+ if (!parse_function_call_arguments(ctx, func, args, false, loc))
|
|
+ return NULL;
|
|
+
|
|
if (!(call = hlsl_new_call(ctx, func, loc)))
|
|
return NULL;
|
|
- hlsl_block_add_instr(args->instrs, call);
|
|
|
|
- if (is_compile)
|
|
- return call;
|
|
+ hlsl_block_add_instr(args->instrs, call);
|
|
|
|
for (i = 0; i < args->args_count; ++i)
|
|
{
|
|
@@ -3288,7 +3297,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_acos(struct hlsl_ctx *ctx,
|
|
@@ -3428,7 +3437,7 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_atan(struct hlsl_ctx *ctx,
|
|
@@ -3611,7 +3620,7 @@ static bool write_cosh_or_sinh(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_cosh(struct hlsl_ctx *ctx,
|
|
@@ -3823,7 +3832,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_distance(struct hlsl_ctx *ctx,
|
|
@@ -3893,7 +3902,7 @@ static bool intrinsic_dst(struct hlsl_ctx *ctx, const struct parse_initializer *
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_exp(struct hlsl_ctx *ctx,
|
|
@@ -3947,7 +3956,7 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_f16tof32(struct hlsl_ctx *ctx,
|
|
@@ -4143,7 +4152,7 @@ static bool intrinsic_frexp(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_fwidth(struct hlsl_ctx *ctx,
|
|
@@ -4170,7 +4179,7 @@ static bool intrinsic_fwidth(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_isinf(struct hlsl_ctx *ctx,
|
|
@@ -4270,7 +4279,7 @@ static bool intrinsic_lit(struct hlsl_ctx *ctx,
|
|
if (!(func = hlsl_compile_internal_function(ctx, "lit", body)))
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_log(struct hlsl_ctx *ctx,
|
|
@@ -4371,7 +4380,7 @@ static bool intrinsic_modf(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_mul(struct hlsl_ctx *ctx,
|
|
@@ -4620,7 +4629,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_round(struct hlsl_ctx *ctx,
|
|
@@ -4722,7 +4731,7 @@ static bool intrinsic_sincos(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_sinh(struct hlsl_ctx *ctx,
|
|
@@ -4757,7 +4766,7 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_sqrt(struct hlsl_ctx *ctx,
|
|
@@ -4831,7 +4840,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx,
|
|
if (!func)
|
|
return false;
|
|
|
|
- return !!add_user_call(ctx, func, params, false, loc);
|
|
+ return !!add_user_call(ctx, func, params, loc);
|
|
}
|
|
|
|
static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *params,
|
|
@@ -5356,17 +5365,114 @@ static bool intrinsic_AllMemoryBarrierWithGroupSync(struct hlsl_ctx *ctx,
|
|
static bool intrinsic_ConstructGSWithSO(struct hlsl_ctx *ctx,
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
{
|
|
- struct hlsl_ir_node *compile;
|
|
+ const char *strings[HLSL_STREAM_OUTPUT_MAX] = {0};
|
|
+ size_t string_count = params->args_count - 1;
|
|
+ struct hlsl_ir_compile *compile;
|
|
+ struct hlsl_ir_node *node;
|
|
+ uint32_t stream_index = 0;
|
|
+ struct hlsl_ir_var *var;
|
|
|
|
if (params->args_count != 2 && params->args_count != 6)
|
|
+ {
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
|
|
- "Wrong number of arguments to ConstructGSWithSO(): expected 2 or 6, but got %u.", params->args_count);
|
|
+ "Unexpected number of arguments to ConstructGSWithSO(): expected 2 or 6, but got %u.",
|
|
+ params->args_count);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (ctx->profile->type != VKD3D_SHADER_TYPE_EFFECT)
|
|
+ {
|
|
+ if (!(node = hlsl_new_compile_with_so(ctx, NULL, 0, 0, NULL, loc)))
|
|
+ return false;
|
|
+ hlsl_block_add_instr(params->instrs, node);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ node = params->args[0];
|
|
+ switch (node->type)
|
|
+ {
|
|
+ case HLSL_IR_COMPILE:
|
|
+ compile = hlsl_ir_compile(node);
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_LOAD:
|
|
+ var = hlsl_ir_load(node)->src.var;
|
|
+ if (var->data_type->class == HLSL_CLASS_ARRAY || !hlsl_type_is_shader(var->data_type))
|
|
+ {
|
|
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
+ "\"%s\" is not a shader compilation.", var->name);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!(compile = var->default_values[0].shader))
|
|
+ {
|
|
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
+ "Stream output shaders can't be constructed with NULL shaders.");
|
|
+ return false;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_INDEX:
|
|
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
+ "Stream output shaders can't be constructed with array indexes.");
|
|
+ return false;
|
|
+
|
|
+ default:
|
|
+ hlsl_fixme(ctx, loc, "Unhandled node type in ConstructGSWithSO().");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (compile->profile->type != VKD3D_SHADER_TYPE_VERTEX && compile->profile->type != VKD3D_SHADER_TYPE_GEOMETRY)
|
|
+ {
|
|
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
+ "Stream output shaders can only be constructed with vertex or geometry shaders.");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (params->args_count == 6)
|
|
+ {
|
|
+ struct hlsl_block stream_index_block;
|
|
+
|
|
+ --string_count;
|
|
+
|
|
+ if (!(node = hlsl_clone_instr(ctx, params->args[5])))
|
|
+ return false;
|
|
+
|
|
+ hlsl_block_init(&stream_index_block);
|
|
+ hlsl_block_add_instr(&stream_index_block, node);
|
|
+
|
|
+ stream_index = evaluate_static_expression_as_uint(ctx, &stream_index_block, loc);
|
|
+
|
|
+ hlsl_block_cleanup(&stream_index_block);
|
|
+ }
|
|
+
|
|
+ for (size_t i = 0; i < string_count; ++i)
|
|
+ {
|
|
+ struct hlsl_ir_node *stream_node = params->args[i + 1];
|
|
|
|
- if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO,
|
|
- NULL, params->args, params->args_count, params->instrs, loc)))
|
|
+ switch (stream_node->type)
|
|
+ {
|
|
+ case HLSL_IR_STRING_CONSTANT:
|
|
+ strings[i] = hlsl_ir_string_constant(stream_node)->string;
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_CONSTANT:
|
|
+ if (stream_node->data_type->class == HLSL_CLASS_NULL)
|
|
+ continue;
|
|
+ /* fall-through */
|
|
+ default:
|
|
+ hlsl_error(ctx, &stream_node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
+ "Stream Output declarations must be a literal string.");
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ VKD3D_ASSERT(string_count <= ARRAY_SIZE(strings));
|
|
+
|
|
+ if (!(node = hlsl_new_compile_with_so(ctx, compile, stream_index, string_count, strings, loc)))
|
|
return false;
|
|
+ hlsl_block_add_instr(params->instrs, node);
|
|
|
|
- hlsl_block_add_instr(params->instrs, compile);
|
|
return true;
|
|
}
|
|
|
|
@@ -5541,15 +5647,12 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name,
|
|
for (unsigned int i = 0; i < args->args_count; ++i)
|
|
{
|
|
if (args->args[i]->data_type->class == HLSL_CLASS_ERROR)
|
|
- {
|
|
- args->instrs->value = ctx->error_instr;
|
|
- return args->instrs;
|
|
- }
|
|
+ goto fail;
|
|
}
|
|
|
|
if ((decl = find_function_call(ctx, name, args, false, loc)))
|
|
{
|
|
- if (!add_user_call(ctx, decl, args, false, loc))
|
|
+ if (!add_user_call(ctx, decl, args, loc))
|
|
goto fail;
|
|
}
|
|
else if ((intrinsic = bsearch(name, intrinsic_functions, ARRAY_SIZE(intrinsic_functions),
|
|
@@ -5601,22 +5704,24 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name,
|
|
return args->instrs;
|
|
|
|
fail:
|
|
- free_parse_initializer(args);
|
|
- return NULL;
|
|
+ args->instrs->value = ctx->error_instr;
|
|
+ vkd3d_free(args->args);
|
|
+ return args->instrs;
|
|
}
|
|
|
|
static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const char *profile_name,
|
|
const char *function_name, struct parse_initializer *args, const struct vkd3d_shader_location *loc)
|
|
{
|
|
- struct hlsl_ir_node *compile, *call_to_compile = NULL;
|
|
+ const struct hlsl_profile_info *profile_info;
|
|
struct hlsl_ir_function_decl *decl;
|
|
+ struct hlsl_block *block = NULL;
|
|
+ struct hlsl_ir_node *compile;
|
|
|
|
if (!ctx->in_state_block && ctx->cur_scope != ctx->globals)
|
|
{
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_MISPLACED_COMPILE,
|
|
"Shader compilation statements must be in global scope or a state block.");
|
|
- free_parse_initializer(args);
|
|
- return NULL;
|
|
+ goto out;
|
|
}
|
|
|
|
if (!(decl = find_function_call(ctx, function_name, args, true, loc)))
|
|
@@ -5632,8 +5737,13 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED,
|
|
"Function \"%s\" is not defined.", function_name);
|
|
}
|
|
- free_parse_initializer(args);
|
|
- return NULL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (!(profile_info = hlsl_get_target_info(profile_name)))
|
|
+ {
|
|
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Unknown profile \"%s\".", profile_name);
|
|
+ goto out;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < args->args_count; ++i)
|
|
@@ -5646,21 +5756,17 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha
|
|
}
|
|
}
|
|
|
|
- if (!(call_to_compile = add_user_call(ctx, decl, args, true, loc)))
|
|
- {
|
|
- free_parse_initializer(args);
|
|
- return NULL;
|
|
- }
|
|
+ if (!parse_function_call_arguments(ctx, decl, args, true, loc))
|
|
+ goto out;
|
|
|
|
- if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_COMPILE,
|
|
- profile_name, &call_to_compile, 1, args->instrs, loc)))
|
|
- {
|
|
- free_parse_initializer(args);
|
|
- return NULL;
|
|
- }
|
|
+ if (!(compile = hlsl_new_compile(ctx, profile_info, decl, args->instrs, loc)))
|
|
+ goto out;
|
|
|
|
+ block = make_block(ctx, compile);
|
|
+
|
|
+out:
|
|
free_parse_initializer(args);
|
|
- return make_block(ctx, compile);
|
|
+ return block;
|
|
}
|
|
|
|
static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type,
|
|
@@ -9474,11 +9580,7 @@ primary_expr:
|
|
}
|
|
| var_identifier '(' func_arguments ')'
|
|
{
|
|
- if (!($$ = add_call(ctx, $1, &$3, &@1)))
|
|
- {
|
|
- vkd3d_free($1);
|
|
- YYABORT;
|
|
- }
|
|
+ $$ = add_call(ctx, $1, &$3, &@1);
|
|
vkd3d_free($1);
|
|
}
|
|
| KW_SAMPLER_STATE '{' state_block_start state_block '}'
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
index 7adaeaa4c1e..9ca7f982263 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
@@ -15311,12 +15311,12 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v
|
|
}
|
|
|
|
int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info,
|
|
- struct hlsl_ir_function_decl *entry_func, struct vsir_program *program,
|
|
- struct vkd3d_shader_code *reflection_data)
|
|
+ struct hlsl_ir_function_decl *entry_func, const struct hlsl_block *initializers,
|
|
+ struct vsir_program *program, struct vkd3d_shader_code *reflection_data)
|
|
{
|
|
- struct hlsl_block global_uniform_block, body, patch_body;
|
|
uint32_t config_flags = vkd3d_shader_init_config_flags();
|
|
const struct hlsl_profile_info *profile = ctx->profile;
|
|
+ struct hlsl_block initializer_block, body, patch_body;
|
|
struct list semantic_vars, patch_semantic_vars;
|
|
struct hlsl_ir_var *var;
|
|
|
|
@@ -15339,13 +15339,17 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info
|
|
list_init(&ctx->extern_vars);
|
|
list_init(&semantic_vars);
|
|
list_init(&patch_semantic_vars);
|
|
- hlsl_block_init(&global_uniform_block);
|
|
+
|
|
+ if (!initializers)
|
|
+ hlsl_block_init(&initializer_block);
|
|
+ else if (!hlsl_clone_block(ctx, &initializer_block, initializers))
|
|
+ return ctx->result;
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
|
|
{
|
|
if (var->storage_modifiers & HLSL_STORAGE_UNIFORM)
|
|
{
|
|
- prepend_uniform_copy(ctx, &global_uniform_block, var);
|
|
+ prepend_uniform_copy(ctx, &initializer_block, var);
|
|
}
|
|
else if (var->storage_modifiers & HLSL_STORAGE_GROUPSHARED)
|
|
{
|
|
@@ -15354,18 +15358,19 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info
|
|
}
|
|
}
|
|
|
|
- process_entry_function(ctx, &semantic_vars, &body, &global_uniform_block, entry_func);
|
|
+ process_entry_function(ctx, &semantic_vars, &body, &initializer_block, entry_func);
|
|
+
|
|
if (ctx->result)
|
|
return ctx->result;
|
|
|
|
if (profile->type == VKD3D_SHADER_TYPE_HULL)
|
|
{
|
|
- process_entry_function(ctx, &patch_semantic_vars, &patch_body, &global_uniform_block, ctx->patch_constant_func);
|
|
+ process_entry_function(ctx, &patch_semantic_vars, &patch_body, &initializer_block, ctx->patch_constant_func);
|
|
if (ctx->result)
|
|
return ctx->result;
|
|
}
|
|
|
|
- hlsl_block_cleanup(&global_uniform_block);
|
|
+ hlsl_block_cleanup(&initializer_block);
|
|
|
|
if (profile->major_version < 4)
|
|
{
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
index 68285be0a49..a8a84ad3f7f 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
@@ -563,8 +563,9 @@ struct shader_dump_data
|
|
|
|
enum shader_dump_type
|
|
{
|
|
- SHADER_DUMP_TYPE_SOURCE,
|
|
+ SHADER_DUMP_TYPE_LOG,
|
|
SHADER_DUMP_TYPE_PREPROC,
|
|
+ SHADER_DUMP_TYPE_SOURCE,
|
|
SHADER_DUMP_TYPE_TARGET,
|
|
};
|
|
|
|
@@ -594,10 +595,12 @@ static void vkd3d_shader_dump_shader(const struct shader_dump_data *dump_data,
|
|
if (dump_data->profile)
|
|
pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-%s", dump_data->profile);
|
|
|
|
- if (type == SHADER_DUMP_TYPE_SOURCE)
|
|
- pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-source.%s", dump_data->source_suffix);
|
|
+ if (type == SHADER_DUMP_TYPE_LOG)
|
|
+ pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, ".log");
|
|
else if (type == SHADER_DUMP_TYPE_PREPROC)
|
|
pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-preproc.%s", dump_data->source_suffix);
|
|
+ else if (type == SHADER_DUMP_TYPE_SOURCE)
|
|
+ pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-source.%s", dump_data->source_suffix);
|
|
else
|
|
pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-target.%s", dump_data->target_suffix);
|
|
|
|
@@ -615,6 +618,17 @@ static void vkd3d_shader_dump_shader(const struct shader_dump_data *dump_data,
|
|
}
|
|
}
|
|
|
|
+static void vkd3d_shader_dump_messages(const struct shader_dump_data *dump_data,
|
|
+ const struct vkd3d_shader_message_context *message_context)
|
|
+{
|
|
+ const struct vkd3d_string_buffer *messages = &message_context->messages;
|
|
+
|
|
+ if (!messages->content_size)
|
|
+ return;
|
|
+
|
|
+ vkd3d_shader_dump_shader(dump_data, messages->buffer, messages->content_size, SHADER_DUMP_TYPE_LOG);
|
|
+}
|
|
+
|
|
static const char *shader_get_source_type_suffix(enum vkd3d_shader_source_type type)
|
|
{
|
|
switch (type)
|
|
@@ -1770,13 +1784,14 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
|
|
vsir_program_cleanup(&program);
|
|
}
|
|
|
|
+ vkd3d_shader_dump_messages(&dump_data, &message_context);
|
|
vkd3d_shader_message_context_trace_messages(&message_context);
|
|
vkd3d_shader_string_from_message_context(messages, &message_context);
|
|
vkd3d_shader_message_context_cleanup(&message_context);
|
|
return ret;
|
|
}
|
|
|
|
-static int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data,
|
|
+int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data,
|
|
uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info,
|
|
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
|
|
{
|
|
@@ -1917,6 +1932,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
|
|
if (ret >= 0)
|
|
vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_TARGET);
|
|
|
|
+ vkd3d_shader_dump_messages(&dump_data, &message_context);
|
|
vkd3d_shader_message_context_trace_messages(&message_context);
|
|
vkd3d_shader_string_from_message_context(messages, &message_context);
|
|
vkd3d_shader_message_context_cleanup(&message_context);
|
|
@@ -2240,6 +2256,7 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info
|
|
if ((ret = preproc_lexer_parse(compile_info, out, &message_context)) >= 0)
|
|
vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_PREPROC);
|
|
|
|
+ vkd3d_shader_dump_messages(&dump_data, &message_context);
|
|
vkd3d_shader_message_context_trace_messages(&message_context);
|
|
vkd3d_shader_string_from_message_context(messages, &message_context);
|
|
vkd3d_shader_message_context_cleanup(&message_context);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
index 794600302f9..35af5f7ec77 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
@@ -1716,6 +1716,9 @@ const struct vkd3d_shader_parameter1 *vsir_program_get_parameter(
|
|
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
|
|
const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type,
|
|
enum vsir_normalisation_level normalisation_level);
|
|
+int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data,
|
|
+ uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info,
|
|
+ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
|
|
enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_t config_flags,
|
|
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context);
|
|
enum vkd3d_result vsir_program_optimize(struct vsir_program *program, uint64_t config_flags,
|
|
--
|
|
2.51.0
|
|
|