mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
4879 lines
195 KiB
Diff
4879 lines
195 KiB
Diff
From caa0d7f0cafae8a67fb79dd7426839126285a092 Mon Sep 17 00:00:00 2001
|
|
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
|
Date: Fri, 29 Nov 2024 07:14:57 +1100
|
|
Subject: [PATCH] Updated vkd3d to 9619582d1b6a54720e17a148a72b446fda2fd41f.
|
|
|
|
---
|
|
libs/vkd3d/include/private/vkd3d_common.h | 2 +-
|
|
libs/vkd3d/include/vkd3d_shader.h | 25 +
|
|
libs/vkd3d/libs/vkd3d-common/blob.c | 1 +
|
|
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 2 +
|
|
libs/vkd3d/libs/vkd3d-shader/dxil.c | 29 +-
|
|
libs/vkd3d/libs/vkd3d-shader/fx.c | 151 ++-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 69 +-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 38 +-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.l | 3 +
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 26 +-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 1164 ++++++++++++++---
|
|
libs/vkd3d/libs/vkd3d-shader/ir.c | 519 +++++++-
|
|
libs/vkd3d/libs/vkd3d-shader/msl.c | 237 +++-
|
|
libs/vkd3d/libs/vkd3d-shader/preproc.l | 1 +
|
|
libs/vkd3d/libs/vkd3d-shader/spirv.c | 80 +-
|
|
libs/vkd3d/libs/vkd3d-shader/tpf.c | 1090 +--------------
|
|
.../libs/vkd3d-shader/vkd3d_shader_main.c | 20 +
|
|
.../libs/vkd3d-shader/vkd3d_shader_private.h | 1 +
|
|
18 files changed, 2038 insertions(+), 1420 deletions(-)
|
|
|
|
diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h
|
|
index ec1dd70c9b2..fd62730f948 100644
|
|
--- a/libs/vkd3d/include/private/vkd3d_common.h
|
|
+++ b/libs/vkd3d/include/private/vkd3d_common.h
|
|
@@ -275,7 +275,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v)
|
|
{
|
|
#ifdef _MSC_VER
|
|
return __popcnt(v);
|
|
-#elif defined(__MINGW32__)
|
|
+#elif defined(HAVE_BUILTIN_POPCOUNT)
|
|
return __builtin_popcount(v);
|
|
#else
|
|
v -= (v >> 1) & 0x55555555;
|
|
diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
|
|
index f95caa2f825..cb561d7f079 100644
|
|
--- a/libs/vkd3d/include/vkd3d_shader.h
|
|
+++ b/libs/vkd3d/include/vkd3d_shader.h
|
|
@@ -112,6 +112,11 @@ enum vkd3d_shader_structure_type
|
|
* \since 1.13
|
|
*/
|
|
VKD3D_SHADER_STRUCTURE_TYPE_PARAMETER_INFO,
|
|
+ /**
|
|
+ * The structure is a vkd3d_shader_scan_hull_shader_tessellation_info structure.
|
|
+ * \since 1.15
|
|
+ */
|
|
+ VKD3D_SHADER_STRUCTURE_TYPE_SCAN_HULL_SHADER_TESSELLATION_INFO,
|
|
|
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
|
|
};
|
|
@@ -2040,6 +2045,26 @@ struct vkd3d_shader_scan_combined_resource_sampler_info
|
|
unsigned int combined_sampler_count;
|
|
};
|
|
|
|
+/**
|
|
+ * A chained structure describing the tessellation information in a hull shader.
|
|
+ *
|
|
+ * This structure extends vkd3d_shader_compile_info.
|
|
+ *
|
|
+ * \since 1.15
|
|
+ */
|
|
+struct vkd3d_shader_scan_hull_shader_tessellation_info
|
|
+{
|
|
+ /** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_SCAN_HULL_SHADER_TESSELLATION_INFO. */
|
|
+ enum vkd3d_shader_structure_type type;
|
|
+ /** Optional pointer to a structure containing further parameters. */
|
|
+ const void *next;
|
|
+
|
|
+ /** The tessellation output primitive. */
|
|
+ enum vkd3d_shader_tessellator_output_primitive output_primitive;
|
|
+ /** The tessellation partitioning mode. */
|
|
+ enum vkd3d_shader_tessellator_partitioning partitioning;
|
|
+};
|
|
+
|
|
/**
|
|
* Data type of a shader varying, returned as part of struct
|
|
* vkd3d_shader_signature_element.
|
|
diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c
|
|
index f60ef7db769..c2c6ad67804 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-common/blob.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-common/blob.c
|
|
@@ -20,6 +20,7 @@
|
|
#define WIDL_C_INLINE_WRAPPERS
|
|
#endif
|
|
#define COBJMACROS
|
|
+
|
|
#define CONST_VTABLE
|
|
#include "vkd3d.h"
|
|
#include "vkd3d_blob.h"
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
index 9e2eacbcfa6..bda9bc72f56 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
@@ -1565,6 +1565,7 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type)
|
|
case HLSL_CLASS_HULL_SHADER:
|
|
case HLSL_CLASS_GEOMETRY_SHADER:
|
|
case HLSL_CLASS_BLEND_STATE:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
case HLSL_CLASS_NULL:
|
|
break;
|
|
}
|
|
@@ -1671,6 +1672,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type)
|
|
case HLSL_CLASS_HULL_SHADER:
|
|
case HLSL_CLASS_GEOMETRY_SHADER:
|
|
case HLSL_CLASS_BLEND_STATE:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
case HLSL_CLASS_NULL:
|
|
break;
|
|
}
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
index 7099bcc9ce2..71f3c7f17b0 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
@@ -3824,7 +3824,7 @@ static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_par
|
|
}
|
|
|
|
static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind(
|
|
- enum vkd3d_shader_sysval_semantic sysval_semantic)
|
|
+ enum vkd3d_shader_sysval_semantic sysval_semantic, bool is_input)
|
|
{
|
|
switch (sysval_semantic)
|
|
{
|
|
@@ -3834,7 +3834,7 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind(
|
|
case VKD3D_SHADER_SV_SAMPLE_INDEX:
|
|
return VKD3DSPR_NULL;
|
|
case VKD3D_SHADER_SV_COVERAGE:
|
|
- return VKD3DSPR_COVERAGE;
|
|
+ return is_input ? VKD3DSPR_COVERAGE : VKD3DSPR_SAMPLEMASK;
|
|
case VKD3D_SHADER_SV_DEPTH:
|
|
return VKD3DSPR_DEPTHOUT;
|
|
case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL:
|
|
@@ -3884,7 +3884,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade
|
|
param = ¶ms[i];
|
|
|
|
if (e->register_index == UINT_MAX
|
|
- && (io_reg_type = register_type_from_dxil_semantic_kind(e->sysval_semantic)) != VKD3DSPR_NULL)
|
|
+ && (io_reg_type = register_type_from_dxil_semantic_kind(e->sysval_semantic, is_input)) != VKD3DSPR_NULL)
|
|
{
|
|
dst_param_io_init(param, e, io_reg_type);
|
|
continue;
|
|
@@ -9348,7 +9348,7 @@ static void signature_element_read_additional_element_values(struct signature_el
|
|
}
|
|
|
|
static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const struct sm6_metadata_value *m,
|
|
- struct shader_signature *s, enum vkd3d_tessellator_domain tessellator_domain)
|
|
+ struct shader_signature *s, enum vkd3d_tessellator_domain tessellator_domain, bool is_input)
|
|
{
|
|
unsigned int i, j, column_count, operand_count, index;
|
|
const struct sm6_metadata_node *node, *element_node;
|
|
@@ -9466,7 +9466,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const
|
|
|
|
if ((is_register = e->register_index == UINT_MAX))
|
|
{
|
|
- if (register_type_from_dxil_semantic_kind(e->sysval_semantic) == VKD3DSPR_INVALID)
|
|
+ if (register_type_from_dxil_semantic_kind(e->sysval_semantic, is_input) == VKD3DSPR_INVALID)
|
|
{
|
|
WARN("Unhandled I/O register semantic kind %u.\n", j);
|
|
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE,
|
|
@@ -9578,17 +9578,17 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons
|
|
}
|
|
|
|
if (m->u.node->operand_count && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[0],
|
|
- &program->input_signature, tessellator_domain)) < 0)
|
|
+ &program->input_signature, tessellator_domain, true)) < 0)
|
|
{
|
|
return ret;
|
|
}
|
|
if (m->u.node->operand_count > 1 && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[1],
|
|
- &program->output_signature, tessellator_domain)) < 0)
|
|
+ &program->output_signature, tessellator_domain, false)) < 0)
|
|
{
|
|
return ret;
|
|
}
|
|
if (m->u.node->operand_count > 1 && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[2],
|
|
- &program->patch_constant_signature, tessellator_domain)) < 0)
|
|
+ &program->patch_constant_signature, tessellator_domain, false)) < 0)
|
|
{
|
|
return ret;
|
|
}
|
|
@@ -9717,12 +9717,13 @@ static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6,
|
|
|
|
ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_TESSELLATOR_DOMAIN);
|
|
ins->declaration.tessellator_domain = tessellator_domain;
|
|
+ sm6->p.program->tess_domain = tessellator_domain;
|
|
}
|
|
|
|
-static void sm6_parser_validate_control_point_count(struct sm6_parser *sm6, unsigned int count,
|
|
- const char *type)
|
|
+static void sm6_parser_validate_control_point_count(struct sm6_parser *sm6,
|
|
+ unsigned int count, bool allow_zero, const char *type)
|
|
{
|
|
- if (!count || count > 32)
|
|
+ if ((!count && !allow_zero) || count > 32)
|
|
{
|
|
WARN("%s control point count %u invalid.\n", type, count);
|
|
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
|
|
@@ -9951,7 +9952,7 @@ static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_pa
|
|
}
|
|
|
|
sm6_parser_emit_dcl_tessellator_domain(sm6, operands[0]);
|
|
- sm6_parser_validate_control_point_count(sm6, operands[1], "Domain shader input");
|
|
+ sm6_parser_validate_control_point_count(sm6, operands[1], true, "Domain shader input");
|
|
sm6->p.program->input_control_point_count = operands[1];
|
|
|
|
return operands[0];
|
|
@@ -10010,9 +10011,9 @@ static enum vkd3d_tessellator_domain sm6_parser_hs_properties_init(struct sm6_pa
|
|
}
|
|
}
|
|
|
|
- sm6_parser_validate_control_point_count(sm6, operands[1], "Hull shader input");
|
|
+ sm6_parser_validate_control_point_count(sm6, operands[1], false, "Hull shader input");
|
|
program->input_control_point_count = operands[1];
|
|
- sm6_parser_validate_control_point_count(sm6, operands[2], "Hull shader output");
|
|
+ sm6_parser_validate_control_point_count(sm6, operands[2], false, "Hull shader output");
|
|
sm6_parser_emit_dcl_count(sm6, VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT, operands[2]);
|
|
program->output_control_point_count = operands[2];
|
|
sm6_parser_emit_dcl_tessellator_domain(sm6, operands[3]);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
index e22177e1e30..064e15c4b60 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
@@ -36,6 +36,16 @@ struct fx_4_binary_type
|
|
uint32_t typeinfo;
|
|
};
|
|
|
|
+struct fx_5_shader
|
|
+{
|
|
+ uint32_t offset;
|
|
+ uint32_t sodecl[4];
|
|
+ uint32_t sodecl_count;
|
|
+ uint32_t rast_stream;
|
|
+ uint32_t iface_bindings_count;
|
|
+ uint32_t iface_bindings;
|
|
+};
|
|
+
|
|
struct string_entry
|
|
{
|
|
struct rb_entry entry;
|
|
@@ -550,6 +560,8 @@ enum fx_4_type_constants
|
|
FX_4_ASSIGNMENT_VARIABLE = 0x2,
|
|
FX_4_ASSIGNMENT_ARRAY_CONSTANT_INDEX = 0x3,
|
|
FX_4_ASSIGNMENT_ARRAY_VARIABLE_INDEX = 0x4,
|
|
+ FX_4_ASSIGNMENT_INLINE_SHADER = 0x7,
|
|
+ FX_5_ASSIGNMENT_INLINE_SHADER = 0x8,
|
|
};
|
|
|
|
static const uint32_t fx_4_numeric_base_types[] =
|
|
@@ -762,6 +774,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
case HLSL_CLASS_TECHNIQUE:
|
|
case HLSL_CLASS_CONSTANT_BUFFER:
|
|
case HLSL_CLASS_NULL:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
vkd3d_unreachable();
|
|
|
|
case HLSL_CLASS_VOID:
|
|
@@ -1298,6 +1311,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type
|
|
case HLSL_CLASS_TECHNIQUE:
|
|
case HLSL_CLASS_CONSTANT_BUFFER:
|
|
case HLSL_CLASS_NULL:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
/* This cannot appear as an extern variable. */
|
|
break;
|
|
}
|
|
@@ -1834,6 +1848,7 @@ enum state_property_component_type
|
|
FX_BLEND,
|
|
FX_VERTEXSHADER,
|
|
FX_PIXELSHADER,
|
|
+ FX_GEOMETRYSHADER,
|
|
FX_COMPONENT_TYPE_COUNT,
|
|
};
|
|
|
|
@@ -2065,6 +2080,7 @@ fx_4_states[] =
|
|
|
|
{ "VertexShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 6 },
|
|
{ "PixelShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 7 },
|
|
+ { "GeometryShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_GEOMETRYSHADER, 1, 1, 8 },
|
|
{ "DS_StencilRef", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 9 },
|
|
{ "AB_BlendFactor", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 10 },
|
|
{ "AB_SampleMask", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 11 },
|
|
@@ -2951,7 +2967,7 @@ static void VKD3D_PRINTF_FUNC(3, 4) fx_parser_error(struct fx_parser *parser, en
|
|
|
|
static int fx_2_parse(struct fx_parser *parser)
|
|
{
|
|
- fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing fx_2_0 binaries is not implemented.\n");
|
|
+ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing fx_2_0 binaries is not implemented.");
|
|
|
|
return -1;
|
|
}
|
|
@@ -3120,7 +3136,7 @@ static void fx_parse_fx_4_annotations(struct fx_parser *parser)
|
|
else
|
|
{
|
|
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA,
|
|
- "Only numeric and string types are supported in annotations.\n");
|
|
+ "Only numeric and string types are supported in annotations.");
|
|
}
|
|
|
|
if (type.element_count)
|
|
@@ -3210,27 +3226,13 @@ static void fx_parse_buffers(struct fx_parser *parser)
|
|
}
|
|
}
|
|
|
|
-static void fx_4_parse_shader_initializer(struct fx_parser *parser, unsigned int object_type)
|
|
+static void fx_4_parse_shader_blob(struct fx_parser *parser, unsigned int object_type, const struct fx_5_shader *shader)
|
|
{
|
|
struct vkd3d_shader_compile_info info = { 0 };
|
|
struct vkd3d_shader_code output;
|
|
- uint32_t data_size, offset;
|
|
const void *data = NULL;
|
|
const char *p, *q, *end;
|
|
- struct fx_5_shader
|
|
- {
|
|
- uint32_t offset;
|
|
- uint32_t sodecl[4];
|
|
- uint32_t sodecl_count;
|
|
- uint32_t rast_stream;
|
|
- uint32_t iface_bindings_count;
|
|
- uint32_t iface_bindings;
|
|
- } shader5;
|
|
- struct fx_4_gs_so
|
|
- {
|
|
- uint32_t offset;
|
|
- uint32_t sodecl;
|
|
- } gs_so;
|
|
+ uint32_t data_size;
|
|
int ret;
|
|
|
|
static const struct vkd3d_shader_compile_option options[] =
|
|
@@ -3238,35 +3240,9 @@ static void fx_4_parse_shader_initializer(struct fx_parser *parser, unsigned int
|
|
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_14},
|
|
};
|
|
|
|
- switch (object_type)
|
|
- {
|
|
- case FX_4_OBJECT_TYPE_PIXEL_SHADER:
|
|
- case FX_4_OBJECT_TYPE_VERTEX_SHADER:
|
|
- case FX_4_OBJECT_TYPE_GEOMETRY_SHADER:
|
|
- offset = fx_parser_read_u32(parser);
|
|
- break;
|
|
-
|
|
- case FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO:
|
|
- fx_parser_read_u32s(parser, &gs_so, sizeof(gs_so));
|
|
- offset = gs_so.offset;
|
|
- break;
|
|
-
|
|
- case FX_5_OBJECT_TYPE_GEOMETRY_SHADER:
|
|
- case FX_5_OBJECT_TYPE_COMPUTE_SHADER:
|
|
- case FX_5_OBJECT_TYPE_HULL_SHADER:
|
|
- case FX_5_OBJECT_TYPE_DOMAIN_SHADER:
|
|
- fx_parser_read_u32s(parser, &shader5, sizeof(shader5));
|
|
- offset = shader5.offset;
|
|
- break;
|
|
-
|
|
- default:
|
|
- parser->failed = true;
|
|
- return;
|
|
- }
|
|
-
|
|
- fx_parser_read_unstructured(parser, &data_size, offset, sizeof(data_size));
|
|
+ fx_parser_read_unstructured(parser, &data_size, shader->offset, sizeof(data_size));
|
|
if (data_size)
|
|
- data = fx_parser_get_unstructured_ptr(parser, offset + 4, data_size);
|
|
+ data = fx_parser_get_unstructured_ptr(parser, shader->offset + 4, data_size);
|
|
|
|
if (!data)
|
|
return;
|
|
@@ -3283,7 +3259,7 @@ static void fx_4_parse_shader_initializer(struct fx_parser *parser, unsigned int
|
|
if ((ret = vkd3d_shader_compile(&info, &output, NULL)) < 0)
|
|
{
|
|
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA,
|
|
- "Failed to disassemble shader blob.\n");
|
|
+ "Failed to disassemble shader blob.");
|
|
return;
|
|
}
|
|
parse_fx_print_indent(parser);
|
|
@@ -3307,26 +3283,58 @@ static void fx_4_parse_shader_initializer(struct fx_parser *parser, unsigned int
|
|
|
|
parse_fx_print_indent(parser);
|
|
vkd3d_string_buffer_printf(&parser->buffer, "}");
|
|
- if (object_type == FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO && gs_so.sodecl)
|
|
+ if (object_type == FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO && shader->sodecl[0])
|
|
{
|
|
vkd3d_string_buffer_printf(&parser->buffer, "\n/* Stream output declaration: \"%s\" */",
|
|
- fx_4_get_string(parser, gs_so.sodecl));
|
|
+ fx_4_get_string(parser, shader->sodecl[0]));
|
|
}
|
|
else if (object_type == FX_5_OBJECT_TYPE_GEOMETRY_SHADER)
|
|
{
|
|
- for (unsigned int i = 0; i < ARRAY_SIZE(shader5.sodecl); ++i)
|
|
+ for (unsigned int i = 0; i < ARRAY_SIZE(shader->sodecl); ++i)
|
|
{
|
|
- if (shader5.sodecl[i])
|
|
+ if (shader->sodecl[i])
|
|
vkd3d_string_buffer_printf(&parser->buffer, "\n/* Stream output %u declaration: \"%s\" */",
|
|
- i, fx_4_get_string(parser, shader5.sodecl[i]));
|
|
+ i, fx_4_get_string(parser, shader->sodecl[i]));
|
|
}
|
|
- if (shader5.sodecl_count)
|
|
- vkd3d_string_buffer_printf(&parser->buffer, "\n/* Rasterized stream %u */", shader5.rast_stream);
|
|
+ if (shader->sodecl_count)
|
|
+ vkd3d_string_buffer_printf(&parser->buffer, "\n/* Rasterized stream %u */", shader->rast_stream);
|
|
}
|
|
|
|
vkd3d_shader_free_shader_code(&output);
|
|
}
|
|
|
|
+static void fx_4_parse_shader_initializer(struct fx_parser *parser, unsigned int object_type)
|
|
+{
|
|
+ struct fx_5_shader shader = { 0 };
|
|
+
|
|
+ switch (object_type)
|
|
+ {
|
|
+ case FX_4_OBJECT_TYPE_PIXEL_SHADER:
|
|
+ case FX_4_OBJECT_TYPE_VERTEX_SHADER:
|
|
+ case FX_4_OBJECT_TYPE_GEOMETRY_SHADER:
|
|
+ shader.offset = fx_parser_read_u32(parser);
|
|
+ break;
|
|
+
|
|
+ case FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO:
|
|
+ shader.offset = fx_parser_read_u32(parser);
|
|
+ shader.sodecl[0] = fx_parser_read_u32(parser);
|
|
+ break;
|
|
+
|
|
+ case FX_5_OBJECT_TYPE_GEOMETRY_SHADER:
|
|
+ case FX_5_OBJECT_TYPE_COMPUTE_SHADER:
|
|
+ case FX_5_OBJECT_TYPE_HULL_SHADER:
|
|
+ case FX_5_OBJECT_TYPE_DOMAIN_SHADER:
|
|
+ fx_parser_read_u32s(parser, &shader, sizeof(shader));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ parser->failed = true;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ fx_4_parse_shader_blob(parser, object_type, &shader);
|
|
+}
|
|
+
|
|
static bool fx_4_object_has_initializer(const struct fx_4_binary_type *type)
|
|
{
|
|
switch (type->typeinfo)
|
|
@@ -3390,6 +3398,8 @@ static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32
|
|
[FX_UINT8] = "byte",
|
|
};
|
|
const struct rhs_named_value *named_value;
|
|
+ struct fx_5_shader shader = { 0 };
|
|
+ unsigned int shader_type = 0;
|
|
uint32_t i, j, comp_count;
|
|
struct fx_4_state *state;
|
|
|
|
@@ -3400,7 +3410,7 @@ static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32
|
|
if (!(state = bsearch(&entry.id, fx_4_states, ARRAY_SIZE(fx_4_states),
|
|
sizeof(*fx_4_states), fx_4_state_id_compare)))
|
|
{
|
|
- fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, "Unrecognized state id %#x.\n", entry.id);
|
|
+ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, "Unrecognized state id %#x.", entry.id);
|
|
break;
|
|
}
|
|
|
|
@@ -3486,9 +3496,38 @@ static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32
|
|
vkd3d_string_buffer_printf(&parser->buffer, "%s[%s]", fx_4_get_string(parser, index.name),
|
|
fx_4_get_string(parser, index.index));
|
|
break;
|
|
+ case FX_4_ASSIGNMENT_INLINE_SHADER:
|
|
+ case FX_5_ASSIGNMENT_INLINE_SHADER:
|
|
+ {
|
|
+ bool shader5 = entry.type == FX_5_ASSIGNMENT_INLINE_SHADER;
|
|
+
|
|
+ if (shader5)
|
|
+ fx_parser_read_unstructured(parser, &shader, entry.value, sizeof(shader));
|
|
+ else
|
|
+ fx_parser_read_unstructured(parser, &shader, entry.value, 2 * sizeof(uint32_t));
|
|
+
|
|
+ if (state->type == FX_PIXELSHADER)
|
|
+ shader_type = FX_4_OBJECT_TYPE_PIXEL_SHADER;
|
|
+ else if (state->type == FX_VERTEXSHADER)
|
|
+ shader_type = FX_4_OBJECT_TYPE_VERTEX_SHADER;
|
|
+ else if (state->type == FX_GEOMETRYSHADER)
|
|
+ shader_type = shader5 ? FX_5_OBJECT_TYPE_GEOMETRY_SHADER : FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO;
|
|
+ else if (state->type == FX_HULLSHADER)
|
|
+ shader_type = FX_5_OBJECT_TYPE_HULL_SHADER;
|
|
+ else if (state->type == FX_DOMAINSHADER)
|
|
+ shader_type = FX_5_OBJECT_TYPE_DOMAIN_SHADER;
|
|
+ else if (state->type == FX_COMPUTESHADER)
|
|
+ shader_type = FX_5_OBJECT_TYPE_COMPUTE_SHADER;
|
|
+
|
|
+ vkd3d_string_buffer_printf(&parser->buffer, "\n");
|
|
+ parse_fx_start_indent(parser);
|
|
+ fx_4_parse_shader_blob(parser, shader_type, &shader);
|
|
+ parse_fx_end_indent(parser);
|
|
+ break;
|
|
+ }
|
|
default:
|
|
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED,
|
|
- "Unsupported assignment type %u.\n", entry.type);
|
|
+ "Unsupported assignment type %u.", entry.type);
|
|
}
|
|
vkd3d_string_buffer_printf(&parser->buffer, ";\n");
|
|
}
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
index 96de18dc886..97c6c0a1377 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
@@ -287,6 +287,7 @@ bool hlsl_type_is_shader(const struct hlsl_type *type)
|
|
case HLSL_CLASS_UAV:
|
|
case HLSL_CLASS_CONSTANT_BUFFER:
|
|
case HLSL_CLASS_BLEND_STATE:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
case HLSL_CLASS_VOID:
|
|
case HLSL_CLASS_NULL:
|
|
return false;
|
|
@@ -434,6 +435,7 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type
|
|
case HLSL_CLASS_HULL_SHADER:
|
|
case HLSL_CLASS_GEOMETRY_SHADER:
|
|
case HLSL_CLASS_BLEND_STATE:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
case HLSL_CLASS_NULL:
|
|
break;
|
|
}
|
|
@@ -525,6 +527,7 @@ static bool type_is_single_component(const struct hlsl_type *type)
|
|
case HLSL_CLASS_PASS:
|
|
case HLSL_CLASS_TECHNIQUE:
|
|
case HLSL_CLASS_VOID:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
break;
|
|
}
|
|
vkd3d_unreachable();
|
|
@@ -680,6 +683,7 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty
|
|
case HLSL_CLASS_SCALAR:
|
|
case HLSL_CLASS_CONSTANT_BUFFER:
|
|
case HLSL_CLASS_NULL:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
vkd3d_unreachable();
|
|
}
|
|
type = next_type;
|
|
@@ -898,6 +902,22 @@ struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *ba
|
|
return type;
|
|
}
|
|
|
|
+struct hlsl_type *hlsl_new_stream_output_type(struct hlsl_ctx *ctx,
|
|
+ enum hlsl_so_object_type so_type, struct hlsl_type *data_type)
|
|
+{
|
|
+ struct hlsl_type *type;
|
|
+
|
|
+ if (!(type = hlsl_alloc(ctx, sizeof(*type))))
|
|
+ return NULL;
|
|
+ type->class = HLSL_CLASS_STREAM_OUTPUT;
|
|
+ type->e.so.so_type = so_type;
|
|
+ type->e.so.type = data_type;
|
|
+
|
|
+ list_add_tail(&ctx->types, &type->entry);
|
|
+
|
|
+ return type;
|
|
+}
|
|
+
|
|
struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name,
|
|
struct hlsl_struct_field *fields, size_t field_count)
|
|
{
|
|
@@ -1086,6 +1106,7 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type)
|
|
case HLSL_CLASS_PASS:
|
|
case HLSL_CLASS_TECHNIQUE:
|
|
case HLSL_CLASS_VOID:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
break;
|
|
}
|
|
|
|
@@ -1157,6 +1178,11 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2
|
|
case HLSL_CLASS_CONSTANT_BUFFER:
|
|
return hlsl_types_are_equal(t1->e.resource.format, t2->e.resource.format);
|
|
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
+ if (t1->e.so.so_type != t2->e.so.so_type)
|
|
+ return false;
|
|
+ return hlsl_types_are_equal(t1->e.so.type, t2->e.so.type);
|
|
+
|
|
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
|
case HLSL_CLASS_EFFECT_GROUP:
|
|
@@ -1695,22 +1721,6 @@ struct hlsl_ir_node *hlsl_new_switch(struct hlsl_ctx *ctx, struct hlsl_ir_node *
|
|
return &s->node;
|
|
}
|
|
|
|
-struct hlsl_ir_node *hlsl_new_vsir_instruction_ref(struct hlsl_ctx *ctx, unsigned int vsir_instr_idx,
|
|
- struct hlsl_type *type, const struct hlsl_reg *reg, const struct vkd3d_shader_location *loc)
|
|
-{
|
|
- struct hlsl_ir_vsir_instruction_ref *vsir_instr;
|
|
-
|
|
- if (!(vsir_instr = hlsl_alloc(ctx, sizeof(*vsir_instr))))
|
|
- return NULL;
|
|
- init_node(&vsir_instr->node, HLSL_IR_VSIR_INSTRUCTION_REF, type, loc);
|
|
- vsir_instr->vsir_instr_idx = vsir_instr_idx;
|
|
-
|
|
- if (reg)
|
|
- vsir_instr->node.reg = *reg;
|
|
-
|
|
- return &vsir_instr->node;
|
|
-}
|
|
-
|
|
struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
|
|
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc)
|
|
{
|
|
@@ -2533,9 +2543,6 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
|
|
|
|
case HLSL_IR_STATEBLOCK_CONSTANT:
|
|
return clone_stateblock_constant(ctx, map, hlsl_ir_stateblock_constant(instr));
|
|
-
|
|
- case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
- vkd3d_unreachable();
|
|
}
|
|
|
|
vkd3d_unreachable();
|
|
@@ -2836,6 +2843,20 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru
|
|
vkd3d_string_buffer_printf(string, "<error type>");
|
|
return string;
|
|
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
+ if (type->e.so.so_type == HLSL_STREAM_OUTPUT_POINT_STREAM)
|
|
+ vkd3d_string_buffer_printf(string, "PointStream");
|
|
+ else if (type->e.so.so_type == HLSL_STREAM_OUTPUT_LINE_STREAM)
|
|
+ vkd3d_string_buffer_printf(string, "LineStream");
|
|
+ else
|
|
+ vkd3d_string_buffer_printf(string, "TriangleStream");
|
|
+ if ((inner_string = hlsl_type_to_string(ctx, type->e.so.type)))
|
|
+ {
|
|
+ vkd3d_string_buffer_printf(string, "<%s>", inner_string->buffer);
|
|
+ hlsl_release_string_buffer(ctx, inner_string);
|
|
+ }
|
|
+ return string;
|
|
+
|
|
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
|
case HLSL_CLASS_EFFECT_GROUP:
|
|
@@ -2968,7 +2989,6 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
|
|
[HLSL_IR_COMPILE] = "HLSL_IR_COMPILE",
|
|
[HLSL_IR_SAMPLER_STATE] = "HLSL_IR_SAMPLER_STATE",
|
|
[HLSL_IR_STATEBLOCK_CONSTANT] = "HLSL_IR_STATEBLOCK_CONSTANT",
|
|
- [HLSL_IR_VSIR_INSTRUCTION_REF] = "HLSL_IR_VSIR_INSTRUCTION_REF",
|
|
};
|
|
|
|
if (type >= ARRAY_SIZE(names))
|
|
@@ -3562,11 +3582,6 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
|
|
case HLSL_IR_STATEBLOCK_CONSTANT:
|
|
dump_ir_stateblock_constant(buffer, hlsl_ir_stateblock_constant(instr));
|
|
break;
|
|
-
|
|
- case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
- vkd3d_string_buffer_printf(buffer, "vsir_program instruction %u",
|
|
- hlsl_ir_vsir_instruction_ref(instr)->vsir_instr_idx);
|
|
- break;
|
|
}
|
|
}
|
|
|
|
@@ -3875,10 +3890,6 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
|
|
case HLSL_IR_STATEBLOCK_CONSTANT:
|
|
free_ir_stateblock_constant(hlsl_ir_stateblock_constant(node));
|
|
break;
|
|
-
|
|
- case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
- vkd3d_free(hlsl_ir_vsir_instruction_ref(node));
|
|
- break;
|
|
}
|
|
}
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
index 075c76cb0e2..25d1b8df947 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
@@ -22,7 +22,6 @@
|
|
|
|
#include "vkd3d_shader_private.h"
|
|
#include "wine/rbtree.h"
|
|
-#include "d3dcommon.h"
|
|
#include "d3dx9shader.h"
|
|
|
|
/* The general IR structure is inspired by Mesa GLSL hir, even though the code
|
|
@@ -105,6 +104,7 @@ enum hlsl_type_class
|
|
HLSL_CLASS_GEOMETRY_SHADER,
|
|
HLSL_CLASS_CONSTANT_BUFFER,
|
|
HLSL_CLASS_BLEND_STATE,
|
|
+ HLSL_CLASS_STREAM_OUTPUT,
|
|
HLSL_CLASS_VOID,
|
|
HLSL_CLASS_NULL,
|
|
HLSL_CLASS_ERROR,
|
|
@@ -142,6 +142,13 @@ enum hlsl_sampler_dim
|
|
/* NOTE: Remember to update object_methods[] in hlsl.y if this enum is modified. */
|
|
};
|
|
|
|
+enum hlsl_so_object_type
|
|
+{
|
|
+ HLSL_STREAM_OUTPUT_POINT_STREAM,
|
|
+ HLSL_STREAM_OUTPUT_LINE_STREAM,
|
|
+ HLSL_STREAM_OUTPUT_TRIANGLE_STREAM,
|
|
+};
|
|
+
|
|
enum hlsl_regset
|
|
{
|
|
HLSL_REGSET_SAMPLERS,
|
|
@@ -220,6 +227,12 @@ struct hlsl_type
|
|
} resource;
|
|
/* Additional field to distinguish object types. Currently used only for technique types. */
|
|
unsigned int version;
|
|
+ /* Additional information if type is HLSL_CLASS_STREAM_OUTPUT. */
|
|
+ struct
|
|
+ {
|
|
+ struct hlsl_type *type;
|
|
+ enum hlsl_so_object_type so_type;
|
|
+ } so;
|
|
} e;
|
|
|
|
/* Number of numeric register components used by one value of this type, for each regset.
|
|
@@ -330,8 +343,6 @@ enum hlsl_ir_node_type
|
|
HLSL_IR_COMPILE,
|
|
HLSL_IR_SAMPLER_STATE,
|
|
HLSL_IR_STATEBLOCK_CONSTANT,
|
|
-
|
|
- HLSL_IR_VSIR_INSTRUCTION_REF,
|
|
};
|
|
|
|
/* Common data for every type of IR instruction node. */
|
|
@@ -934,16 +945,6 @@ struct hlsl_ir_stateblock_constant
|
|
char *name;
|
|
};
|
|
|
|
-/* A vkd3d_shader_instruction that can be inserted in a hlsl_block.
|
|
- * Only used for the HLSL IR to vsir translation, might be removed once this translation is complete. */
|
|
-struct hlsl_ir_vsir_instruction_ref
|
|
-{
|
|
- struct hlsl_ir_node node;
|
|
-
|
|
- /* Index to a vkd3d_shader_instruction within a vkd3d_shader_instruction_array in a vsir_program. */
|
|
- unsigned int vsir_instr_idx;
|
|
-};
|
|
-
|
|
struct hlsl_scope
|
|
{
|
|
/* Item entry for hlsl_ctx.scopes. */
|
|
@@ -1259,12 +1260,6 @@ static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(co
|
|
return CONTAINING_RECORD(node, struct hlsl_ir_stateblock_constant, node);
|
|
}
|
|
|
|
-static inline struct hlsl_ir_vsir_instruction_ref *hlsl_ir_vsir_instruction_ref(const struct hlsl_ir_node *node)
|
|
-{
|
|
- VKD3D_ASSERT(node->type == HLSL_IR_VSIR_INSTRUCTION_REF);
|
|
- return CONTAINING_RECORD(node, struct hlsl_ir_vsir_instruction_ref, node);
|
|
-}
|
|
-
|
|
static inline void hlsl_block_init(struct hlsl_block *block)
|
|
{
|
|
list_init(&block->instrs);
|
|
@@ -1519,6 +1514,8 @@ struct hlsl_ir_node *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *cond
|
|
struct hlsl_ir_node *hlsl_new_int_constant(struct hlsl_ctx *ctx, int32_t n, const struct vkd3d_shader_location *loc);
|
|
struct hlsl_ir_node *hlsl_new_jump(struct hlsl_ctx *ctx,
|
|
enum hlsl_ir_jump_type type, struct hlsl_ir_node *condition, const struct vkd3d_shader_location *loc);
|
|
+struct hlsl_type *hlsl_new_stream_output_type(struct hlsl_ctx *ctx,
|
|
+ enum hlsl_so_object_type so_type, struct hlsl_type *type);
|
|
struct hlsl_ir_node *hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op,
|
|
struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, struct hlsl_ir_node *arg3);
|
|
|
|
@@ -1588,9 +1585,6 @@ struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned
|
|
struct hlsl_ir_node *hlsl_new_switch(struct hlsl_ctx *ctx, struct hlsl_ir_node *selector,
|
|
struct list *cases, const struct vkd3d_shader_location *loc);
|
|
|
|
-struct hlsl_ir_node *hlsl_new_vsir_instruction_ref(struct hlsl_ctx *ctx, unsigned int vsir_instr_idx,
|
|
- struct hlsl_type *type, const struct hlsl_reg *reg, const struct vkd3d_shader_location *loc);
|
|
-
|
|
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
|
|
enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
|
|
void hlsl_fixme(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
|
index 8dace11916a..31fb30521e9 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
|
@@ -104,6 +104,7 @@ if {return KW_IF; }
|
|
in {return KW_IN; }
|
|
inline {return KW_INLINE; }
|
|
inout {return KW_INOUT; }
|
|
+LineStream {return KW_LINESTREAM; }
|
|
linear {return KW_LINEAR; }
|
|
matrix {return KW_MATRIX; }
|
|
namespace {return KW_NAMESPACE; }
|
|
@@ -114,6 +115,7 @@ out {return KW_OUT; }
|
|
packoffset {return KW_PACKOFFSET; }
|
|
pass {return KW_PASS; }
|
|
PixelShader {return KW_PIXELSHADER; }
|
|
+PointStream {return KW_POINTSTREAM; }
|
|
pixelshader {return KW_PIXELSHADER; }
|
|
RasterizerOrderedBuffer {return KW_RASTERIZERORDEREDBUFFER; }
|
|
RasterizerOrderedStructuredBuffer {return KW_RASTERIZERORDEREDSTRUCTUREDBUFFER; }
|
|
@@ -170,6 +172,7 @@ texture3D {return KW_TEXTURE3D; }
|
|
TextureCube {return KW_TEXTURECUBE; }
|
|
textureCUBE {return KW_TEXTURECUBE; }
|
|
TextureCubeArray {return KW_TEXTURECUBEARRAY; }
|
|
+TriangleStream {return KW_TRIANGLESTREAM; }
|
|
true {return KW_TRUE; }
|
|
typedef {return KW_TYPEDEF; }
|
|
unsigned {return KW_UNSIGNED; }
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
index 60aade732db..5bcd5e9034b 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
@@ -678,8 +678,6 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx
|
|
hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
|
"Expected literal expression.");
|
|
break;
|
|
- case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
- vkd3d_unreachable();
|
|
}
|
|
}
|
|
|
|
@@ -6553,6 +6551,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|
struct hlsl_semantic semantic;
|
|
enum hlsl_buffer_type buffer_type;
|
|
enum hlsl_sampler_dim sampler_dim;
|
|
+ enum hlsl_so_object_type so_type;
|
|
struct hlsl_attribute *attr;
|
|
struct parse_attribute_list attr_list;
|
|
struct hlsl_ir_switch_case *switch_case;
|
|
@@ -6596,6 +6595,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|
%token KW_INLINE
|
|
%token KW_INOUT
|
|
%token KW_LINEAR
|
|
+%token KW_LINESTREAM
|
|
%token KW_MATRIX
|
|
%token KW_NAMESPACE
|
|
%token KW_NOINTERPOLATION
|
|
@@ -6605,6 +6605,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|
%token KW_PACKOFFSET
|
|
%token KW_PASS
|
|
%token KW_PIXELSHADER
|
|
+%token KW_POINTSTREAM
|
|
%token KW_RASTERIZERORDEREDBUFFER
|
|
%token KW_RASTERIZERORDEREDSTRUCTUREDBUFFER
|
|
%token KW_RASTERIZERORDEREDTEXTURE1D
|
|
@@ -6654,6 +6655,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|
%token KW_TEXTURE3D
|
|
%token KW_TEXTURECUBE
|
|
%token KW_TEXTURECUBEARRAY
|
|
+%token KW_TRIANGLESTREAM
|
|
%token KW_TRUE
|
|
%token KW_TYPEDEF
|
|
%token KW_UNSIGNED
|
|
@@ -6784,6 +6786,8 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|
|
|
%type <semantic> semantic
|
|
|
|
+%type <so_type> so_type
|
|
+
|
|
%type <state_block> state_block
|
|
|
|
%type <state_block_index> state_block_index_opt
|
|
@@ -7805,6 +7809,20 @@ rov_type:
|
|
$$ = HLSL_SAMPLER_DIM_3D;
|
|
}
|
|
|
|
+so_type:
|
|
+ KW_POINTSTREAM
|
|
+ {
|
|
+ $$ = HLSL_STREAM_OUTPUT_POINT_STREAM;
|
|
+ }
|
|
+ | KW_LINESTREAM
|
|
+ {
|
|
+ $$ = HLSL_STREAM_OUTPUT_LINE_STREAM;
|
|
+ }
|
|
+ | KW_TRIANGLESTREAM
|
|
+ {
|
|
+ $$ = HLSL_STREAM_OUTPUT_TRIANGLE_STREAM;
|
|
+ }
|
|
+
|
|
resource_format:
|
|
var_modifiers type
|
|
{
|
|
@@ -7948,6 +7966,10 @@ type_no_void:
|
|
validate_uav_type(ctx, $1, $3, &@4);
|
|
$$ = hlsl_new_uav_type(ctx, $1, $3, true);
|
|
}
|
|
+ | so_type '<' type '>'
|
|
+ {
|
|
+ $$ = hlsl_new_stream_output_type(ctx, $1, $3);
|
|
+ }
|
|
| KW_RWBYTEADDRESSBUFFER
|
|
{
|
|
$$ = hlsl_new_uav_type(ctx, HLSL_SAMPLER_DIM_RAW_BUFFER, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), false);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
index d11ff481f6b..8f45628dbee 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
@@ -19,6 +19,7 @@
|
|
*/
|
|
|
|
#include "hlsl.h"
|
|
+#include "vkd3d_shader_private.h"
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
@@ -1678,6 +1679,7 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx,
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
|
case HLSL_CLASS_GEOMETRY_SHADER:
|
|
case HLSL_CLASS_BLEND_STATE:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
case HLSL_CLASS_NULL:
|
|
break;
|
|
|
|
@@ -4162,9 +4164,6 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
|
|
case HLSL_IR_STATEBLOCK_CONSTANT:
|
|
/* Stateblock constants should not appear in the shader program. */
|
|
vkd3d_unreachable();
|
|
- case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
- /* HLSL IR nodes are not translated to hlsl_ir_vsir_instruction_ref at this point. */
|
|
- vkd3d_unreachable();
|
|
}
|
|
|
|
return false;
|
|
@@ -4304,9 +4303,6 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
|
|
case HLSL_IR_STATEBLOCK_CONSTANT:
|
|
/* Stateblock constants should not appear in the shader program. */
|
|
vkd3d_unreachable();
|
|
- case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
- /* HLSL IR nodes are not translated to hlsl_ir_vsir_instruction_ref at this point. */
|
|
- vkd3d_unreachable();
|
|
|
|
case HLSL_IR_STORE:
|
|
{
|
|
@@ -4494,6 +4490,9 @@ struct register_allocator
|
|
|
|
/* Two allocations with different mode can't share the same register. */
|
|
int mode;
|
|
+ /* If an allocation is VIP, no new allocations can be made in the
|
|
+ * register unless they are VIP as well. */
|
|
+ bool vip;
|
|
} *allocations;
|
|
size_t count, capacity;
|
|
|
|
@@ -4513,7 +4512,7 @@ struct register_allocator
|
|
};
|
|
|
|
static unsigned int get_available_writemask(const struct register_allocator *allocator,
|
|
- unsigned int first_write, unsigned int last_read, uint32_t reg_idx, int mode)
|
|
+ unsigned int first_write, unsigned int last_read, uint32_t reg_idx, int mode, bool vip)
|
|
{
|
|
unsigned int writemask = VKD3DSP_WRITEMASK_ALL;
|
|
size_t i;
|
|
@@ -4532,6 +4531,8 @@ static unsigned int get_available_writemask(const struct register_allocator *all
|
|
writemask &= ~allocation->writemask;
|
|
if (allocation->mode != mode)
|
|
writemask = 0;
|
|
+ if (allocation->vip && !vip)
|
|
+ writemask = 0;
|
|
}
|
|
|
|
if (!writemask)
|
|
@@ -4542,7 +4543,7 @@ static unsigned int get_available_writemask(const struct register_allocator *all
|
|
}
|
|
|
|
static void record_allocation(struct hlsl_ctx *ctx, struct register_allocator *allocator, uint32_t reg_idx,
|
|
- unsigned int writemask, unsigned int first_write, unsigned int last_read, int mode)
|
|
+ unsigned int writemask, unsigned int first_write, unsigned int last_read, int mode, bool vip)
|
|
{
|
|
struct allocation *allocation;
|
|
|
|
@@ -4556,16 +4557,25 @@ static void record_allocation(struct hlsl_ctx *ctx, struct register_allocator *a
|
|
allocation->first_write = first_write;
|
|
allocation->last_read = last_read;
|
|
allocation->mode = mode;
|
|
+ allocation->vip = vip;
|
|
|
|
allocator->reg_count = max(allocator->reg_count, reg_idx + 1);
|
|
}
|
|
|
|
-/* reg_size is the number of register components to be reserved, while component_count is the number
|
|
- * of components for the register's writemask. In SM1, floats and vectors allocate the whole
|
|
- * register, even if they don't use it completely. */
|
|
+/* Allocates a register (or some components of it) within the register allocator.
|
|
+ * 'reg_size' is the number of register components to be reserved.
|
|
+ * 'component_count' is the number of components for the hlsl_reg's
|
|
+ * writemask, which can be smaller than 'reg_size'. For instance, sm1
|
|
+ * floats and vectors allocate the whole register even if they are not
|
|
+ * using all components.
|
|
+ * 'mode' can be provided to avoid allocating on a register that already has an
|
|
+ * allocation with a different mode.
|
|
+ * 'force_align' can be used so that the allocation always start in '.x'.
|
|
+ * 'vip' can be used so that no new allocations can be made in the given register
|
|
+ * unless they are 'vip' as well. */
|
|
static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_allocator *allocator,
|
|
unsigned int first_write, unsigned int last_read, unsigned int reg_size,
|
|
- unsigned int component_count, int mode, bool force_align)
|
|
+ unsigned int component_count, int mode, bool force_align, bool vip)
|
|
{
|
|
struct hlsl_reg ret = {.allocation_size = 1, .allocated = true};
|
|
unsigned int required_size = force_align ? 4 : reg_size;
|
|
@@ -4579,7 +4589,7 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a
|
|
for (uint32_t reg_idx = 0; reg_idx < allocator->reg_count; ++reg_idx)
|
|
{
|
|
unsigned int available_writemask = get_available_writemask(allocator,
|
|
- first_write, last_read, reg_idx, mode);
|
|
+ first_write, last_read, reg_idx, mode, vip);
|
|
|
|
if (vkd3d_popcount(available_writemask) >= pref)
|
|
{
|
|
@@ -4589,7 +4599,8 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a
|
|
ret.id = reg_idx;
|
|
ret.writemask = hlsl_combine_writemasks(writemask,
|
|
vkd3d_write_mask_from_component_count(component_count));
|
|
- record_allocation(ctx, allocator, reg_idx, writemask, first_write, last_read, mode);
|
|
+
|
|
+ record_allocation(ctx, allocator, reg_idx, writemask, first_write, last_read, mode, vip);
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -4598,13 +4609,14 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a
|
|
ret.id = allocator->reg_count;
|
|
ret.writemask = vkd3d_write_mask_from_component_count(component_count);
|
|
record_allocation(ctx, allocator, allocator->reg_count,
|
|
- vkd3d_write_mask_from_component_count(reg_size), first_write, last_read, mode);
|
|
+ vkd3d_write_mask_from_component_count(reg_size), first_write, last_read, mode, vip);
|
|
return ret;
|
|
}
|
|
|
|
/* Allocate a register with writemask, while reserving reg_writemask. */
|
|
-static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx, struct register_allocator *allocator,
|
|
- unsigned int first_write, unsigned int last_read, uint32_t reg_writemask, uint32_t writemask, int mode)
|
|
+static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx,
|
|
+ struct register_allocator *allocator, unsigned int first_write, unsigned int last_read,
|
|
+ uint32_t reg_writemask, uint32_t writemask, int mode, bool vip)
|
|
{
|
|
struct hlsl_reg ret = {0};
|
|
uint32_t reg_idx;
|
|
@@ -4614,11 +4626,11 @@ static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx, struct
|
|
for (reg_idx = 0;; ++reg_idx)
|
|
{
|
|
if ((get_available_writemask(allocator, first_write, last_read,
|
|
- reg_idx, mode) & reg_writemask) == reg_writemask)
|
|
+ reg_idx, mode, vip) & reg_writemask) == reg_writemask)
|
|
break;
|
|
}
|
|
|
|
- record_allocation(ctx, allocator, reg_idx, reg_writemask, first_write, last_read, mode);
|
|
+ record_allocation(ctx, allocator, reg_idx, reg_writemask, first_write, last_read, mode, vip);
|
|
|
|
ret.id = reg_idx;
|
|
ret.allocation_size = 1;
|
|
@@ -4628,7 +4640,7 @@ static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx, struct
|
|
}
|
|
|
|
static bool is_range_available(const struct register_allocator *allocator, unsigned int first_write,
|
|
- unsigned int last_read, uint32_t reg_idx, unsigned int reg_size, int mode)
|
|
+ unsigned int last_read, uint32_t reg_idx, unsigned int reg_size, int mode, bool vip)
|
|
{
|
|
unsigned int last_reg_mask = (1u << (reg_size % 4)) - 1;
|
|
unsigned int writemask;
|
|
@@ -4636,18 +4648,18 @@ static bool is_range_available(const struct register_allocator *allocator, unsig
|
|
|
|
for (i = 0; i < (reg_size / 4); ++i)
|
|
{
|
|
- writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + i, mode);
|
|
+ writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + i, mode, vip);
|
|
if (writemask != VKD3DSP_WRITEMASK_ALL)
|
|
return false;
|
|
}
|
|
- writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + (reg_size / 4), mode);
|
|
+ writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + (reg_size / 4), mode, vip);
|
|
if ((writemask & last_reg_mask) != last_reg_mask)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allocator *allocator,
|
|
- unsigned int first_write, unsigned int last_read, unsigned int reg_size, int mode)
|
|
+ unsigned int first_write, unsigned int last_read, unsigned int reg_size, int mode, bool vip)
|
|
{
|
|
struct hlsl_reg ret = {0};
|
|
uint32_t reg_idx;
|
|
@@ -4655,15 +4667,15 @@ static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allo
|
|
|
|
for (reg_idx = 0;; ++reg_idx)
|
|
{
|
|
- if (is_range_available(allocator, first_write, last_read, reg_idx, reg_size, mode))
|
|
+ if (is_range_available(allocator, first_write, last_read, reg_idx, reg_size, mode, vip))
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < reg_size / 4; ++i)
|
|
- record_allocation(ctx, allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, first_write, last_read, mode);
|
|
+ record_allocation(ctx, allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, first_write, last_read, mode, vip);
|
|
if (reg_size % 4)
|
|
record_allocation(ctx, allocator, reg_idx + (reg_size / 4),
|
|
- (1u << (reg_size % 4)) - 1, first_write, last_read, mode);
|
|
+ (1u << (reg_size % 4)) - 1, first_write, last_read, mode, vip);
|
|
|
|
ret.id = reg_idx;
|
|
ret.allocation_size = align(reg_size, 4) / 4;
|
|
@@ -4679,9 +4691,9 @@ static struct hlsl_reg allocate_numeric_registers_for_type(struct hlsl_ctx *ctx,
|
|
/* 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, type->dimx, type->dimx, 0, false);
|
|
+ return allocate_register(ctx, allocator, first_write, last_read, type->dimx, type->dimx, 0, false, false);
|
|
else
|
|
- return allocate_range(ctx, allocator, first_write, last_read, reg_size, 0);
|
|
+ return allocate_range(ctx, allocator, first_write, last_read, reg_size, 0, false);
|
|
}
|
|
|
|
static const char *debug_register(char class, struct hlsl_reg reg, const struct hlsl_type *type)
|
|
@@ -4859,8 +4871,8 @@ static void allocate_instr_temp_register(struct hlsl_ctx *ctx,
|
|
}
|
|
|
|
if (reg_writemask)
|
|
- instr->reg = allocate_register_with_masks(ctx, allocator,
|
|
- instr->index, instr->last_read, reg_writemask, dst_writemask, 0);
|
|
+ instr->reg = allocate_register_with_masks(ctx, allocator, instr->index,
|
|
+ instr->last_read, reg_writemask, dst_writemask, 0, false);
|
|
else
|
|
instr->reg = allocate_numeric_registers_for_type(ctx, allocator,
|
|
instr->index, instr->last_read, instr->data_type);
|
|
@@ -5181,14 +5193,15 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi
|
|
{
|
|
if (i < bind_count)
|
|
{
|
|
- if (get_available_writemask(&allocator_used, 1, UINT_MAX, reg_idx + i, 0) != VKD3DSP_WRITEMASK_ALL)
|
|
+ if (get_available_writemask(&allocator_used, 1, UINT_MAX,
|
|
+ reg_idx + i, 0, false) != VKD3DSP_WRITEMASK_ALL)
|
|
{
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
|
|
"Overlapping register() reservations on 'c%u'.", reg_idx + i);
|
|
}
|
|
- record_allocation(ctx, &allocator_used, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX, 0);
|
|
+ record_allocation(ctx, &allocator_used, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX, 0, false);
|
|
}
|
|
- record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX, 0);
|
|
+ record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX, 0, false);
|
|
}
|
|
|
|
var->regs[HLSL_REGSET_NUMERIC].id = reg_idx;
|
|
@@ -5211,7 +5224,7 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi
|
|
|
|
if (!var->regs[HLSL_REGSET_NUMERIC].allocated)
|
|
{
|
|
- var->regs[HLSL_REGSET_NUMERIC] = allocate_range(ctx, &allocator, 1, UINT_MAX, alloc_size, 0);
|
|
+ var->regs[HLSL_REGSET_NUMERIC] = allocate_range(ctx, &allocator, 1, UINT_MAX, alloc_size, 0, false);
|
|
TRACE("Allocated %s to %s.\n", var->name,
|
|
debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type));
|
|
}
|
|
@@ -5254,7 +5267,8 @@ static uint32_t allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun
|
|
var = entry_func->parameters.vars[i];
|
|
if (var->is_output_semantic)
|
|
{
|
|
- record_allocation(ctx, &allocator, 0, VKD3DSP_WRITEMASK_ALL, var->first_write, var->last_read, 0);
|
|
+ record_allocation(ctx, &allocator, 0, VKD3DSP_WRITEMASK_ALL,
|
|
+ var->first_write, var->last_read, 0, false);
|
|
break;
|
|
}
|
|
}
|
|
@@ -5311,6 +5325,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var
|
|
|
|
enum vkd3d_shader_register_type type;
|
|
struct vkd3d_shader_version version;
|
|
+ bool special_interpolation = false;
|
|
+ bool vip_allocation = false;
|
|
uint32_t reg;
|
|
bool builtin;
|
|
|
|
@@ -5363,6 +5379,14 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var
|
|
* domains, it is allocated as if it was 'float[1]'. */
|
|
var->force_align = true;
|
|
}
|
|
+
|
|
+ if (semantic == VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX
|
|
+ || semantic == VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX
|
|
+ || semantic == VKD3D_SHADER_SV_PRIMITIVE_ID)
|
|
+ vip_allocation = true;
|
|
+
|
|
+ if (semantic == VKD3D_SHADER_SV_IS_FRONT_FACE || semantic == VKD3D_SHADER_SV_SAMPLE_INDEX)
|
|
+ special_interpolation = true;
|
|
}
|
|
|
|
if (builtin)
|
|
@@ -5376,8 +5400,11 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var
|
|
? 0 : sm4_get_interpolation_mode(var->data_type, var->storage_modifiers);
|
|
unsigned int reg_size = optimize ? var->data_type->dimx : 4;
|
|
|
|
- var->regs[HLSL_REGSET_NUMERIC] = allocate_register(ctx, allocator, 1,
|
|
- UINT_MAX, reg_size, var->data_type->dimx, mode, var->force_align);
|
|
+ if (special_interpolation)
|
|
+ mode = VKD3DSIM_NONE;
|
|
+
|
|
+ var->regs[HLSL_REGSET_NUMERIC] = allocate_register(ctx, allocator, 1, UINT_MAX,
|
|
+ reg_size, var->data_type->dimx, mode, var->force_align, vip_allocation);
|
|
|
|
TRACE("Allocated %s to %s (mode %d).\n", var->name, debug_register(output ? 'o' : 'v',
|
|
var->regs[HLSL_REGSET_NUMERIC], var->data_type), mode);
|
|
@@ -6812,7 +6839,7 @@ static void vsir_src_from_hlsl_constant_value(struct vkd3d_shader_src_param *src
|
|
}
|
|
|
|
static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src,
|
|
- struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, uint32_t map_writemask)
|
|
+ struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr, uint32_t map_writemask)
|
|
{
|
|
struct hlsl_ir_constant *constant;
|
|
|
|
@@ -6832,6 +6859,242 @@ static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src,
|
|
}
|
|
}
|
|
|
|
+static bool sm4_generate_vsir_numeric_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
+ struct vkd3d_shader_register *reg, uint32_t *writemask, const struct hlsl_deref *deref)
|
|
+{
|
|
+ const struct hlsl_ir_var *var = deref->var;
|
|
+ unsigned int offset_const_deref;
|
|
+
|
|
+ reg->type = var->indexable ? VKD3DSPR_IDXTEMP : VKD3DSPR_TEMP;
|
|
+ reg->idx[0].offset = var->regs[HLSL_REGSET_NUMERIC].id;
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+
|
|
+ VKD3D_ASSERT(var->regs[HLSL_REGSET_NUMERIC].allocated);
|
|
+
|
|
+ if (!var->indexable)
|
|
+ {
|
|
+ offset_const_deref = hlsl_offset_from_deref_safe(ctx, deref);
|
|
+ reg->idx[0].offset += offset_const_deref / 4;
|
|
+ reg->idx_count = 1;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ offset_const_deref = deref->const_offset;
|
|
+ reg->idx[1].offset = offset_const_deref / 4;
|
|
+ reg->idx_count = 2;
|
|
+
|
|
+ if (deref->rel_offset.node)
|
|
+ {
|
|
+ struct vkd3d_shader_src_param *idx_src;
|
|
+
|
|
+ if (!(idx_src = vsir_program_get_src_params(program, 1)))
|
|
+ {
|
|
+ ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+ return false;
|
|
+ }
|
|
+ memset(idx_src, 0, sizeof(*idx_src));
|
|
+ reg->idx[1].rel_addr = idx_src;
|
|
+
|
|
+ vsir_src_from_hlsl_node(idx_src, ctx, deref->rel_offset.node, VKD3DSP_WRITEMASK_ALL);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *writemask = 0xf & (0xf << (offset_const_deref % 4));
|
|
+ if (var->regs[HLSL_REGSET_NUMERIC].writemask)
|
|
+ *writemask = hlsl_combine_writemasks(var->regs[HLSL_REGSET_NUMERIC].writemask, *writemask);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
+ struct vkd3d_shader_register *reg, uint32_t *writemask, const struct hlsl_deref *deref)
|
|
+{
|
|
+ const struct vkd3d_shader_version *version = &program->shader_version;
|
|
+ const struct hlsl_type *data_type = hlsl_deref_get_type(ctx, deref);
|
|
+ const struct hlsl_ir_var *var = deref->var;
|
|
+
|
|
+ if (var->is_uniform)
|
|
+ {
|
|
+ enum hlsl_regset regset = hlsl_deref_get_regset(ctx, deref);
|
|
+
|
|
+ if (regset == HLSL_REGSET_TEXTURES)
|
|
+ {
|
|
+ reg->type = VKD3DSPR_RESOURCE;
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+ if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
+ {
|
|
+ reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].id;
|
|
+ reg->idx[1].offset = var->regs[HLSL_REGSET_TEXTURES].index; /* FIXME: array index */
|
|
+ reg->idx_count = 2;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].index;
|
|
+ reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref);
|
|
+ reg->idx_count = 1;
|
|
+ }
|
|
+ VKD3D_ASSERT(regset == HLSL_REGSET_TEXTURES);
|
|
+ *writemask = VKD3DSP_WRITEMASK_ALL;
|
|
+ }
|
|
+ else if (regset == HLSL_REGSET_UAVS)
|
|
+ {
|
|
+ reg->type = VKD3DSPR_UAV;
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+ if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
+ {
|
|
+ reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].id;
|
|
+ reg->idx[1].offset = var->regs[HLSL_REGSET_UAVS].index; /* FIXME: array index */
|
|
+ reg->idx_count = 2;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].index;
|
|
+ reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref);
|
|
+ reg->idx_count = 1;
|
|
+ }
|
|
+ VKD3D_ASSERT(regset == HLSL_REGSET_UAVS);
|
|
+ *writemask = VKD3DSP_WRITEMASK_ALL;
|
|
+ }
|
|
+ else if (regset == HLSL_REGSET_SAMPLERS)
|
|
+ {
|
|
+ reg->type = VKD3DSPR_SAMPLER;
|
|
+ reg->dimension = VSIR_DIMENSION_NONE;
|
|
+ if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
+ {
|
|
+ reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].id;
|
|
+ reg->idx[1].offset = var->regs[HLSL_REGSET_SAMPLERS].index; /* FIXME: array index */
|
|
+ reg->idx_count = 2;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].index;
|
|
+ reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref);
|
|
+ reg->idx_count = 1;
|
|
+ }
|
|
+ VKD3D_ASSERT(regset == HLSL_REGSET_SAMPLERS);
|
|
+ *writemask = VKD3DSP_WRITEMASK_ALL;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref) + var->buffer_offset;
|
|
+
|
|
+ VKD3D_ASSERT(data_type->class <= HLSL_CLASS_VECTOR);
|
|
+ reg->type = VKD3DSPR_CONSTBUFFER;
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+ if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
+ {
|
|
+ reg->idx[0].offset = var->buffer->reg.id;
|
|
+ reg->idx[1].offset = var->buffer->reg.index; /* FIXME: array index */
|
|
+ reg->idx[2].offset = offset / 4;
|
|
+ reg->idx_count = 3;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ reg->idx[0].offset = var->buffer->reg.index;
|
|
+ reg->idx[1].offset = offset / 4;
|
|
+ reg->idx_count = 2;
|
|
+ }
|
|
+ *writemask = ((1u << data_type->dimx) - 1) << (offset & 3);
|
|
+ }
|
|
+ }
|
|
+ else if (var->is_input_semantic)
|
|
+ {
|
|
+ bool has_idx;
|
|
+
|
|
+ if (sm4_register_from_semantic_name(version, var->semantic.name, false, ®->type, &has_idx))
|
|
+ {
|
|
+ unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref);
|
|
+
|
|
+ if (has_idx)
|
|
+ {
|
|
+ reg->idx[0].offset = var->semantic.index + offset / 4;
|
|
+ reg->idx_count = 1;
|
|
+ }
|
|
+
|
|
+ if (shader_sm4_is_scalar_register(reg))
|
|
+ reg->dimension = VSIR_DIMENSION_SCALAR;
|
|
+ else
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+ *writemask = ((1u << data_type->dimx) - 1) << (offset % 4);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ struct hlsl_reg hlsl_reg = hlsl_reg_from_deref(ctx, deref);
|
|
+
|
|
+ VKD3D_ASSERT(hlsl_reg.allocated);
|
|
+
|
|
+ if (version->type == VKD3D_SHADER_TYPE_DOMAIN)
|
|
+ reg->type = VKD3DSPR_PATCHCONST;
|
|
+ else
|
|
+ reg->type = VKD3DSPR_INPUT;
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+ reg->idx[0].offset = hlsl_reg.id;
|
|
+ reg->idx_count = 1;
|
|
+ *writemask = hlsl_reg.writemask;
|
|
+ }
|
|
+ }
|
|
+ else if (var->is_output_semantic)
|
|
+ {
|
|
+ bool has_idx;
|
|
+
|
|
+ if (sm4_register_from_semantic_name(version, var->semantic.name, true, ®->type, &has_idx))
|
|
+ {
|
|
+ unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref);
|
|
+
|
|
+ if (has_idx)
|
|
+ {
|
|
+ reg->idx[0].offset = var->semantic.index + offset / 4;
|
|
+ reg->idx_count = 1;
|
|
+ }
|
|
+
|
|
+ if (shader_sm4_is_scalar_register(reg))
|
|
+ reg->dimension = VSIR_DIMENSION_SCALAR;
|
|
+ else
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+ *writemask = ((1u << data_type->dimx) - 1) << (offset % 4);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ struct hlsl_reg hlsl_reg = hlsl_reg_from_deref(ctx, deref);
|
|
+
|
|
+ VKD3D_ASSERT(hlsl_reg.allocated);
|
|
+ reg->type = VKD3DSPR_OUTPUT;
|
|
+ reg->dimension = VSIR_DIMENSION_VEC4;
|
|
+ reg->idx[0].offset = hlsl_reg.id;
|
|
+ reg->idx_count = 1;
|
|
+ *writemask = hlsl_reg.writemask;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ return sm4_generate_vsir_numeric_reg_from_deref(ctx, program, reg, writemask, deref);
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
+ struct vkd3d_shader_src_param *src_param, const struct hlsl_deref *deref,
|
|
+ unsigned int dst_writemask, const struct vkd3d_shader_location *loc)
|
|
+{
|
|
+ uint32_t writemask;
|
|
+
|
|
+ if (!sm4_generate_vsir_reg_from_deref(ctx, program, &src_param->reg, &writemask, deref))
|
|
+ return false;
|
|
+ src_param->swizzle = generate_vsir_get_src_swizzle(writemask, dst_writemask);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
+ struct vkd3d_shader_dst_param *dst_param, const struct hlsl_deref *deref,
|
|
+ const struct vkd3d_shader_location *loc, unsigned int writemask)
|
|
+{
|
|
+ uint32_t reg_writemask;
|
|
+
|
|
+ if (!sm4_generate_vsir_reg_from_deref(ctx, program, &dst_param->reg, ®_writemask, deref))
|
|
+ return false;
|
|
+ dst_param->write_mask = hlsl_combine_writemasks(reg_writemask, writemask);
|
|
+ return true;
|
|
+}
|
|
+
|
|
static void vsir_dst_from_hlsl_node(struct vkd3d_shader_dst_param *dst,
|
|
struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr)
|
|
{
|
|
@@ -7059,13 +7322,10 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx,
|
|
|
|
case HLSL_TYPE_INT:
|
|
case HLSL_TYPE_UINT:
|
|
+ case HLSL_TYPE_BOOL:
|
|
generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true);
|
|
return true;
|
|
|
|
- case HLSL_TYPE_BOOL:
|
|
- hlsl_fixme(ctx, &instr->loc, "SM1 cast from bool to integer.");
|
|
- break;
|
|
-
|
|
case HLSL_TYPE_DOUBLE:
|
|
hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to integer.");
|
|
break;
|
|
@@ -7659,40 +7919,6 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
|
|
sm1_generate_vsir_block(ctx, &entry_func->body, program);
|
|
}
|
|
|
|
-static void add_last_vsir_instr_to_block(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_block *block)
|
|
-{
|
|
- struct vkd3d_shader_location *loc;
|
|
- struct hlsl_ir_node *vsir_instr;
|
|
-
|
|
- loc = &program->instructions.elements[program->instructions.count - 1].location;
|
|
-
|
|
- if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, program->instructions.count - 1, NULL, NULL, loc)))
|
|
- {
|
|
- ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
|
|
- return;
|
|
- }
|
|
- hlsl_block_add_instr(block, vsir_instr);
|
|
-}
|
|
-
|
|
-static void replace_instr_with_last_vsir_instr(struct hlsl_ctx *ctx,
|
|
- struct vsir_program *program, struct hlsl_ir_node *instr)
|
|
-{
|
|
- struct vkd3d_shader_location *loc;
|
|
- struct hlsl_ir_node *vsir_instr;
|
|
-
|
|
- loc = &program->instructions.elements[program->instructions.count - 1].location;
|
|
-
|
|
- if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx,
|
|
- program->instructions.count - 1, instr->data_type, &instr->reg, loc)))
|
|
- {
|
|
- ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
|
|
- return;
|
|
- }
|
|
-
|
|
- list_add_before(&instr->entry, &vsir_instr->entry);
|
|
- hlsl_replace_node(instr, vsir_instr);
|
|
-}
|
|
-
|
|
static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
const struct hlsl_ir_var *var, bool is_patch_constant_func, struct hlsl_block *block,
|
|
const struct vkd3d_shader_location *loc)
|
|
@@ -7806,8 +8032,6 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs
|
|
|
|
if (var->is_input_semantic && version->type == VKD3D_SHADER_TYPE_PIXEL)
|
|
ins->flags = sm4_get_interpolation_mode(var->data_type, var->storage_modifiers);
|
|
-
|
|
- add_last_vsir_instr_to_block(ctx, program, block);
|
|
}
|
|
|
|
static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
@@ -7819,8 +8043,6 @@ static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_
|
|
return;
|
|
|
|
ins->declaration.count = temp_count;
|
|
-
|
|
- add_last_vsir_instr_to_block(ctx, program, block);
|
|
}
|
|
|
|
static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx,
|
|
@@ -7838,8 +8060,6 @@ static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx,
|
|
ins->declaration.indexable_temp.data_type = VKD3D_DATA_FLOAT;
|
|
ins->declaration.indexable_temp.component_count = comp_count;
|
|
ins->declaration.indexable_temp.has_function_scope = false;
|
|
-
|
|
- add_last_vsir_instr_to_block(ctx, program, block);
|
|
}
|
|
|
|
static bool type_is_float(const struct hlsl_type *type)
|
|
@@ -8505,99 +8725,730 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx,
|
|
}
|
|
}
|
|
|
|
-static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program)
|
|
+static bool sm4_generate_vsir_instr_store(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, struct hlsl_ir_store *store)
|
|
{
|
|
- struct vkd3d_string_buffer *dst_type_string;
|
|
- struct hlsl_ir_node *instr, *next;
|
|
- struct hlsl_ir_switch_case *c;
|
|
+ struct hlsl_ir_node *instr = &store->node;
|
|
+ struct vkd3d_shader_dst_param *dst_param;
|
|
+ struct vkd3d_shader_src_param *src_param;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
|
|
- LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry)
|
|
- {
|
|
- if (instr->data_type)
|
|
- {
|
|
- if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR)
|
|
- {
|
|
- hlsl_fixme(ctx, &instr->loc, "Class %#x should have been lowered or removed.", instr->data_type->class);
|
|
- break;
|
|
- }
|
|
- }
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1)))
|
|
+ return false;
|
|
|
|
- switch (instr->type)
|
|
- {
|
|
- case HLSL_IR_CALL:
|
|
- vkd3d_unreachable();
|
|
+ dst_param = &ins->dst[0];
|
|
+ if (!sm4_generate_vsir_init_dst_param_from_deref(ctx, program,
|
|
+ dst_param, &store->lhs, &instr->loc, store->writemask))
|
|
+ return false;
|
|
|
|
- case HLSL_IR_CONSTANT:
|
|
- /* In SM4 all constants are inlined. */
|
|
- break;
|
|
+ src_param = &ins->src[0];
|
|
+ vsir_src_from_hlsl_node(src_param, ctx, store->rhs.node, dst_param->write_mask);
|
|
|
|
- case HLSL_IR_EXPR:
|
|
- if (!(dst_type_string = hlsl_type_to_string(ctx, instr->data_type)))
|
|
- break;
|
|
+ return true;
|
|
+}
|
|
|
|
- if (sm4_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr), dst_type_string->buffer))
|
|
- replace_instr_with_last_vsir_instr(ctx, program, instr);
|
|
+/* Does this variable's data come directly from the API user, rather than
|
|
+ * being temporary or from a previous shader stage? I.e. is it a uniform or
|
|
+ * VS input? */
|
|
+static bool var_is_user_input(const struct vkd3d_shader_version *version, const struct hlsl_ir_var *var)
|
|
+{
|
|
+ if (var->is_uniform)
|
|
+ return true;
|
|
|
|
- hlsl_release_string_buffer(ctx, dst_type_string);
|
|
- break;
|
|
+ return var->is_input_semantic && version->type == VKD3D_SHADER_TYPE_VERTEX;
|
|
+}
|
|
|
|
- case HLSL_IR_IF:
|
|
- sm4_generate_vsir_block(ctx, &hlsl_ir_if(instr)->then_block, program);
|
|
- sm4_generate_vsir_block(ctx, &hlsl_ir_if(instr)->else_block, program);
|
|
- break;
|
|
+static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_load *load)
|
|
+{
|
|
+ const struct vkd3d_shader_version *version = &program->shader_version;
|
|
+ const struct hlsl_type *type = load->node.data_type;
|
|
+ struct vkd3d_shader_dst_param *dst_param;
|
|
+ struct hlsl_ir_node *instr = &load->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ struct hlsl_constant_value value;
|
|
|
|
- case HLSL_IR_LOOP:
|
|
- sm4_generate_vsir_block(ctx, &hlsl_ir_loop(instr)->body, program);
|
|
- break;
|
|
+ VKD3D_ASSERT(hlsl_is_numeric_type(type));
|
|
+ if (type->e.numeric.type == HLSL_TYPE_BOOL && var_is_user_input(version, load->src.var))
|
|
+ {
|
|
+ /* Uniform bools can be specified as anything, but internal bools
|
|
+ * always have 0 for false and ~0 for true. Normalise that here. */
|
|
|
|
- case HLSL_IR_SWITCH:
|
|
- LIST_FOR_EACH_ENTRY(c, &hlsl_ir_switch(instr)->cases, struct hlsl_ir_switch_case, entry)
|
|
- sm4_generate_vsir_block(ctx, &c->body, program);
|
|
- break;
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOVC, 1, 3)))
|
|
+ return false;
|
|
|
|
- case HLSL_IR_SWIZZLE:
|
|
- generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr));
|
|
- replace_instr_with_last_vsir_instr(ctx, program, instr);
|
|
- break;
|
|
+ dst_param = &ins->dst[0];
|
|
+ vsir_dst_from_hlsl_node(dst_param, ctx, instr);
|
|
|
|
- default:
|
|
- break;
|
|
- }
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[0], &load->src, dst_param->write_mask, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ memset(&value, 0xff, sizeof(value));
|
|
+ vsir_src_from_hlsl_constant_value(&ins->src[1], ctx, &value,
|
|
+ VKD3D_DATA_UINT, type->dimx, dst_param->write_mask);
|
|
+ memset(&value, 0x00, sizeof(value));
|
|
+ vsir_src_from_hlsl_constant_value(&ins->src[2], ctx, &value,
|
|
+ VKD3D_DATA_UINT, type->dimx, dst_param->write_mask);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1)))
|
|
+ return false;
|
|
+
|
|
+ dst_param = &ins->dst[0];
|
|
+ vsir_dst_from_hlsl_node(dst_param, ctx, instr);
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[0], &load->src, dst_param->write_mask, &instr->loc))
|
|
+ return false;
|
|
}
|
|
+ return true;
|
|
}
|
|
|
|
-static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx,
|
|
- struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program)
|
|
+static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, struct hlsl_ir_resource_store *store)
|
|
{
|
|
- bool is_patch_constant_func = func == ctx->patch_constant_func;
|
|
- struct hlsl_block block = {0};
|
|
- struct hlsl_scope *scope;
|
|
- struct hlsl_ir_var *var;
|
|
- uint32_t temp_count;
|
|
-
|
|
- compute_liveness(ctx, func);
|
|
- mark_indexable_vars(ctx, func);
|
|
- temp_count = allocate_temp_registers(ctx, func);
|
|
- if (ctx->result)
|
|
- return;
|
|
- program->temp_count = max(program->temp_count, temp_count);
|
|
+ struct hlsl_type *resource_type = hlsl_deref_get_type(ctx, &store->resource);
|
|
+ struct hlsl_ir_node *coords = store->coords.node, *value = store->value.node;
|
|
+ struct hlsl_ir_node *instr = &store->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ unsigned int writemask;
|
|
|
|
- hlsl_block_init(&block);
|
|
+ if (!store->resource.var->is_uniform)
|
|
+ {
|
|
+ hlsl_fixme(ctx, &store->node.loc, "Store to non-uniform resource variable.");
|
|
+ return false;
|
|
+ }
|
|
|
|
- LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry)
|
|
+ if (resource_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER)
|
|
{
|
|
- if ((var->is_input_semantic && var->last_read)
|
|
- || (var->is_output_semantic && var->first_write))
|
|
- sm4_generate_vsir_instr_dcl_semantic(ctx, program, var, is_patch_constant_func, &block, &var->loc);
|
|
+ hlsl_fixme(ctx, &store->node.loc, "Structured buffers store is not implemented.");
|
|
+ return false;
|
|
}
|
|
|
|
- if (temp_count)
|
|
- sm4_generate_vsir_instr_dcl_temps(ctx, program, temp_count, &block, &func->loc);
|
|
+ if (resource_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER)
|
|
+ {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_STORE_RAW, 1, 2)))
|
|
+ return false;
|
|
|
|
- LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
|
|
+ writemask = vkd3d_write_mask_from_component_count(value->data_type->dimx);
|
|
+ if (!sm4_generate_vsir_init_dst_param_from_deref(ctx, program,
|
|
+ &ins->dst[0], &store->resource, &instr->loc, writemask))
|
|
+ return false;
|
|
+ }
|
|
+ else
|
|
{
|
|
- LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
- {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_STORE_UAV_TYPED, 1, 2)))
|
|
+ return false;
|
|
+
|
|
+ if (!sm4_generate_vsir_init_dst_param_from_deref(ctx, program,
|
|
+ &ins->dst[0], &store->resource, &instr->loc, VKD3DSP_WRITEMASK_ALL))
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL);
|
|
+ vsir_src_from_hlsl_node(&ins->src[1], ctx, value, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_validate_texel_offset_aoffimmi(const struct hlsl_ir_node *texel_offset)
|
|
+{
|
|
+ struct hlsl_ir_constant *offset;
|
|
+
|
|
+ VKD3D_ASSERT(texel_offset);
|
|
+ if (texel_offset->type != HLSL_IR_CONSTANT)
|
|
+ return false;
|
|
+ offset = hlsl_ir_constant(texel_offset);
|
|
+
|
|
+ if (offset->value.u[0].i < -8 || offset->value.u[0].i > 7)
|
|
+ return false;
|
|
+ if (offset->node.data_type->dimx > 1 && (offset->value.u[1].i < -8 || offset->value.u[1].i > 7))
|
|
+ return false;
|
|
+ if (offset->node.data_type->dimx > 2 && (offset->value.u[2].i < -8 || offset->value.u[2].i > 7))
|
|
+ return false;
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static void sm4_generate_vsir_encode_texel_offset_as_aoffimmi(
|
|
+ struct vkd3d_shader_instruction *ins, const struct hlsl_ir_node *texel_offset)
|
|
+{
|
|
+ struct hlsl_ir_constant *offset;
|
|
+
|
|
+ if (!texel_offset)
|
|
+ return;
|
|
+ offset = hlsl_ir_constant(texel_offset);
|
|
+
|
|
+ ins->texel_offset.u = offset->value.u[0].i;
|
|
+ ins->texel_offset.v = 0;
|
|
+ ins->texel_offset.w = 0;
|
|
+ if (offset->node.data_type->dimx > 1)
|
|
+ ins->texel_offset.v = offset->value.u[1].i;
|
|
+ if (offset->node.data_type->dimx > 2)
|
|
+ ins->texel_offset.w = offset->value.u[2].i;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, const struct hlsl_ir_resource_load *load)
|
|
+{
|
|
+ const struct hlsl_type *resource_type = hlsl_deref_get_type(ctx, &load->resource);
|
|
+ bool uav = (hlsl_deref_get_regset(ctx, &load->resource) == HLSL_REGSET_UAVS);
|
|
+ const struct vkd3d_shader_version *version = &program->shader_version;
|
|
+ bool raw = resource_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER;
|
|
+ const struct hlsl_ir_node *sample_index = load->sample_index.node;
|
|
+ const struct hlsl_ir_node *texel_offset = load->texel_offset.node;
|
|
+ const struct hlsl_ir_node *coords = load->coords.node;
|
|
+ unsigned int coords_writemask = VKD3DSP_WRITEMASK_ALL;
|
|
+ const struct hlsl_deref *resource = &load->resource;
|
|
+ const struct hlsl_ir_node *instr = &load->node;
|
|
+ enum hlsl_sampler_dim dim = load->sampling_dim;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ enum vkd3d_shader_opcode opcode;
|
|
+ bool multisampled;
|
|
+
|
|
+ VKD3D_ASSERT(load->load_type == HLSL_RESOURCE_LOAD);
|
|
+
|
|
+ multisampled = resource_type->class == HLSL_CLASS_TEXTURE
|
|
+ && (resource_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS
|
|
+ || resource_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY);
|
|
+
|
|
+ if (uav)
|
|
+ opcode = VKD3DSIH_LD_UAV_TYPED;
|
|
+ else if (raw)
|
|
+ opcode = VKD3DSIH_LD_RAW;
|
|
+ else
|
|
+ opcode = multisampled ? VKD3DSIH_LD2DMS : VKD3DSIH_LD;
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 2 + multisampled)))
|
|
+ return false;
|
|
+
|
|
+ if (texel_offset && !sm4_generate_vsir_validate_texel_offset_aoffimmi(texel_offset))
|
|
+ {
|
|
+ hlsl_error(ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
|
|
+ "Offset must resolve to integer literal in the range -8 to 7.");
|
|
+ return false;
|
|
+ }
|
|
+ sm4_generate_vsir_encode_texel_offset_as_aoffimmi(ins, texel_offset);
|
|
+
|
|
+ vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
|
+
|
|
+ if (!uav)
|
|
+ {
|
|
+ /* Mipmap level is in the last component in the IR, but needs to be in
|
|
+ * the W component in the instruction. */
|
|
+ unsigned int dim_count = hlsl_sampler_dim_count(dim);
|
|
+
|
|
+ if (dim_count == 1)
|
|
+ coords_writemask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_3;
|
|
+ if (dim_count == 2)
|
|
+ coords_writemask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_3;
|
|
+ }
|
|
+
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, coords_writemask);
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[1], resource, ins->dst[0].write_mask, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ if (multisampled)
|
|
+ {
|
|
+ if (sample_index->type == HLSL_IR_CONSTANT)
|
|
+ vsir_src_from_hlsl_constant_value(&ins->src[2], ctx,
|
|
+ &hlsl_ir_constant(sample_index)->value, VKD3D_DATA_INT, 1, 0);
|
|
+ else if (version->major == 4 && version->minor == 0)
|
|
+ hlsl_error(ctx, &sample_index->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Expected literal sample index.");
|
|
+ else
|
|
+ vsir_src_from_hlsl_node(&ins->src[2], ctx, sample_index, VKD3DSP_WRITEMASK_ALL);
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, const struct hlsl_ir_resource_load *load)
|
|
+{
|
|
+ const struct hlsl_ir_node *texel_offset = load->texel_offset.node;
|
|
+ const struct hlsl_ir_node *coords = load->coords.node;
|
|
+ const struct hlsl_deref *resource = &load->resource;
|
|
+ const struct hlsl_deref *sampler = &load->sampler;
|
|
+ const struct hlsl_ir_node *instr = &load->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ enum vkd3d_shader_opcode opcode;
|
|
+ unsigned int src_count;
|
|
+
|
|
+ switch (load->load_type)
|
|
+ {
|
|
+ case HLSL_RESOURCE_SAMPLE:
|
|
+ opcode = VKD3DSIH_SAMPLE;
|
|
+ src_count = 3;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_CMP:
|
|
+ opcode = VKD3DSIH_SAMPLE_C;
|
|
+ src_count = 4;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_CMP_LZ:
|
|
+ opcode = VKD3DSIH_SAMPLE_C_LZ;
|
|
+ src_count = 4;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_LOD:
|
|
+ opcode = VKD3DSIH_SAMPLE_LOD;
|
|
+ src_count = 4;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_LOD_BIAS:
|
|
+ opcode = VKD3DSIH_SAMPLE_B;
|
|
+ src_count = 4;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_GRAD:
|
|
+ opcode = VKD3DSIH_SAMPLE_GRAD;
|
|
+ src_count = 5;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ vkd3d_unreachable();
|
|
+ }
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, src_count)))
|
|
+ return false;
|
|
+
|
|
+ if (texel_offset && !sm4_generate_vsir_validate_texel_offset_aoffimmi(texel_offset))
|
|
+ {
|
|
+ hlsl_error(ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
|
|
+ "Offset must resolve to integer literal in the range -8 to 7.");
|
|
+ return false;
|
|
+ }
|
|
+ sm4_generate_vsir_encode_texel_offset_as_aoffimmi(ins, texel_offset);
|
|
+
|
|
+ vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
|
+
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[1],
|
|
+ resource, ins->dst[0].write_mask, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[2],
|
|
+ sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ if (opcode == VKD3DSIH_SAMPLE_LOD || opcode == VKD3DSIH_SAMPLE_B)
|
|
+ {
|
|
+ vsir_src_from_hlsl_node(&ins->src[3], ctx, load->lod.node, VKD3DSP_WRITEMASK_ALL);
|
|
+ }
|
|
+ else if (opcode == VKD3DSIH_SAMPLE_C || opcode == VKD3DSIH_SAMPLE_C_LZ)
|
|
+ {
|
|
+ vsir_src_from_hlsl_node(&ins->src[3], ctx, load->cmp.node, VKD3DSP_WRITEMASK_ALL);
|
|
+ }
|
|
+ else if (opcode == VKD3DSIH_SAMPLE_GRAD)
|
|
+ {
|
|
+ vsir_src_from_hlsl_node(&ins->src[3], ctx, load->ddx.node, VKD3DSP_WRITEMASK_ALL);
|
|
+ vsir_src_from_hlsl_node(&ins->src[4], ctx, load->ddy.node, VKD3DSP_WRITEMASK_ALL);
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
+ const struct hlsl_ir_resource_load *load, uint32_t swizzle)
|
|
+{
|
|
+ const struct vkd3d_shader_version *version = &program->shader_version;
|
|
+ const struct hlsl_ir_node *texel_offset = load->texel_offset.node;
|
|
+ const struct hlsl_ir_node *coords = load->coords.node;
|
|
+ const struct hlsl_deref *resource = &load->resource;
|
|
+ const struct hlsl_deref *sampler = &load->sampler;
|
|
+ const struct hlsl_ir_node *instr = &load->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ enum vkd3d_shader_opcode opcode;
|
|
+
|
|
+ opcode = VKD3DSIH_GATHER4;
|
|
+ if (texel_offset && !sm4_generate_vsir_validate_texel_offset_aoffimmi(texel_offset))
|
|
+ {
|
|
+ if (!vkd3d_shader_ver_ge(version, 5, 0))
|
|
+ {
|
|
+ hlsl_error(ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
|
|
+ "Offset must resolve to integer literal in the range -8 to 7 for profiles < 5.");
|
|
+ return false;
|
|
+ }
|
|
+ opcode = VKD3DSIH_GATHER4_PO;
|
|
+ }
|
|
+
|
|
+ if (opcode == VKD3DSIH_GATHER4)
|
|
+ {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 3)))
|
|
+ return false;
|
|
+
|
|
+ vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL);
|
|
+ sm4_generate_vsir_encode_texel_offset_as_aoffimmi(ins, texel_offset);
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[1], resource, ins->dst[0].write_mask, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[2], sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc))
|
|
+ return false;
|
|
+ ins->src[2].reg.dimension = VSIR_DIMENSION_VEC4;
|
|
+ ins->src[2].swizzle = swizzle;
|
|
+ }
|
|
+ else if (opcode == VKD3DSIH_GATHER4_PO)
|
|
+ {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 4)))
|
|
+ return false;
|
|
+
|
|
+ vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL);
|
|
+ vsir_src_from_hlsl_node(&ins->src[1], ctx, texel_offset, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[2], resource, ins->dst[0].write_mask, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[3], sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc))
|
|
+ return false;
|
|
+ ins->src[3].reg.dimension = VSIR_DIMENSION_VEC4;
|
|
+ ins->src[3].swizzle = swizzle;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ vkd3d_unreachable();
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_instr_sample_info(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, const struct hlsl_ir_resource_load *load)
|
|
+{
|
|
+ const struct hlsl_deref *resource = &load->resource;
|
|
+ const struct hlsl_ir_node *instr = &load->node;
|
|
+ struct hlsl_type *type = instr->data_type;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+
|
|
+ VKD3D_ASSERT(type->e.numeric.type == HLSL_TYPE_UINT || type->e.numeric.type == HLSL_TYPE_FLOAT);
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_SAMPLE_INFO, 1, 1)))
|
|
+ return false;
|
|
+
|
|
+ if (type->e.numeric.type == HLSL_TYPE_UINT)
|
|
+ ins->flags = VKD3DSI_SAMPLE_INFO_UINT;
|
|
+
|
|
+ vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[0], resource, ins->dst[0].write_mask, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_instr_resinfo(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, const struct hlsl_ir_resource_load *load)
|
|
+{
|
|
+ const struct hlsl_deref *resource = &load->resource;
|
|
+ const struct hlsl_ir_node *instr = &load->node;
|
|
+ struct hlsl_type *type = instr->data_type;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+
|
|
+ if (resource->data_type->sampler_dim == HLSL_SAMPLER_DIM_BUFFER
|
|
+ || resource->data_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER)
|
|
+ {
|
|
+ hlsl_fixme(ctx, &load->node.loc, "resinfo for buffers.");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ VKD3D_ASSERT(type->e.numeric.type == HLSL_TYPE_UINT || type->e.numeric.type == HLSL_TYPE_FLOAT);
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_RESINFO, 1, 2)))
|
|
+ return false;
|
|
+
|
|
+ if (type->e.numeric.type == HLSL_TYPE_UINT)
|
|
+ ins->flags = VKD3DSI_RESINFO_UINT;
|
|
+
|
|
+ vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
|
|
+
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, load->lod.node, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program,
|
|
+ &ins->src[1], resource, ins->dst[0].write_mask, &instr->loc))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, const struct hlsl_ir_resource_load *load)
|
|
+{
|
|
+ if (load->sampler.var && !load->sampler.var->is_uniform)
|
|
+ {
|
|
+ hlsl_fixme(ctx, &load->node.loc, "Sample using non-uniform sampler variable.");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!load->resource.var->is_uniform)
|
|
+ {
|
|
+ hlsl_fixme(ctx, &load->node.loc, "Load from non-uniform resource variable.");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ switch (load->load_type)
|
|
+ {
|
|
+ case HLSL_RESOURCE_LOAD:
|
|
+ return sm4_generate_vsir_instr_ld(ctx, program, load);
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE:
|
|
+ case HLSL_RESOURCE_SAMPLE_CMP:
|
|
+ case HLSL_RESOURCE_SAMPLE_CMP_LZ:
|
|
+ case HLSL_RESOURCE_SAMPLE_LOD:
|
|
+ case HLSL_RESOURCE_SAMPLE_LOD_BIAS:
|
|
+ case HLSL_RESOURCE_SAMPLE_GRAD:
|
|
+ /* Combined sample expressions were lowered. */
|
|
+ VKD3D_ASSERT(load->sampler.var);
|
|
+ return sm4_generate_vsir_instr_sample(ctx, program, load);
|
|
+
|
|
+ case HLSL_RESOURCE_GATHER_RED:
|
|
+ return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(X, X, X, X));
|
|
+
|
|
+ case HLSL_RESOURCE_GATHER_GREEN:
|
|
+ return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y));
|
|
+
|
|
+ case HLSL_RESOURCE_GATHER_BLUE:
|
|
+ return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z));
|
|
+
|
|
+ case HLSL_RESOURCE_GATHER_ALPHA:
|
|
+ return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(W, W, W, W));
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_INFO:
|
|
+ return sm4_generate_vsir_instr_sample_info(ctx, program, load);
|
|
+
|
|
+ case HLSL_RESOURCE_RESINFO:
|
|
+ return sm4_generate_vsir_instr_resinfo(ctx, program, load);
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_PROJ:
|
|
+ vkd3d_unreachable();
|
|
+
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool sm4_generate_vsir_instr_jump(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, const struct hlsl_ir_jump *jump)
|
|
+{
|
|
+ const struct hlsl_ir_node *instr = &jump->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+
|
|
+ switch (jump->type)
|
|
+ {
|
|
+ case HLSL_IR_JUMP_BREAK:
|
|
+ return generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_BREAK, 0, 0);
|
|
+
|
|
+ case HLSL_IR_JUMP_CONTINUE:
|
|
+ return generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_CONTINUE, 0, 0);
|
|
+
|
|
+ case HLSL_IR_JUMP_DISCARD_NZ:
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_DISCARD, 0, 1)))
|
|
+ return false;
|
|
+ ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ;
|
|
+
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, jump->condition.node, VKD3DSP_WRITEMASK_ALL);
|
|
+ return true;
|
|
+
|
|
+ case HLSL_IR_JUMP_RETURN:
|
|
+ vkd3d_unreachable();
|
|
+
|
|
+ default:
|
|
+ hlsl_fixme(ctx, &jump->node.loc, "Jump type %s.", hlsl_jump_type_to_string(jump->type));
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program);
|
|
+
|
|
+static void sm4_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_if *iff)
|
|
+{
|
|
+ struct hlsl_ir_node *instr = &iff->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+
|
|
+ VKD3D_ASSERT(iff->condition.node->data_type->dimx == 1);
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_IF, 0, 1)))
|
|
+ return;
|
|
+ ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ;
|
|
+
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, iff->condition.node, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ sm4_generate_vsir_block(ctx, &iff->then_block, program);
|
|
+
|
|
+ if (!list_empty(&iff->else_block.instrs))
|
|
+ {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_ELSE, 0, 0)))
|
|
+ return;
|
|
+ sm4_generate_vsir_block(ctx, &iff->else_block, program);
|
|
+ }
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_ENDIF, 0, 0)))
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void sm4_generate_vsir_instr_loop(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, struct hlsl_ir_loop *loop)
|
|
+{
|
|
+ struct hlsl_ir_node *instr = &loop->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_LOOP, 0, 0)))
|
|
+ return;
|
|
+
|
|
+ sm4_generate_vsir_block(ctx, &loop->body, program);
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_ENDLOOP, 0, 0)))
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, struct hlsl_ir_switch *swi)
|
|
+{
|
|
+ const struct hlsl_ir_node *selector = swi->selector.node;
|
|
+ struct hlsl_ir_node *instr = &swi->node;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ struct hlsl_ir_switch_case *cas;
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_SWITCH, 0, 1)))
|
|
+ return;
|
|
+ vsir_src_from_hlsl_node(&ins->src[0], ctx, selector, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ LIST_FOR_EACH_ENTRY(cas, &swi->cases, struct hlsl_ir_switch_case, entry)
|
|
+ {
|
|
+ if (cas->is_default)
|
|
+ {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_DEFAULT, 0, 0)))
|
|
+ return;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ struct hlsl_constant_value value = {.u[0].u = cas->value};
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_CASE, 0, 1)))
|
|
+ return;
|
|
+ vsir_src_from_hlsl_constant_value(&ins->src[0], ctx, &value, VKD3D_DATA_UINT, 1, VKD3DSP_WRITEMASK_ALL);
|
|
+ }
|
|
+
|
|
+ sm4_generate_vsir_block(ctx, &cas->body, program);
|
|
+ }
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_ENDSWITCH, 0, 0)))
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program)
|
|
+{
|
|
+ struct vkd3d_string_buffer *dst_type_string;
|
|
+ struct hlsl_ir_node *instr, *next;
|
|
+
|
|
+ LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry)
|
|
+ {
|
|
+ if (instr->data_type)
|
|
+ {
|
|
+ if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR)
|
|
+ {
|
|
+ hlsl_fixme(ctx, &instr->loc, "Class %#x should have been lowered or removed.", instr->data_type->class);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ switch (instr->type)
|
|
+ {
|
|
+ case HLSL_IR_CALL:
|
|
+ vkd3d_unreachable();
|
|
+
|
|
+ case HLSL_IR_CONSTANT:
|
|
+ /* In SM4 all constants are inlined. */
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_EXPR:
|
|
+ if (!(dst_type_string = hlsl_type_to_string(ctx, instr->data_type)))
|
|
+ break;
|
|
+ sm4_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr), dst_type_string->buffer);
|
|
+ hlsl_release_string_buffer(ctx, dst_type_string);
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_IF:
|
|
+ sm4_generate_vsir_instr_if(ctx, program, hlsl_ir_if(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_LOAD:
|
|
+ sm4_generate_vsir_instr_load(ctx, program, hlsl_ir_load(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_LOOP:
|
|
+ sm4_generate_vsir_instr_loop(ctx, program, hlsl_ir_loop(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_RESOURCE_LOAD:
|
|
+ sm4_generate_vsir_instr_resource_load(ctx, program, hlsl_ir_resource_load(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_RESOURCE_STORE:
|
|
+ sm4_generate_vsir_instr_resource_store(ctx, program, hlsl_ir_resource_store(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_JUMP:
|
|
+ sm4_generate_vsir_instr_jump(ctx, program, hlsl_ir_jump(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_STORE:
|
|
+ sm4_generate_vsir_instr_store(ctx, program, hlsl_ir_store(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_SWITCH:
|
|
+ sm4_generate_vsir_instr_switch(ctx, program, hlsl_ir_switch(instr));
|
|
+ break;
|
|
+
|
|
+ case HLSL_IR_SWIZZLE:
|
|
+ generate_vsir_instr_swizzle(ctx, program, hlsl_ir_swizzle(instr));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx,
|
|
+ struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program)
|
|
+{
|
|
+ bool is_patch_constant_func = func == ctx->patch_constant_func;
|
|
+ struct hlsl_block block = {0};
|
|
+ struct hlsl_scope *scope;
|
|
+ struct hlsl_ir_var *var;
|
|
+ uint32_t temp_count;
|
|
+
|
|
+ compute_liveness(ctx, func);
|
|
+ mark_indexable_vars(ctx, func);
|
|
+ temp_count = allocate_temp_registers(ctx, func);
|
|
+ if (ctx->result)
|
|
+ return;
|
|
+ program->temp_count = max(program->temp_count, temp_count);
|
|
+
|
|
+ hlsl_block_init(&block);
|
|
+
|
|
+ LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry)
|
|
+ {
|
|
+ if ((var->is_input_semantic && var->last_read)
|
|
+ || (var->is_output_semantic && var->first_write))
|
|
+ sm4_generate_vsir_instr_dcl_semantic(ctx, program, var, is_patch_constant_func, &block, &var->loc);
|
|
+ }
|
|
+
|
|
+ if (temp_count)
|
|
+ sm4_generate_vsir_instr_dcl_temps(ctx, program, temp_count, &block, &func->loc);
|
|
+
|
|
+ LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
|
|
+ {
|
|
+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
+ {
|
|
if (var->is_uniform || var->is_input_semantic || var->is_output_semantic)
|
|
continue;
|
|
if (!var->regs[HLSL_REGSET_NUMERIC].allocated)
|
|
@@ -8618,6 +9469,8 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx,
|
|
hlsl_block_cleanup(&block);
|
|
|
|
sm4_generate_vsir_block(ctx, &func->body, program);
|
|
+
|
|
+ generate_vsir_add_program_instruction(ctx, program, &func->loc, VKD3DSIH_RET, 0, 0);
|
|
}
|
|
|
|
/* OBJECTIVE: Translate all the information from ctx and entry_func to the
|
|
@@ -8649,9 +9502,16 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
|
|
program->thread_group_size.z = ctx->thread_count[2];
|
|
}
|
|
|
|
+ if (version.type == VKD3D_SHADER_TYPE_HULL)
|
|
+ generate_vsir_add_program_instruction(ctx, program,
|
|
+ &ctx->patch_constant_func->loc, VKD3DSIH_HS_CONTROL_POINT_PHASE, 0, 0);
|
|
sm4_generate_vsir_add_function(ctx, func, config_flags, program);
|
|
if (version.type == VKD3D_SHADER_TYPE_HULL)
|
|
+ {
|
|
+ generate_vsir_add_program_instruction(ctx, program,
|
|
+ &ctx->patch_constant_func->loc, VKD3DSIH_HS_FORK_PHASE, 0, 0);
|
|
sm4_generate_vsir_add_function(ctx, ctx->patch_constant_func, config_flags, program);
|
|
+ }
|
|
}
|
|
|
|
static struct hlsl_ir_jump *loop_unrolling_find_jump(struct hlsl_block *block, struct hlsl_ir_node *stop_point,
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
index b0e89bededb..0c06db9ff15 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
@@ -201,6 +201,14 @@ static void src_param_init_const_uint(struct vkd3d_shader_src_param *src, uint32
|
|
src->reg.u.immconst_u32[0] = value;
|
|
}
|
|
|
|
+static void vsir_src_param_init_io(struct vkd3d_shader_src_param *src,
|
|
+ enum vkd3d_shader_register_type reg_type, const struct signature_element *e, unsigned int idx_count)
|
|
+{
|
|
+ vsir_src_param_init(src, reg_type, vkd3d_data_type_from_component_type(e->component_type), idx_count);
|
|
+ src->reg.dimension = VSIR_DIMENSION_VEC4;
|
|
+ src->swizzle = vsir_swizzle_from_writemask(e->mask);
|
|
+}
|
|
+
|
|
void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id)
|
|
{
|
|
vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UNUSED, 1);
|
|
@@ -278,6 +286,14 @@ void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader
|
|
param->shift = 0;
|
|
}
|
|
|
|
+static void vsir_dst_param_init_io(struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_register_type reg_type,
|
|
+ const struct signature_element *e, unsigned int idx_count)
|
|
+{
|
|
+ vsir_dst_param_init(dst, reg_type, vkd3d_data_type_from_component_type(e->component_type), idx_count);
|
|
+ dst->reg.dimension = VSIR_DIMENSION_VEC4;
|
|
+ dst->write_mask = e->mask;
|
|
+}
|
|
+
|
|
static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx)
|
|
{
|
|
vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1);
|
|
@@ -743,6 +759,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr
|
|
case VKD3DSIH_DCL_GLOBAL_FLAGS:
|
|
case VKD3DSIH_DCL_SAMPLER:
|
|
case VKD3DSIH_DCL_TEMPS:
|
|
+ case VKD3DSIH_DCL_TESSELLATOR_DOMAIN:
|
|
case VKD3DSIH_DCL_THREAD_GROUP:
|
|
case VKD3DSIH_DCL_UAV_TYPED:
|
|
vkd3d_shader_instruction_make_nop(ins);
|
|
@@ -1369,26 +1386,17 @@ static void shader_dst_param_normalise_outpointid(struct vkd3d_shader_dst_param
|
|
}
|
|
}
|
|
|
|
-static void shader_dst_param_io_init(struct vkd3d_shader_dst_param *param, const struct signature_element *e,
|
|
- enum vkd3d_shader_register_type reg_type, unsigned int idx_count)
|
|
-{
|
|
- param->write_mask = e->mask;
|
|
- param->modifiers = 0;
|
|
- param->shift = 0;
|
|
- vsir_register_init(¶m->reg, reg_type, vkd3d_data_type_from_component_type(e->component_type), idx_count);
|
|
-}
|
|
-
|
|
static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_point_normaliser *normaliser,
|
|
const struct shader_signature *s, unsigned int input_control_point_count, unsigned int dst,
|
|
const struct vkd3d_shader_location *location)
|
|
{
|
|
struct vkd3d_shader_instruction *ins;
|
|
- struct vkd3d_shader_dst_param *param;
|
|
const struct signature_element *e;
|
|
- unsigned int i, count;
|
|
+ unsigned int i, count, stride = 0;
|
|
|
|
- for (i = 0, count = 1; i < s->element_count; ++i)
|
|
- count += !!s->elements[i].used_mask;
|
|
+ for (i = 0; i < s->element_count; ++i)
|
|
+ stride += !!s->elements[i].used_mask;
|
|
+ count = 2 + 3 * stride;
|
|
|
|
if (!shader_instruction_array_reserve(&normaliser->instructions, normaliser->instructions.count + count))
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
@@ -1399,31 +1407,75 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p
|
|
|
|
ins = &normaliser->instructions.elements[dst];
|
|
vsir_instruction_init(ins, location, VKD3DSIH_HS_CONTROL_POINT_PHASE);
|
|
- ins->flags = 1;
|
|
- ++ins;
|
|
+
|
|
+ ins = &normaliser->instructions.elements[dst + 1 + 3 * stride];
|
|
+ vsir_instruction_init(ins, location, VKD3DSIH_RET);
|
|
+
|
|
+ ins = &normaliser->instructions.elements[dst + 1];
|
|
|
|
for (i = 0; i < s->element_count; ++i)
|
|
{
|
|
+ struct vkd3d_shader_instruction *ins_in, *ins_out, *ins_mov;
|
|
+ struct vkd3d_shader_dst_param *param_in, *param_out;
|
|
+
|
|
e = &s->elements[i];
|
|
if (!e->used_mask)
|
|
continue;
|
|
|
|
+ ins_in = ins;
|
|
+ ins_out = &ins[stride];
|
|
+ ins_mov = &ins[2 * stride];
|
|
+
|
|
if (e->sysval_semantic != VKD3D_SHADER_SV_NONE)
|
|
{
|
|
- vsir_instruction_init(ins, location, VKD3DSIH_DCL_INPUT_SIV);
|
|
- param = &ins->declaration.register_semantic.reg;
|
|
- ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic);
|
|
+ vsir_instruction_init(ins_in, location, VKD3DSIH_DCL_INPUT_SIV);
|
|
+ param_in = &ins_in->declaration.register_semantic.reg;
|
|
+ ins_in->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic);
|
|
+
|
|
+ vsir_instruction_init(ins_out, location, VKD3DSIH_DCL_OUTPUT_SIV);
|
|
+ param_out = &ins_out->declaration.register_semantic.reg;
|
|
+ ins_out->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic);
|
|
}
|
|
else
|
|
{
|
|
- vsir_instruction_init(ins, location, VKD3DSIH_DCL_INPUT);
|
|
- param = &ins->declaration.dst;
|
|
+ vsir_instruction_init(ins_in, location, VKD3DSIH_DCL_INPUT);
|
|
+ param_in = &ins_in->declaration.dst;
|
|
+
|
|
+ vsir_instruction_init(ins_out, location, VKD3DSIH_DCL_OUTPUT);
|
|
+ param_out = &ins_out->declaration.dst;
|
|
}
|
|
|
|
- shader_dst_param_io_init(param, e, VKD3DSPR_INPUT, 2);
|
|
- param->reg.idx[0].offset = input_control_point_count;
|
|
- param->reg.idx[1].offset = e->register_index;
|
|
- param->write_mask = e->mask;
|
|
+ vsir_dst_param_init_io(param_in, VKD3DSPR_INPUT, e, 2);
|
|
+ param_in->reg.idx[0].offset = input_control_point_count;
|
|
+ param_in->reg.idx[1].offset = e->register_index;
|
|
+ param_in->write_mask = e->mask;
|
|
+
|
|
+ vsir_dst_param_init_io(param_out, VKD3DSPR_OUTPUT, e, 2);
|
|
+ param_out->reg.idx[0].offset = input_control_point_count;
|
|
+ param_out->reg.idx[1].offset = e->register_index;
|
|
+ param_out->write_mask = e->mask;
|
|
+
|
|
+ vsir_instruction_init(ins_mov, location, VKD3DSIH_MOV);
|
|
+ ins_mov->dst = shader_dst_param_allocator_get(&normaliser->instructions.dst_params, 1);
|
|
+ ins_mov->dst_count = 1;
|
|
+ ins_mov->src = shader_src_param_allocator_get(&normaliser->instructions.src_params, 1);
|
|
+ ins_mov->src_count = 1;
|
|
+
|
|
+ if (!ins_mov->dst || ! ins_mov->src)
|
|
+ {
|
|
+ WARN("Failed to allocate dst/src param.\n");
|
|
+ return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+ }
|
|
+
|
|
+ vsir_dst_param_init_io(&ins_mov->dst[0], VKD3DSPR_OUTPUT, e, 2);
|
|
+ ins_mov->dst[0].reg.idx[0].offset = 0;
|
|
+ ins_mov->dst[0].reg.idx[0].rel_addr = normaliser->outpointid_param;
|
|
+ ins_mov->dst[0].reg.idx[1].offset = e->register_index;
|
|
+
|
|
+ vsir_src_param_init_io(&ins_mov->src[0], VKD3DSPR_INPUT, e, 2);
|
|
+ ins_mov->src[0].reg.idx[0].offset = 0;
|
|
+ ins_mov->src[0].reg.idx[0].rel_addr = normaliser->outpointid_param;
|
|
+ ins_mov->src[0].reg.idx[1].offset = e->register_index;
|
|
|
|
++ins;
|
|
}
|
|
@@ -2129,6 +2181,8 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par
|
|
|
|
case VKD3DSPR_OUTCONTROLPOINT:
|
|
reg->type = VKD3DSPR_OUTPUT;
|
|
+ if (io_normaliser_is_in_fork_or_join_phase(normaliser))
|
|
+ normaliser->use_vocp = true;
|
|
/* fall through */
|
|
case VKD3DSPR_OUTPUT:
|
|
reg_idx = reg->idx[reg->idx_count - 1].offset;
|
|
@@ -2179,9 +2233,6 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi
|
|
{
|
|
reg = &ins->declaration.dst.reg;
|
|
|
|
- if (reg->type == VKD3DSPR_OUTCONTROLPOINT)
|
|
- normaliser->use_vocp = true;
|
|
-
|
|
/* We don't need to keep OUTCONTROLPOINT or PATCHCONST input declarations since their
|
|
* equivalents were declared earlier, but INCONTROLPOINT may be the first occurrence. */
|
|
if (reg->type == VKD3DSPR_OUTCONTROLPOINT || reg->type == VKD3DSPR_PATCHCONST)
|
|
@@ -6665,6 +6716,9 @@ struct validation_context
|
|
enum vkd3d_shader_opcode *blocks;
|
|
size_t depth;
|
|
size_t blocks_capacity;
|
|
+
|
|
+ unsigned int outer_tess_idxs[4];
|
|
+ unsigned int inner_tess_idxs[2];
|
|
};
|
|
|
|
static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx,
|
|
@@ -7185,6 +7239,10 @@ static void vsir_validate_register(struct validation_context *ctx,
|
|
vsir_validate_register_without_indices(ctx, reg);
|
|
break;
|
|
|
|
+ case VKD3DSPR_PRIMID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
case VKD3DSPR_NULL:
|
|
vsir_validate_register_without_indices(ctx, reg);
|
|
break;
|
|
@@ -7201,6 +7259,18 @@ static void vsir_validate_register(struct validation_context *ctx,
|
|
vsir_validate_uav_register(ctx, reg);
|
|
break;
|
|
|
|
+ case VKD3DSPR_OUTPOINTID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_FORKINSTID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_JOININSTID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
case VKD3DSPR_INCONTROLPOINT:
|
|
vsir_validate_io_register(ctx, reg);
|
|
break;
|
|
@@ -7213,6 +7283,38 @@ static void vsir_validate_register(struct validation_context *ctx,
|
|
vsir_validate_io_register(ctx, reg);
|
|
break;
|
|
|
|
+ case VKD3DSPR_TESSCOORD:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_THREADID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_THREADGROUPID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_LOCALTHREADID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_LOCALTHREADINDEX:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_COVERAGE:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_SAMPLEMASK:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_GSINSTID:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
case VKD3DSPR_DEPTHOUTGE:
|
|
vsir_validate_register_without_indices(ctx, reg);
|
|
break;
|
|
@@ -7221,10 +7323,22 @@ static void vsir_validate_register(struct validation_context *ctx,
|
|
vsir_validate_register_without_indices(ctx, reg);
|
|
break;
|
|
|
|
+ case VKD3DSPR_OUTSTENCILREF:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
case VKD3DSPR_SSA:
|
|
vsir_validate_ssa_register(ctx, reg);
|
|
break;
|
|
|
|
+ case VKD3DSPR_WAVELANECOUNT:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_WAVELANEINDEX:
|
|
+ vsir_validate_register_without_indices(ctx, reg);
|
|
+ break;
|
|
+
|
|
default:
|
|
break;
|
|
}
|
|
@@ -7469,9 +7583,11 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
|
|
const struct shader_signature *signature, enum vsir_signature_type signature_type,
|
|
unsigned int idx)
|
|
{
|
|
+ enum vkd3d_tessellator_domain expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_INVALID;
|
|
const char *signature_type_name = signature_type_names[signature_type];
|
|
const struct signature_element *element = &signature->elements[idx];
|
|
- bool integer_type = false;
|
|
+ bool integer_type = false, is_outer = false;
|
|
+ unsigned int semantic_index_max = 0;
|
|
|
|
if (element->register_count == 0)
|
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
@@ -7523,12 +7639,6 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
|
|
case VKD3D_SHADER_SV_INSTANCE_ID:
|
|
case VKD3D_SHADER_SV_IS_FRONT_FACE:
|
|
case VKD3D_SHADER_SV_SAMPLE_INDEX:
|
|
- case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE:
|
|
- case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT:
|
|
- case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE:
|
|
- case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT:
|
|
- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET:
|
|
- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN:
|
|
case VKD3D_SHADER_SV_TARGET:
|
|
case VKD3D_SHADER_SV_DEPTH:
|
|
case VKD3D_SHADER_SV_COVERAGE:
|
|
@@ -7537,6 +7647,37 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
|
|
case VKD3D_SHADER_SV_STENCIL_REF:
|
|
break;
|
|
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE:
|
|
+ expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_QUAD;
|
|
+ semantic_index_max = 4;
|
|
+ is_outer = true;
|
|
+ break;
|
|
+
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT:
|
|
+ expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_QUAD;
|
|
+ semantic_index_max = 2;
|
|
+ is_outer = false;
|
|
+ break;
|
|
+
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE:
|
|
+ expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_TRIANGLE;
|
|
+ semantic_index_max = 3;
|
|
+ is_outer = true;
|
|
+ break;
|
|
+
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT:
|
|
+ expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_TRIANGLE;
|
|
+ semantic_index_max = 1;
|
|
+ is_outer = false;
|
|
+ break;
|
|
+
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET:
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN:
|
|
+ expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_LINE;
|
|
+ semantic_index_max = 2;
|
|
+ is_outer = true;
|
|
+ break;
|
|
+
|
|
default:
|
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
"element %u of %s signature: Invalid system value semantic %#x.",
|
|
@@ -7544,6 +7685,38 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
|
|
break;
|
|
}
|
|
|
|
+ if (expected_tess_domain != VKD3D_TESSELLATOR_DOMAIN_INVALID)
|
|
+ {
|
|
+ if (signature_type != SIGNATURE_TYPE_PATCH_CONSTANT)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: System value semantic %#x is only valid "
|
|
+ "in the patch constant signature.",
|
|
+ idx, signature_type_name, element->sysval_semantic);
|
|
+
|
|
+ if (ctx->program->tess_domain != expected_tess_domain)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid system value semantic %#x for tessellator domain %#x.",
|
|
+ idx, signature_type_name, element->sysval_semantic, ctx->program->tess_domain);
|
|
+
|
|
+ if (element->semantic_index >= semantic_index_max)
|
|
+ {
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid semantic index %u for system value semantic %#x.",
|
|
+ idx, signature_type_name, element->semantic_index, element->sysval_semantic);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ unsigned int *idx_pos = &(is_outer ? ctx->outer_tess_idxs : ctx->inner_tess_idxs)[element->semantic_index];
|
|
+
|
|
+ if (*idx_pos != ~0u)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Duplicate semantic index %u for system value semantic %#x.",
|
|
+ idx, signature_type_name, element->semantic_index, element->sysval_semantic);
|
|
+ else
|
|
+ *idx_pos = idx;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (element->sysval_semantic < ARRAY_SIZE(sysval_validation_data))
|
|
{
|
|
const struct sysval_validation_data_element *data = &sysval_validation_data[element->sysval_semantic];
|
|
@@ -7643,6 +7816,109 @@ static void vsir_validate_signature(struct validation_context *ctx,
|
|
|
|
for (i = 0; i < signature->element_count; ++i)
|
|
vsir_validate_signature_element(ctx, signature, signature_type, i);
|
|
+
|
|
+ if (signature_type == SIGNATURE_TYPE_PATCH_CONSTANT)
|
|
+ {
|
|
+ const struct signature_element *first_element, *element;
|
|
+ unsigned int expected_outer_count = 0;
|
|
+ unsigned int expected_inner_count = 0;
|
|
+
|
|
+ switch (ctx->program->tess_domain)
|
|
+ {
|
|
+ case VKD3D_TESSELLATOR_DOMAIN_QUAD:
|
|
+ expected_outer_count = 4;
|
|
+ expected_inner_count = 2;
|
|
+ break;
|
|
+
|
|
+ case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE:
|
|
+ expected_outer_count = 3;
|
|
+ expected_inner_count = 1;
|
|
+ break;
|
|
+
|
|
+ case VKD3D_TESSELLATOR_DOMAIN_LINE:
|
|
+ expected_outer_count = 2;
|
|
+ expected_inner_count = 0;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* After I/O normalisation tessellation factors are merged in a single array. */
|
|
+ if (ctx->program->normalisation_level >= VSIR_FULLY_NORMALISED_IO)
|
|
+ {
|
|
+ expected_outer_count = min(1, expected_outer_count);
|
|
+ expected_inner_count = min(1, expected_inner_count);
|
|
+ }
|
|
+
|
|
+ first_element = NULL;
|
|
+ for (i = 0; i < expected_outer_count; ++i)
|
|
+ {
|
|
+ if (ctx->outer_tess_idxs[i] == ~0u)
|
|
+ {
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "Missing outer system value semantic %u.", i);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ element = &signature->elements[ctx->outer_tess_idxs[i]];
|
|
+
|
|
+ if (!first_element)
|
|
+ {
|
|
+ first_element = element;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (element->register_index != first_element->register_index + i)
|
|
+ {
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
|
|
+ "Invalid register index %u for outer system value semantic %u, expected %u.",
|
|
+ element->register_index, i, first_element->register_index + i);
|
|
+ }
|
|
+
|
|
+ if (element->mask != first_element->mask)
|
|
+ {
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK,
|
|
+ "Invalid mask %#x for outer system value semantic %u, expected %#x.",
|
|
+ element->mask, i, first_element->mask);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ first_element = NULL;
|
|
+ for (i = 0; i < expected_inner_count; ++i)
|
|
+ {
|
|
+ if (ctx->inner_tess_idxs[i] == ~0u)
|
|
+ {
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "Missing inner system value semantic %u.", i);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ element = &signature->elements[ctx->inner_tess_idxs[i]];
|
|
+
|
|
+ if (!first_element)
|
|
+ {
|
|
+ first_element = element;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (element->register_index != first_element->register_index + i)
|
|
+ {
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
|
|
+ "Invalid register index %u for inner system value semantic %u, expected %u.",
|
|
+ element->register_index, i, first_element->register_index + i);
|
|
+ }
|
|
+
|
|
+ if (element->mask != first_element->mask)
|
|
+ {
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK,
|
|
+ "Invalid mask %#x for inner system value semantic %u, expected %#x.",
|
|
+ element->mask, i, first_element->mask);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
static const char *name_from_cf_type(enum vsir_control_flow_type type)
|
|
@@ -7754,6 +8030,39 @@ static void vsir_validate_dcl_hs_max_tessfactor(struct validation_context *ctx,
|
|
instruction->declaration.max_tessellation_factor);
|
|
}
|
|
|
|
+static void vsir_validate_dcl_input(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.dst.reg.type)
|
|
+ {
|
|
+ /* Signature input registers. */
|
|
+ case VKD3DSPR_INPUT:
|
|
+ case VKD3DSPR_INCONTROLPOINT:
|
|
+ case VKD3DSPR_OUTCONTROLPOINT:
|
|
+ case VKD3DSPR_PATCHCONST:
|
|
+ /* Non-signature input registers. */
|
|
+ case VKD3DSPR_PRIMID:
|
|
+ case VKD3DSPR_FORKINSTID:
|
|
+ case VKD3DSPR_JOININSTID:
|
|
+ case VKD3DSPR_THREADID:
|
|
+ case VKD3DSPR_THREADGROUPID:
|
|
+ case VKD3DSPR_LOCALTHREADID:
|
|
+ case VKD3DSPR_LOCALTHREADINDEX:
|
|
+ case VKD3DSPR_COVERAGE:
|
|
+ case VKD3DSPR_TESSCOORD:
|
|
+ case VKD3DSPR_OUTPOINTID:
|
|
+ case VKD3DSPR_GSINSTID:
|
|
+ case VKD3DSPR_WAVELANECOUNT:
|
|
+ case VKD3DSPR_WAVELANEINDEX:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_INPUT.",
|
|
+ instruction->declaration.dst.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
static void vsir_validate_dcl_input_primitive(struct validation_context *ctx,
|
|
const struct vkd3d_shader_instruction *instruction)
|
|
{
|
|
@@ -7763,6 +8072,105 @@ static void vsir_validate_dcl_input_primitive(struct validation_context *ctx,
|
|
instruction->declaration.primitive_type.type);
|
|
}
|
|
|
|
+static void vsir_validate_dcl_input_ps(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.dst.reg.type)
|
|
+ {
|
|
+ case VKD3DSPR_INPUT:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_INPUT_PS.",
|
|
+ instruction->declaration.dst.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void vsir_validate_dcl_input_ps_sgv(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.register_semantic.reg.reg.type)
|
|
+ {
|
|
+ case VKD3DSPR_INPUT:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_INPUT_PS_SGV.",
|
|
+ instruction->declaration.register_semantic.reg.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void vsir_validate_dcl_input_ps_siv(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.register_semantic.reg.reg.type)
|
|
+ {
|
|
+ case VKD3DSPR_INPUT:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_INPUT_PS_SIV.",
|
|
+ instruction->declaration.register_semantic.reg.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void vsir_validate_dcl_input_sgv(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.register_semantic.reg.reg.type)
|
|
+ {
|
|
+ case VKD3DSPR_INPUT:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_INPUT_SGV.",
|
|
+ instruction->declaration.register_semantic.reg.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void vsir_validate_dcl_input_siv(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.register_semantic.reg.reg.type)
|
|
+ {
|
|
+ case VKD3DSPR_INPUT:
|
|
+ case VKD3DSPR_PATCHCONST:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_INPUT_SIV.",
|
|
+ instruction->declaration.register_semantic.reg.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void vsir_validate_dcl_output(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.dst.reg.type)
|
|
+ {
|
|
+ /* Signature output registers. */
|
|
+ case VKD3DSPR_OUTPUT:
|
|
+ case VKD3DSPR_PATCHCONST:
|
|
+ /* Non-signature output registers. */
|
|
+ case VKD3DSPR_DEPTHOUT:
|
|
+ case VKD3DSPR_SAMPLEMASK:
|
|
+ case VKD3DSPR_DEPTHOUTGE:
|
|
+ case VKD3DSPR_DEPTHOUTLE:
|
|
+ case VKD3DSPR_OUTSTENCILREF:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_OUTPUT.",
|
|
+ instruction->declaration.dst.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
static void vsir_validate_dcl_output_control_point_count(struct validation_context *ctx,
|
|
const struct vkd3d_shader_instruction *instruction)
|
|
{
|
|
@@ -7772,6 +8180,22 @@ static void vsir_validate_dcl_output_control_point_count(struct validation_conte
|
|
instruction->declaration.count);
|
|
}
|
|
|
|
+static void vsir_validate_dcl_output_siv(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ switch (instruction->declaration.register_semantic.reg.reg.type)
|
|
+ {
|
|
+ case VKD3DSPR_OUTPUT:
|
|
+ case VKD3DSPR_PATCHCONST:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid register type %#x in instruction DCL_OUTPUT_SIV.",
|
|
+ instruction->declaration.register_semantic.reg.reg.type);
|
|
+ }
|
|
+}
|
|
+
|
|
static void vsir_validate_dcl_output_topology(struct validation_context *ctx,
|
|
const struct vkd3d_shader_instruction *instruction)
|
|
{
|
|
@@ -7801,6 +8225,11 @@ static void vsir_validate_dcl_tessellator_domain(struct validation_context *ctx,
|
|
|| instruction->declaration.tessellator_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT)
|
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION,
|
|
"Tessellator domain %#x is invalid.", instruction->declaration.tessellator_domain);
|
|
+
|
|
+ if (instruction->declaration.tessellator_domain != ctx->program->tess_domain)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION,
|
|
+ "DCL_TESSELLATOR_DOMAIN argument %#x doesn't match the shader tessellator domain %#x.",
|
|
+ instruction->declaration.tessellator_domain, ctx->program->tess_domain);
|
|
}
|
|
|
|
static void vsir_validate_dcl_tessellator_output_primitive(struct validation_context *ctx,
|
|
@@ -8063,8 +8492,16 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[
|
|
[VKD3DSIH_HS_JOIN_PHASE] = {0, 0, vsir_validate_hull_shader_phase},
|
|
[VKD3DSIH_DCL_GS_INSTANCES] = {0, 0, vsir_validate_dcl_gs_instances},
|
|
[VKD3DSIH_DCL_HS_MAX_TESSFACTOR] = {0, 0, vsir_validate_dcl_hs_max_tessfactor},
|
|
+ [VKD3DSIH_DCL_INPUT] = {0, 0, vsir_validate_dcl_input},
|
|
[VKD3DSIH_DCL_INPUT_PRIMITIVE] = {0, 0, vsir_validate_dcl_input_primitive},
|
|
+ [VKD3DSIH_DCL_INPUT_PS] = {0, 0, vsir_validate_dcl_input_ps},
|
|
+ [VKD3DSIH_DCL_INPUT_PS_SGV] = {0, 0, vsir_validate_dcl_input_ps_sgv},
|
|
+ [VKD3DSIH_DCL_INPUT_PS_SIV] = {0, 0, vsir_validate_dcl_input_ps_siv},
|
|
+ [VKD3DSIH_DCL_INPUT_SGV] = {0, 0, vsir_validate_dcl_input_sgv},
|
|
+ [VKD3DSIH_DCL_INPUT_SIV] = {0, 0, vsir_validate_dcl_input_siv},
|
|
+ [VKD3DSIH_DCL_OUTPUT] = {0, 0, vsir_validate_dcl_output},
|
|
[VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT] = {0, 0, vsir_validate_dcl_output_control_point_count},
|
|
+ [VKD3DSIH_DCL_OUTPUT_SIV] = {0, 0, vsir_validate_dcl_output_siv},
|
|
[VKD3DSIH_DCL_OUTPUT_TOPOLOGY] = {0, 0, vsir_validate_dcl_output_topology},
|
|
[VKD3DSIH_DCL_TEMPS] = {0, 0, vsir_validate_dcl_temps},
|
|
[VKD3DSIH_DCL_TESSELLATOR_DOMAIN] = {0, 0, vsir_validate_dcl_tessellator_domain},
|
|
@@ -8177,6 +8614,12 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c
|
|
.status = VKD3D_OK,
|
|
.phase = VKD3DSIH_INVALID,
|
|
.invalid_instruction_idx = true,
|
|
+ .outer_tess_idxs[0] = ~0u,
|
|
+ .outer_tess_idxs[1] = ~0u,
|
|
+ .outer_tess_idxs[2] = ~0u,
|
|
+ .outer_tess_idxs[3] = ~0u,
|
|
+ .inner_tess_idxs[0] = ~0u,
|
|
+ .inner_tess_idxs[1] = ~0u,
|
|
};
|
|
unsigned int i;
|
|
|
|
@@ -8187,12 +8630,20 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c
|
|
{
|
|
case VKD3D_SHADER_TYPE_HULL:
|
|
case VKD3D_SHADER_TYPE_DOMAIN:
|
|
+ if (program->tess_domain == VKD3D_TESSELLATOR_DOMAIN_INVALID
|
|
+ || program->tess_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT)
|
|
+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION,
|
|
+ "Invalid tessellation domain %#x.", program->tess_domain);
|
|
break;
|
|
|
|
default:
|
|
if (program->patch_constant_signature.element_count != 0)
|
|
validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
"Patch constant signature is only valid for hull and domain shaders.");
|
|
+
|
|
+ if (program->tess_domain != VKD3D_TESSELLATOR_DOMAIN_INVALID)
|
|
+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION,
|
|
+ "Invalid tessellation domain %#x.", program->tess_domain);
|
|
}
|
|
|
|
switch (program->shader_version.type)
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c
|
|
index df3edeaa4e6..29f51088728 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/msl.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c
|
|
@@ -153,6 +153,64 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer,
|
|
msl_print_register_datatype(buffer, gen, reg->data_type);
|
|
break;
|
|
|
|
+ case VKD3DSPR_IMMCONST:
|
|
+ switch (reg->dimension)
|
|
+ {
|
|
+ case VSIR_DIMENSION_SCALAR:
|
|
+ switch (reg->data_type)
|
|
+ {
|
|
+ case VKD3D_DATA_INT:
|
|
+ vkd3d_string_buffer_printf(buffer, "as_type<int>(%#xu)", reg->u.immconst_u32[0]);
|
|
+ break;
|
|
+ case VKD3D_DATA_UINT:
|
|
+ vkd3d_string_buffer_printf(buffer, "%#xu", reg->u.immconst_u32[0]);
|
|
+ break;
|
|
+ case VKD3D_DATA_FLOAT:
|
|
+ vkd3d_string_buffer_printf(buffer, "as_type<float>(%#xu)", reg->u.immconst_u32[0]);
|
|
+ break;
|
|
+ default:
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled immconst datatype %#x.", reg->data_type);
|
|
+ vkd3d_string_buffer_printf(buffer, "<unrecognised immconst datatype %#x>", reg->data_type);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VSIR_DIMENSION_VEC4:
|
|
+ switch (reg->data_type)
|
|
+ {
|
|
+ case VKD3D_DATA_INT:
|
|
+ vkd3d_string_buffer_printf(buffer, "as_type<int4>(uint4(%#xu, %#xu, %#xu, %#xu))",
|
|
+ reg->u.immconst_u32[0], reg->u.immconst_u32[1],
|
|
+ reg->u.immconst_u32[2], reg->u.immconst_u32[3]);
|
|
+ break;
|
|
+ case VKD3D_DATA_UINT:
|
|
+ vkd3d_string_buffer_printf(buffer, "uint4(%#xu, %#xu, %#xu, %#xu)",
|
|
+ reg->u.immconst_u32[0], reg->u.immconst_u32[1],
|
|
+ reg->u.immconst_u32[2], reg->u.immconst_u32[3]);
|
|
+ vkd3d_string_buffer_printf(buffer, "%#xu", reg->u.immconst_u32[0]);
|
|
+ break;
|
|
+ case VKD3D_DATA_FLOAT:
|
|
+ vkd3d_string_buffer_printf(buffer, "as_type<float4>(uint4(%#xu, %#xu, %#xu, %#xu))",
|
|
+ reg->u.immconst_u32[0], reg->u.immconst_u32[1],
|
|
+ reg->u.immconst_u32[2], reg->u.immconst_u32[3]);
|
|
+ break;
|
|
+ default:
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled immconst datatype %#x.", reg->data_type);
|
|
+ vkd3d_string_buffer_printf(buffer, "<unrecognised immconst datatype %#x>", reg->data_type);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled_dimension %#x>", reg->dimension);
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled dimension %#x.", reg->dimension);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
case VKD3DSPR_CONSTBUFFER:
|
|
if (reg->idx_count != 3)
|
|
{
|
|
@@ -215,19 +273,43 @@ static void msl_src_init(struct msl_src *msl_src, struct msl_generator *gen,
|
|
const struct vkd3d_shader_src_param *vsir_src, uint32_t mask)
|
|
{
|
|
const struct vkd3d_shader_register *reg = &vsir_src->reg;
|
|
+ struct vkd3d_string_buffer *str;
|
|
|
|
msl_src->str = vkd3d_string_buffer_get(&gen->string_buffers);
|
|
|
|
if (reg->non_uniform)
|
|
msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
"Internal compiler error: Unhandled 'non-uniform' modifier.");
|
|
- if (vsir_src->modifiers)
|
|
- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
- "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers);
|
|
|
|
- msl_print_register_name(msl_src->str, gen, reg);
|
|
+ if (!vsir_src->modifiers)
|
|
+ str = msl_src->str;
|
|
+ else
|
|
+ str = vkd3d_string_buffer_get(&gen->string_buffers);
|
|
+
|
|
+ msl_print_register_name(str, gen, reg);
|
|
if (reg->dimension == VSIR_DIMENSION_VEC4)
|
|
- msl_print_swizzle(msl_src->str, vsir_src->swizzle, mask);
|
|
+ msl_print_swizzle(str, vsir_src->swizzle, mask);
|
|
+
|
|
+ switch (vsir_src->modifiers)
|
|
+ {
|
|
+ case VKD3DSPSM_NONE:
|
|
+ break;
|
|
+ case VKD3DSPSM_NEG:
|
|
+ vkd3d_string_buffer_printf(msl_src->str, "-%s", str->buffer);
|
|
+ break;
|
|
+ case VKD3DSPSM_ABS:
|
|
+ vkd3d_string_buffer_printf(msl_src->str, "abs(%s)", str->buffer);
|
|
+ break;
|
|
+ default:
|
|
+ vkd3d_string_buffer_printf(msl_src->str, "<unhandled modifier %#x>(%s)",
|
|
+ vsir_src->modifiers, str->buffer);
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (str != msl_src->str)
|
|
+ vkd3d_string_buffer_release(&gen->string_buffers, str);
|
|
}
|
|
|
|
static void msl_dst_cleanup(struct msl_dst *dst, struct vkd3d_string_buffer_cache *cache)
|
|
@@ -288,6 +370,80 @@ static void msl_unhandled(struct msl_generator *gen, const struct vkd3d_shader_i
|
|
"Internal compiler error: Unhandled instruction %#x.", ins->opcode);
|
|
}
|
|
|
|
+static void msl_binop(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op)
|
|
+{
|
|
+ struct msl_src src[2];
|
|
+ struct msl_dst dst;
|
|
+ uint32_t mask;
|
|
+
|
|
+ mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]);
|
|
+ msl_src_init(&src[0], gen, &ins->src[0], mask);
|
|
+ msl_src_init(&src[1], gen, &ins->src[1], mask);
|
|
+
|
|
+ msl_print_assignment(gen, &dst, "%s %s %s", src[0].str->buffer, op, src[1].str->buffer);
|
|
+
|
|
+ msl_src_cleanup(&src[1], &gen->string_buffers);
|
|
+ msl_src_cleanup(&src[0], &gen->string_buffers);
|
|
+ msl_dst_cleanup(&dst, &gen->string_buffers);
|
|
+}
|
|
+
|
|
+static void msl_intrinsic(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op)
|
|
+{
|
|
+ struct msl_src src;
|
|
+ struct msl_dst dst;
|
|
+ uint32_t mask;
|
|
+
|
|
+ mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]);
|
|
+ msl_src_init(&src, gen, &ins->src[0], mask);
|
|
+
|
|
+ msl_print_assignment(gen, &dst, "%s(%s)", op, src.str->buffer);
|
|
+
|
|
+ msl_src_cleanup(&src, &gen->string_buffers);
|
|
+ msl_dst_cleanup(&dst, &gen->string_buffers);
|
|
+}
|
|
+
|
|
+static void msl_relop(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op)
|
|
+{
|
|
+ unsigned int mask_size;
|
|
+ struct msl_src src[2];
|
|
+ struct msl_dst dst;
|
|
+ uint32_t mask;
|
|
+
|
|
+ mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]);
|
|
+ msl_src_init(&src[0], gen, &ins->src[0], mask);
|
|
+ msl_src_init(&src[1], gen, &ins->src[1], mask);
|
|
+
|
|
+ if ((mask_size = vsir_write_mask_component_count(mask)) > 1)
|
|
+ msl_print_assignment(gen, &dst, "select(uint%u(0u), uint%u(0xffffffffu), bool%u(%s %s %s))",
|
|
+ mask_size, mask_size, mask_size, src[0].str->buffer, op, src[1].str->buffer);
|
|
+ else
|
|
+ msl_print_assignment(gen, &dst, "%s %s %s ? 0xffffffffu : 0u",
|
|
+ src[0].str->buffer, op, src[1].str->buffer);
|
|
+
|
|
+ msl_src_cleanup(&src[1], &gen->string_buffers);
|
|
+ msl_src_cleanup(&src[0], &gen->string_buffers);
|
|
+ msl_dst_cleanup(&dst, &gen->string_buffers);
|
|
+}
|
|
+
|
|
+static void msl_cast(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *constructor)
|
|
+{
|
|
+ unsigned int component_count;
|
|
+ struct msl_src src;
|
|
+ struct msl_dst dst;
|
|
+ uint32_t mask;
|
|
+
|
|
+ mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]);
|
|
+ msl_src_init(&src, gen, &ins->src[0], mask);
|
|
+
|
|
+ if ((component_count = vsir_write_mask_component_count(mask)) > 1)
|
|
+ msl_print_assignment(gen, &dst, "%s%u(%s)", constructor, component_count, src.str->buffer);
|
|
+ else
|
|
+ msl_print_assignment(gen, &dst, "%s(%s)", constructor, src.str->buffer);
|
|
+
|
|
+ msl_src_cleanup(&src, &gen->string_buffers);
|
|
+ msl_dst_cleanup(&dst, &gen->string_buffers);
|
|
+}
|
|
+
|
|
static void msl_mov(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins)
|
|
{
|
|
struct msl_src src;
|
|
@@ -303,6 +459,31 @@ static void msl_mov(struct msl_generator *gen, const struct vkd3d_shader_instruc
|
|
msl_dst_cleanup(&dst, &gen->string_buffers);
|
|
}
|
|
|
|
+static void msl_movc(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins)
|
|
+{
|
|
+ unsigned int component_count;
|
|
+ struct msl_src src[3];
|
|
+ struct msl_dst dst;
|
|
+ uint32_t mask;
|
|
+
|
|
+ mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]);
|
|
+ msl_src_init(&src[0], gen, &ins->src[0], mask);
|
|
+ msl_src_init(&src[1], gen, &ins->src[1], mask);
|
|
+ msl_src_init(&src[2], gen, &ins->src[2], mask);
|
|
+
|
|
+ if ((component_count = vsir_write_mask_component_count(mask)) > 1)
|
|
+ msl_print_assignment(gen, &dst, "select(%s, %s, bool%u(%s))",
|
|
+ src[2].str->buffer, src[1].str->buffer, component_count, src[0].str->buffer);
|
|
+ else
|
|
+ msl_print_assignment(gen, &dst, "select(%s, %s, bool(%s))",
|
|
+ src[2].str->buffer, src[1].str->buffer, src[0].str->buffer);
|
|
+
|
|
+ msl_src_cleanup(&src[2], &gen->string_buffers);
|
|
+ msl_src_cleanup(&src[1], &gen->string_buffers);
|
|
+ msl_src_cleanup(&src[0], &gen->string_buffers);
|
|
+ msl_dst_cleanup(&dst, &gen->string_buffers);
|
|
+}
|
|
+
|
|
static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins)
|
|
{
|
|
msl_print_indent(gen->buffer, gen->indent);
|
|
@@ -315,17 +496,61 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d
|
|
|
|
switch (ins->opcode)
|
|
{
|
|
+ case VKD3DSIH_ADD:
|
|
+ msl_binop(gen, ins, "+");
|
|
+ break;
|
|
+ case VKD3DSIH_AND:
|
|
+ msl_binop(gen, ins, "&");
|
|
+ break;
|
|
case VKD3DSIH_DCL_INPUT:
|
|
case VKD3DSIH_DCL_OUTPUT:
|
|
case VKD3DSIH_DCL_OUTPUT_SIV:
|
|
case VKD3DSIH_NOP:
|
|
break;
|
|
+ case VKD3DSIH_DIV:
|
|
+ msl_binop(gen, ins, "/");
|
|
+ break;
|
|
+ case VKD3DSIH_FRC:
|
|
+ msl_intrinsic(gen, ins, "fract");
|
|
+ break;
|
|
+ case VKD3DSIH_FTOI:
|
|
+ msl_cast(gen, ins, "int");
|
|
+ break;
|
|
+ case VKD3DSIH_FTOU:
|
|
+ msl_cast(gen, ins, "uint");
|
|
+ break;
|
|
+ case VKD3DSIH_GEO:
|
|
+ msl_relop(gen, ins, ">=");
|
|
+ break;
|
|
+ case VKD3DSIH_INE:
|
|
+ case VKD3DSIH_NEU:
|
|
+ msl_relop(gen, ins, "!=");
|
|
+ break;
|
|
+ case VKD3DSIH_ITOF:
|
|
+ case VKD3DSIH_UTOF:
|
|
+ msl_cast(gen, ins, "float");
|
|
+ break;
|
|
case VKD3DSIH_MOV:
|
|
msl_mov(gen, ins);
|
|
break;
|
|
+ case VKD3DSIH_MOVC:
|
|
+ msl_movc(gen, ins);
|
|
+ break;
|
|
+ case VKD3DSIH_MUL:
|
|
+ msl_binop(gen, ins, "*");
|
|
+ break;
|
|
+ case VKD3DSIH_OR:
|
|
+ msl_binop(gen, ins, "|");
|
|
+ break;
|
|
case VKD3DSIH_RET:
|
|
msl_ret(gen, ins);
|
|
break;
|
|
+ case VKD3DSIH_ROUND_PI:
|
|
+ msl_intrinsic(gen, ins, "ceil");
|
|
+ break;
|
|
+ case VKD3DSIH_ROUND_Z:
|
|
+ msl_intrinsic(gen, ins, "trunc");
|
|
+ break;
|
|
default:
|
|
msl_unhandled(gen, ins);
|
|
break;
|
|
@@ -790,6 +1015,8 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader
|
|
MESSAGE("Generating a MSL shader. This is unsupported; you get to keep all the pieces if it breaks.\n");
|
|
|
|
vkd3d_string_buffer_printf(gen->buffer, "/* Generated by %s. */\n\n", vkd3d_shader_get_version(NULL, NULL));
|
|
+ vkd3d_string_buffer_printf(gen->buffer, "#include <metal_common>\n\n");
|
|
+ vkd3d_string_buffer_printf(gen->buffer, "using namespace metal;\n\n");
|
|
|
|
if (gen->program->global_flags)
|
|
msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l
|
|
index 4a8d0fddae1..d167415c356 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/preproc.l
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l
|
|
@@ -20,6 +20,7 @@
|
|
|
|
%{
|
|
|
|
+#include "preproc.h"
|
|
#include "preproc.tab.h"
|
|
|
|
#undef ERROR /* defined in wingdi.h */
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
index bdfd632ad12..005b40a9d1f 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
@@ -2471,7 +2471,6 @@ struct spirv_compiler
|
|
bool emit_point_size;
|
|
|
|
enum vkd3d_shader_opcode phase;
|
|
- bool emit_default_control_point_phase;
|
|
struct vkd3d_shader_phase control_point_phase;
|
|
struct vkd3d_shader_phase patch_constant_phase;
|
|
|
|
@@ -6822,15 +6821,11 @@ static void spirv_compiler_emit_dcl_gs_instances(struct spirv_compiler *compiler
|
|
compiler->spirv_builder.invocation_count = instruction->declaration.count;
|
|
}
|
|
|
|
-static void spirv_compiler_emit_dcl_tessellator_domain(struct spirv_compiler *compiler,
|
|
- const struct vkd3d_shader_instruction *instruction)
|
|
+static void spirv_compiler_emit_tessellator_domain(struct spirv_compiler *compiler,
|
|
+ enum vkd3d_tessellator_domain domain)
|
|
{
|
|
- enum vkd3d_tessellator_domain domain = instruction->declaration.tessellator_domain;
|
|
SpvExecutionMode mode;
|
|
|
|
- if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && spirv_compiler_is_opengl_target(compiler))
|
|
- return;
|
|
-
|
|
switch (domain)
|
|
{
|
|
case VKD3D_TESSELLATOR_DOMAIN_LINE:
|
|
@@ -6916,15 +6911,10 @@ static void spirv_compiler_emit_thread_group_size(struct spirv_compiler *compile
|
|
SpvExecutionModeLocalSize, local_size, ARRAY_SIZE(local_size));
|
|
}
|
|
|
|
-static void spirv_compiler_emit_default_control_point_phase(struct spirv_compiler *compiler);
|
|
-
|
|
static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler)
|
|
{
|
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
|
|
- if (is_in_control_point_phase(compiler) && compiler->emit_default_control_point_phase)
|
|
- spirv_compiler_emit_default_control_point_phase(compiler);
|
|
-
|
|
vkd3d_spirv_build_op_function_end(builder);
|
|
|
|
if (is_in_control_point_phase(compiler))
|
|
@@ -6969,9 +6959,6 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler,
|
|
phase->function_id = function_id;
|
|
/* The insertion location must be set after the label is emitted. */
|
|
phase->function_location = 0;
|
|
-
|
|
- if (instruction->opcode == VKD3DSIH_HS_CONTROL_POINT_PHASE)
|
|
- compiler->emit_default_control_point_phase = instruction->flags;
|
|
}
|
|
|
|
static void spirv_compiler_initialise_block(struct spirv_compiler *compiler)
|
|
@@ -7000,63 +6987,6 @@ static void spirv_compiler_initialise_block(struct spirv_compiler *compiler)
|
|
}
|
|
}
|
|
|
|
-static void spirv_compiler_emit_default_control_point_phase(struct spirv_compiler *compiler)
|
|
-{
|
|
- const struct shader_signature *output_signature = &compiler->output_signature;
|
|
- const struct shader_signature *input_signature = &compiler->input_signature;
|
|
- uint32_t type_id, output_ptr_type_id, input_id, dst_id, invocation_id;
|
|
- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
- enum vkd3d_shader_component_type component_type;
|
|
- struct vkd3d_shader_src_param invocation;
|
|
- struct vkd3d_shader_register input_reg;
|
|
- unsigned int component_count;
|
|
- unsigned int i;
|
|
-
|
|
- vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
|
|
- spirv_compiler_initialise_block(compiler);
|
|
- invocation_id = spirv_compiler_emit_load_invocation_id(compiler);
|
|
-
|
|
- memset(&invocation, 0, sizeof(invocation));
|
|
- vsir_register_init(&invocation.reg, VKD3DSPR_OUTPOINTID, VKD3D_DATA_INT, 0);
|
|
- invocation.swizzle = VKD3D_SHADER_NO_SWIZZLE;
|
|
-
|
|
- vsir_register_init(&input_reg, VKD3DSPR_INPUT, VKD3D_DATA_FLOAT, 2);
|
|
- input_reg.idx[0].offset = 0;
|
|
- input_reg.idx[0].rel_addr = &invocation;
|
|
- input_reg.idx[1].offset = 0;
|
|
- input_id = spirv_compiler_get_register_id(compiler, &input_reg);
|
|
-
|
|
- VKD3D_ASSERT(input_signature->element_count == output_signature->element_count);
|
|
- for (i = 0; i < output_signature->element_count; ++i)
|
|
- {
|
|
- const struct signature_element *output = &output_signature->elements[i];
|
|
- const struct signature_element *input = &input_signature->elements[i];
|
|
- struct vkd3d_shader_register_info output_reg_info;
|
|
- struct vkd3d_shader_register output_reg;
|
|
-
|
|
- VKD3D_ASSERT(input->mask == output->mask);
|
|
- VKD3D_ASSERT(input->component_type == output->component_type);
|
|
-
|
|
- input_reg.idx[1].offset = i;
|
|
- input_id = spirv_compiler_get_register_id(compiler, &input_reg);
|
|
-
|
|
- vsir_register_init(&output_reg, VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1);
|
|
- output_reg.idx[0].offset = i;
|
|
- spirv_compiler_get_register_info(compiler, &output_reg, &output_reg_info);
|
|
-
|
|
- component_type = output->component_type;
|
|
- component_count = vsir_write_mask_component_count(output->mask);
|
|
- type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
|
|
- output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id);
|
|
-
|
|
- dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_reg_info.id, invocation_id);
|
|
-
|
|
- vkd3d_spirv_build_op_copy_memory(builder, dst_id, input_id, SpvMemoryAccessMaskNone);
|
|
- }
|
|
-
|
|
- vkd3d_spirv_build_op_return(builder);
|
|
-}
|
|
-
|
|
static void spirv_compiler_emit_barrier(struct spirv_compiler *compiler,
|
|
SpvScope execution_scope, SpvScope memory_scope, SpvMemorySemanticsMask semantics)
|
|
{
|
|
@@ -10239,9 +10169,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
|
|
case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT:
|
|
spirv_compiler_emit_output_vertex_count(compiler, instruction);
|
|
break;
|
|
- case VKD3DSIH_DCL_TESSELLATOR_DOMAIN:
|
|
- spirv_compiler_emit_dcl_tessellator_domain(compiler, instruction);
|
|
- break;
|
|
case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE:
|
|
spirv_compiler_emit_tessellator_output_primitive(compiler,
|
|
instruction->declaration.tessellator_output_primitive);
|
|
@@ -10743,6 +10670,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct
|
|
compiler->input_control_point_count = program->input_control_point_count;
|
|
compiler->output_control_point_count = program->output_control_point_count;
|
|
|
|
+ if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL && !spirv_compiler_is_opengl_target(compiler))
|
|
+ spirv_compiler_emit_tessellator_domain(compiler, program->tess_domain);
|
|
+
|
|
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
|
|
spirv_compiler_emit_shader_signature_outputs(compiler);
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
index 9c41e2c2053..409328b2e53 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
@@ -707,6 +707,7 @@ struct vkd3d_sm4_opcode_info
|
|
char src_info[SM4_MAX_SRC_COUNT];
|
|
void (*read_opcode_func)(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token,
|
|
const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv);
|
|
+ bool is_conditional_op;
|
|
};
|
|
|
|
static const enum vkd3d_primitive_type output_primitive_type_table[] =
|
|
@@ -1268,6 +1269,7 @@ static void shader_sm5_read_dcl_tessellator_domain(struct vkd3d_shader_instructi
|
|
{
|
|
ins->declaration.tessellator_domain = (opcode_token & VKD3D_SM5_TESSELLATOR_MASK)
|
|
>> VKD3D_SM5_TESSELLATOR_SHIFT;
|
|
+ priv->p.program->tess_domain = ins->declaration.tessellator_domain;
|
|
}
|
|
|
|
static void shader_sm5_read_dcl_tessellator_partitioning(struct vkd3d_shader_instruction *ins, uint32_t opcode,
|
|
@@ -1439,18 +1441,18 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
|
|
{VKD3D_SM4_OP_AND, VKD3DSIH_AND, "u", "uu"},
|
|
{VKD3D_SM4_OP_BREAK, VKD3DSIH_BREAK, "", ""},
|
|
{VKD3D_SM4_OP_BREAKC, VKD3DSIH_BREAKP, "", "u",
|
|
- shader_sm4_read_conditional_op},
|
|
+ shader_sm4_read_conditional_op, true},
|
|
{VKD3D_SM4_OP_CASE, VKD3DSIH_CASE, "", "u",
|
|
shader_sm4_read_case_condition},
|
|
{VKD3D_SM4_OP_CONTINUE, VKD3DSIH_CONTINUE, "", ""},
|
|
{VKD3D_SM4_OP_CONTINUEC, VKD3DSIH_CONTINUEP, "", "u",
|
|
- shader_sm4_read_conditional_op},
|
|
+ shader_sm4_read_conditional_op, true},
|
|
{VKD3D_SM4_OP_CUT, VKD3DSIH_CUT, "", ""},
|
|
{VKD3D_SM4_OP_DEFAULT, VKD3DSIH_DEFAULT, "", ""},
|
|
{VKD3D_SM4_OP_DERIV_RTX, VKD3DSIH_DSX, "f", "f"},
|
|
{VKD3D_SM4_OP_DERIV_RTY, VKD3DSIH_DSY, "f", "f"},
|
|
{VKD3D_SM4_OP_DISCARD, VKD3DSIH_DISCARD, "", "u",
|
|
- shader_sm4_read_conditional_op},
|
|
+ shader_sm4_read_conditional_op, true},
|
|
{VKD3D_SM4_OP_DIV, VKD3DSIH_DIV, "f", "ff"},
|
|
{VKD3D_SM4_OP_DP2, VKD3DSIH_DP2, "f", "ff"},
|
|
{VKD3D_SM4_OP_DP3, VKD3DSIH_DP3, "f", "ff"},
|
|
@@ -1468,7 +1470,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
|
|
{VKD3D_SM4_OP_GE, VKD3DSIH_GEO, "u", "ff"},
|
|
{VKD3D_SM4_OP_IADD, VKD3DSIH_IADD, "i", "ii"},
|
|
{VKD3D_SM4_OP_IF, VKD3DSIH_IF, "", "u",
|
|
- shader_sm4_read_conditional_op},
|
|
+ shader_sm4_read_conditional_op, true},
|
|
{VKD3D_SM4_OP_IEQ, VKD3DSIH_IEQ, "u", "ii"},
|
|
{VKD3D_SM4_OP_IGE, VKD3DSIH_IGE, "u", "ii"},
|
|
{VKD3D_SM4_OP_ILT, VKD3DSIH_ILT, "u", "ii"},
|
|
@@ -1502,7 +1504,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
|
|
{VKD3D_SM4_OP_RESINFO, VKD3DSIH_RESINFO, "f", "i*"},
|
|
{VKD3D_SM4_OP_RET, VKD3DSIH_RET, "", ""},
|
|
{VKD3D_SM4_OP_RETC, VKD3DSIH_RETP, "", "u",
|
|
- shader_sm4_read_conditional_op},
|
|
+ shader_sm4_read_conditional_op, true},
|
|
{VKD3D_SM4_OP_ROUND_NE, VKD3DSIH_ROUND_NE, "f", "f"},
|
|
{VKD3D_SM4_OP_ROUND_NI, VKD3DSIH_ROUND_NI, "f", "f"},
|
|
{VKD3D_SM4_OP_ROUND_PI, VKD3DSIH_ROUND_PI, "f", "f"},
|
|
@@ -1967,16 +1969,6 @@ static const struct vkd3d_sm4_register_type_info *get_info_from_vkd3d_register_t
|
|
return lookup->register_type_info_from_vkd3d[vkd3d_type];
|
|
}
|
|
|
|
-static enum vkd3d_sm4_swizzle_type vkd3d_sm4_get_default_swizzle_type(
|
|
- const struct vkd3d_sm4_lookup_tables *lookup, enum vkd3d_shader_register_type vkd3d_type)
|
|
-{
|
|
- const struct vkd3d_sm4_register_type_info *register_type_info =
|
|
- get_info_from_vkd3d_register_type(lookup, vkd3d_type);
|
|
-
|
|
- VKD3D_ASSERT(register_type_info);
|
|
- return register_type_info->default_src_swizzle_type;
|
|
-}
|
|
-
|
|
static enum vkd3d_sm4_stat_field get_stat_field_from_sm4_opcode(
|
|
const struct vkd3d_sm4_lookup_tables *lookup, enum vkd3d_sm4_opcode sm4_opcode)
|
|
{
|
|
@@ -2993,8 +2985,6 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
-static void write_sm4_block(struct tpf_compiler *tpf, const struct hlsl_block *block);
|
|
-
|
|
bool sm4_register_from_semantic_name(const struct vkd3d_shader_version *version,
|
|
const char *semantic_name, bool output, enum vkd3d_shader_register_type *type, bool *has_idx)
|
|
{
|
|
@@ -3331,6 +3321,7 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type)
|
|
case HLSL_CLASS_HULL_SHADER:
|
|
case HLSL_CLASS_GEOMETRY_SHADER:
|
|
case HLSL_CLASS_BLEND_STATE:
|
|
+ case HLSL_CLASS_STREAM_OUTPUT:
|
|
case HLSL_CLASS_NULL:
|
|
break;
|
|
}
|
|
@@ -4096,297 +4087,6 @@ struct sm4_instruction
|
|
unsigned int idx_src_count;
|
|
};
|
|
|
|
-static void sm4_register_from_node(struct vkd3d_shader_register *reg, uint32_t *writemask,
|
|
- const struct hlsl_ir_node *instr)
|
|
-{
|
|
- VKD3D_ASSERT(instr->reg.allocated);
|
|
- reg->type = VKD3DSPR_TEMP;
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- reg->idx[0].offset = instr->reg.id;
|
|
- reg->idx_count = 1;
|
|
- *writemask = instr->reg.writemask;
|
|
-}
|
|
-
|
|
-static void sm4_numeric_register_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_register *reg,
|
|
- enum vkd3d_shader_register_type type, uint32_t *writemask, const struct hlsl_deref *deref,
|
|
- struct sm4_instruction *sm4_instr)
|
|
-{
|
|
- const struct hlsl_ir_var *var = deref->var;
|
|
- unsigned int offset_const_deref;
|
|
-
|
|
- reg->type = type;
|
|
- reg->idx[0].offset = var->regs[HLSL_REGSET_NUMERIC].id;
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
-
|
|
- VKD3D_ASSERT(var->regs[HLSL_REGSET_NUMERIC].allocated);
|
|
-
|
|
- if (!var->indexable)
|
|
- {
|
|
- offset_const_deref = hlsl_offset_from_deref_safe(ctx, deref);
|
|
- reg->idx[0].offset += offset_const_deref / 4;
|
|
- reg->idx_count = 1;
|
|
- }
|
|
- else
|
|
- {
|
|
- offset_const_deref = deref->const_offset;
|
|
- reg->idx[1].offset = offset_const_deref / 4;
|
|
- reg->idx_count = 2;
|
|
-
|
|
- if (deref->rel_offset.node)
|
|
- {
|
|
- struct vkd3d_shader_src_param *idx_src;
|
|
- unsigned int idx_writemask;
|
|
-
|
|
- VKD3D_ASSERT(sm4_instr->idx_src_count < ARRAY_SIZE(sm4_instr->idx_srcs));
|
|
- idx_src = &sm4_instr->idx_srcs[sm4_instr->idx_src_count++];
|
|
- memset(idx_src, 0, sizeof(*idx_src));
|
|
-
|
|
- reg->idx[1].rel_addr = idx_src;
|
|
- sm4_register_from_node(&idx_src->reg, &idx_writemask, deref->rel_offset.node);
|
|
- VKD3D_ASSERT(idx_writemask != 0);
|
|
- idx_src->swizzle = swizzle_from_sm4(hlsl_swizzle_from_writemask(idx_writemask));
|
|
- }
|
|
- }
|
|
-
|
|
- *writemask = 0xf & (0xf << (offset_const_deref % 4));
|
|
- if (var->regs[HLSL_REGSET_NUMERIC].writemask)
|
|
- *writemask = hlsl_combine_writemasks(var->regs[HLSL_REGSET_NUMERIC].writemask, *writemask);
|
|
-}
|
|
-
|
|
-static void sm4_register_from_deref(const struct tpf_compiler *tpf, struct vkd3d_shader_register *reg,
|
|
- uint32_t *writemask, const struct hlsl_deref *deref, struct sm4_instruction *sm4_instr)
|
|
-{
|
|
- const struct vkd3d_shader_version *version = &tpf->program->shader_version;
|
|
- const struct hlsl_type *data_type = hlsl_deref_get_type(tpf->ctx, deref);
|
|
- const struct hlsl_ir_var *var = deref->var;
|
|
- struct hlsl_ctx *ctx = tpf->ctx;
|
|
-
|
|
- if (var->is_uniform)
|
|
- {
|
|
- enum hlsl_regset regset = hlsl_deref_get_regset(ctx, deref);
|
|
-
|
|
- if (regset == HLSL_REGSET_TEXTURES)
|
|
- {
|
|
- reg->type = VKD3DSPR_RESOURCE;
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
- {
|
|
- reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].id;
|
|
- reg->idx[1].offset = var->regs[HLSL_REGSET_TEXTURES].index; /* FIXME: array index */
|
|
- reg->idx_count = 2;
|
|
- }
|
|
- else
|
|
- {
|
|
- reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].index;
|
|
- reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref);
|
|
- reg->idx_count = 1;
|
|
- }
|
|
- VKD3D_ASSERT(regset == HLSL_REGSET_TEXTURES);
|
|
- *writemask = VKD3DSP_WRITEMASK_ALL;
|
|
- }
|
|
- else if (regset == HLSL_REGSET_UAVS)
|
|
- {
|
|
- reg->type = VKD3DSPR_UAV;
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
- {
|
|
- reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].id;
|
|
- reg->idx[1].offset = var->regs[HLSL_REGSET_UAVS].index; /* FIXME: array index */
|
|
- reg->idx_count = 2;
|
|
- }
|
|
- else
|
|
- {
|
|
- reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].index;
|
|
- reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref);
|
|
- reg->idx_count = 1;
|
|
- }
|
|
- VKD3D_ASSERT(regset == HLSL_REGSET_UAVS);
|
|
- *writemask = VKD3DSP_WRITEMASK_ALL;
|
|
- }
|
|
- else if (regset == HLSL_REGSET_SAMPLERS)
|
|
- {
|
|
- reg->type = VKD3DSPR_SAMPLER;
|
|
- reg->dimension = VSIR_DIMENSION_NONE;
|
|
- if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
- {
|
|
- reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].id;
|
|
- reg->idx[1].offset = var->regs[HLSL_REGSET_SAMPLERS].index; /* FIXME: array index */
|
|
- reg->idx_count = 2;
|
|
- }
|
|
- else
|
|
- {
|
|
- reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].index;
|
|
- reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref);
|
|
- reg->idx_count = 1;
|
|
- }
|
|
- VKD3D_ASSERT(regset == HLSL_REGSET_SAMPLERS);
|
|
- *writemask = VKD3DSP_WRITEMASK_ALL;
|
|
- }
|
|
- else
|
|
- {
|
|
- unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref) + var->buffer_offset;
|
|
-
|
|
- VKD3D_ASSERT(data_type->class <= HLSL_CLASS_VECTOR);
|
|
- reg->type = VKD3DSPR_CONSTBUFFER;
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- if (vkd3d_shader_ver_ge(version, 5, 1))
|
|
- {
|
|
- reg->idx[0].offset = var->buffer->reg.id;
|
|
- reg->idx[1].offset = var->buffer->reg.index; /* FIXME: array index */
|
|
- reg->idx[2].offset = offset / 4;
|
|
- reg->idx_count = 3;
|
|
- }
|
|
- else
|
|
- {
|
|
- reg->idx[0].offset = var->buffer->reg.index;
|
|
- reg->idx[1].offset = offset / 4;
|
|
- reg->idx_count = 2;
|
|
- }
|
|
- *writemask = ((1u << data_type->dimx) - 1) << (offset & 3);
|
|
- }
|
|
- }
|
|
- else if (var->is_input_semantic)
|
|
- {
|
|
- bool has_idx;
|
|
-
|
|
- if (sm4_register_from_semantic_name(version, var->semantic.name, false, ®->type, &has_idx))
|
|
- {
|
|
- unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref);
|
|
-
|
|
- if (has_idx)
|
|
- {
|
|
- reg->idx[0].offset = var->semantic.index + offset / 4;
|
|
- reg->idx_count = 1;
|
|
- }
|
|
-
|
|
- if (shader_sm4_is_scalar_register(reg))
|
|
- reg->dimension = VSIR_DIMENSION_SCALAR;
|
|
- else
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- *writemask = ((1u << data_type->dimx) - 1) << (offset % 4);
|
|
- }
|
|
- else
|
|
- {
|
|
- struct hlsl_reg hlsl_reg = hlsl_reg_from_deref(ctx, deref);
|
|
-
|
|
- VKD3D_ASSERT(hlsl_reg.allocated);
|
|
-
|
|
- if (version->type == VKD3D_SHADER_TYPE_DOMAIN)
|
|
- reg->type = VKD3DSPR_PATCHCONST;
|
|
- else
|
|
- reg->type = VKD3DSPR_INPUT;
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- reg->idx[0].offset = hlsl_reg.id;
|
|
- reg->idx_count = 1;
|
|
- *writemask = hlsl_reg.writemask;
|
|
- }
|
|
- }
|
|
- else if (var->is_output_semantic)
|
|
- {
|
|
- bool has_idx;
|
|
-
|
|
- if (sm4_register_from_semantic_name(version, var->semantic.name, true, ®->type, &has_idx))
|
|
- {
|
|
- unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref);
|
|
-
|
|
- if (has_idx)
|
|
- {
|
|
- reg->idx[0].offset = var->semantic.index + offset / 4;
|
|
- reg->idx_count = 1;
|
|
- }
|
|
-
|
|
- if (shader_sm4_is_scalar_register(reg))
|
|
- reg->dimension = VSIR_DIMENSION_SCALAR;
|
|
- else
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- *writemask = ((1u << data_type->dimx) - 1) << (offset % 4);
|
|
- }
|
|
- else
|
|
- {
|
|
- struct hlsl_reg hlsl_reg = hlsl_reg_from_deref(ctx, deref);
|
|
-
|
|
- VKD3D_ASSERT(hlsl_reg.allocated);
|
|
- reg->type = VKD3DSPR_OUTPUT;
|
|
- reg->dimension = VSIR_DIMENSION_VEC4;
|
|
- reg->idx[0].offset = hlsl_reg.id;
|
|
- reg->idx_count = 1;
|
|
- *writemask = hlsl_reg.writemask;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- enum vkd3d_shader_register_type type = deref->var->indexable ? VKD3DSPR_IDXTEMP : VKD3DSPR_TEMP;
|
|
-
|
|
- sm4_numeric_register_from_deref(ctx, reg, type, writemask, deref, sm4_instr);
|
|
- }
|
|
-}
|
|
-
|
|
-static void sm4_src_from_deref(const struct tpf_compiler *tpf, struct vkd3d_shader_src_param *src,
|
|
- const struct hlsl_deref *deref, unsigned int map_writemask, struct sm4_instruction *sm4_instr)
|
|
-{
|
|
- unsigned int hlsl_swizzle;
|
|
- uint32_t writemask;
|
|
-
|
|
- sm4_register_from_deref(tpf, &src->reg, &writemask, deref, sm4_instr);
|
|
- if (vkd3d_sm4_get_default_swizzle_type(&tpf->lookup, src->reg.type) == VKD3D_SM4_SWIZZLE_VEC4)
|
|
- {
|
|
- hlsl_swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), map_writemask);
|
|
- src->swizzle = swizzle_from_sm4(hlsl_swizzle);
|
|
- }
|
|
-}
|
|
-
|
|
-static void sm4_dst_from_node(struct vkd3d_shader_dst_param *dst, const struct hlsl_ir_node *instr)
|
|
-{
|
|
- sm4_register_from_node(&dst->reg, &dst->write_mask, instr);
|
|
-}
|
|
-
|
|
-static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src,
|
|
- const struct hlsl_constant_value *value, unsigned int width, unsigned int map_writemask)
|
|
-{
|
|
- src->swizzle = 0;
|
|
- src->reg.type = VKD3DSPR_IMMCONST;
|
|
- if (width == 1)
|
|
- {
|
|
- src->reg.dimension = VSIR_DIMENSION_SCALAR;
|
|
- src->reg.u.immconst_u32[0] = value->u[0].u;
|
|
- }
|
|
- else
|
|
- {
|
|
- unsigned int i, j = 0;
|
|
-
|
|
- src->reg.dimension = VSIR_DIMENSION_VEC4;
|
|
- for (i = 0; i < 4; ++i)
|
|
- {
|
|
- if ((map_writemask & (1u << i)) && (j < width))
|
|
- src->reg.u.immconst_u32[i] = value->u[j++].u;
|
|
- else
|
|
- src->reg.u.immconst_u32[i] = 0;
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-static void sm4_src_from_node(const struct tpf_compiler *tpf, struct vkd3d_shader_src_param *src,
|
|
- const struct hlsl_ir_node *instr, uint32_t map_writemask)
|
|
-{
|
|
- unsigned int hlsl_swizzle;
|
|
- uint32_t writemask;
|
|
-
|
|
- if (instr->type == HLSL_IR_CONSTANT)
|
|
- {
|
|
- struct hlsl_ir_constant *constant = hlsl_ir_constant(instr);
|
|
-
|
|
- sm4_src_from_constant_value(src, &constant->value, instr->data_type->dimx, map_writemask);
|
|
- return;
|
|
- }
|
|
-
|
|
- sm4_register_from_node(&src->reg, &writemask, instr);
|
|
- if (vkd3d_sm4_get_default_swizzle_type(&tpf->lookup, src->reg.type) == VKD3D_SM4_SWIZZLE_VEC4)
|
|
- {
|
|
- hlsl_swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), map_writemask);
|
|
- src->swizzle = swizzle_from_sm4(hlsl_swizzle);
|
|
- }
|
|
-}
|
|
-
|
|
static unsigned int sm4_get_index_addressing_from_reg(const struct vkd3d_shader_register *reg,
|
|
unsigned int i)
|
|
{
|
|
@@ -4650,33 +4350,6 @@ static void write_sm4_instruction(const struct tpf_compiler *tpf, const struct s
|
|
sm4_update_stat_counters(tpf, instr);
|
|
}
|
|
|
|
-static bool encode_texel_offset_as_aoffimmi(struct sm4_instruction *instr,
|
|
- const struct hlsl_ir_node *texel_offset)
|
|
-{
|
|
- struct sm4_instruction_modifier modif;
|
|
- struct hlsl_ir_constant *offset;
|
|
-
|
|
- if (!texel_offset || texel_offset->type != HLSL_IR_CONSTANT)
|
|
- return false;
|
|
- offset = hlsl_ir_constant(texel_offset);
|
|
-
|
|
- modif.type = VKD3D_SM4_MODIFIER_AOFFIMMI;
|
|
- modif.u.aoffimmi.u = offset->value.u[0].i;
|
|
- modif.u.aoffimmi.v = 0;
|
|
- modif.u.aoffimmi.w = 0;
|
|
- if (offset->node.data_type->dimx > 1)
|
|
- modif.u.aoffimmi.v = offset->value.u[1].i;
|
|
- if (offset->node.data_type->dimx > 2)
|
|
- modif.u.aoffimmi.w = offset->value.u[2].i;
|
|
- if (modif.u.aoffimmi.u < -8 || modif.u.aoffimmi.u > 7
|
|
- || modif.u.aoffimmi.v < -8 || modif.u.aoffimmi.v > 7
|
|
- || modif.u.aoffimmi.w < -8 || modif.u.aoffimmi.w > 7)
|
|
- return false;
|
|
-
|
|
- instr->modifiers[instr->modifier_count++] = modif;
|
|
- return true;
|
|
-}
|
|
-
|
|
static void write_sm4_dcl_constant_buffer(const struct tpf_compiler *tpf, const struct hlsl_buffer *cbuffer)
|
|
{
|
|
size_t size = (cbuffer->used_size + 3) / 4;
|
|
@@ -4945,26 +4618,6 @@ static void tpf_write_hs_decls(const struct tpf_compiler *tpf)
|
|
write_sm4_instruction(tpf, &instr);
|
|
}
|
|
|
|
-static void tpf_write_hs_control_point_phase(const struct tpf_compiler *tpf)
|
|
-{
|
|
- struct sm4_instruction instr =
|
|
- {
|
|
- .opcode = VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE,
|
|
- };
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void tpf_write_hs_fork_phase(const struct tpf_compiler *tpf)
|
|
-{
|
|
- struct sm4_instruction instr =
|
|
- {
|
|
- .opcode = VKD3D_SM5_OP_HS_FORK_PHASE,
|
|
- };
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
static void tpf_write_dcl_input_control_point_count(const struct tpf_compiler *tpf, const uint32_t count)
|
|
{
|
|
struct sm4_instruction instr =
|
|
@@ -5022,594 +4675,9 @@ static void tpf_write_dcl_tessellator_output_primitive(const struct tpf_compiler
|
|
write_sm4_instruction(tpf, &instr);
|
|
}
|
|
|
|
-static void write_sm4_ret(const struct tpf_compiler *tpf)
|
|
-{
|
|
- struct sm4_instruction instr =
|
|
- {
|
|
- .opcode = VKD3D_SM4_OP_RET,
|
|
- };
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_ld(const struct tpf_compiler *tpf, const struct hlsl_ir_node *dst,
|
|
- const struct hlsl_deref *resource, const struct hlsl_ir_node *coords,
|
|
- const struct hlsl_ir_node *sample_index, const struct hlsl_ir_node *texel_offset,
|
|
- enum hlsl_sampler_dim dim)
|
|
-{
|
|
- const struct hlsl_type *resource_type = hlsl_deref_get_type(tpf->ctx, resource);
|
|
- bool multisampled = resource_type->class == HLSL_CLASS_TEXTURE
|
|
- && (resource_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS || resource_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY);
|
|
- bool uav = (hlsl_deref_get_regset(tpf->ctx, resource) == HLSL_REGSET_UAVS);
|
|
- const struct vkd3d_shader_version *version = &tpf->program->shader_version;
|
|
- bool raw = resource_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER;
|
|
- unsigned int coords_writemask = VKD3DSP_WRITEMASK_ALL;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- if (uav)
|
|
- instr.opcode = VKD3D_SM5_OP_LD_UAV_TYPED;
|
|
- else if (raw)
|
|
- instr.opcode = VKD3D_SM5_OP_LD_RAW;
|
|
- else
|
|
- instr.opcode = multisampled ? VKD3D_SM4_OP_LD2DMS : VKD3D_SM4_OP_LD;
|
|
-
|
|
- if (texel_offset)
|
|
- {
|
|
- if (!encode_texel_offset_as_aoffimmi(&instr, texel_offset))
|
|
- {
|
|
- hlsl_error(tpf->ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
|
|
- "Offset must resolve to integer literal in the range -8 to 7.");
|
|
- return;
|
|
- }
|
|
- }
|
|
-
|
|
- sm4_dst_from_node(&instr.dsts[0], dst);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- if (!uav)
|
|
- {
|
|
- /* Mipmap level is in the last component in the IR, but needs to be in the W
|
|
- * component in the instruction. */
|
|
- unsigned int dim_count = hlsl_sampler_dim_count(dim);
|
|
-
|
|
- if (dim_count == 1)
|
|
- coords_writemask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_3;
|
|
- if (dim_count == 2)
|
|
- coords_writemask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_3;
|
|
- }
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], coords, coords_writemask);
|
|
-
|
|
- sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask, &instr);
|
|
-
|
|
- instr.src_count = 2;
|
|
-
|
|
- if (multisampled)
|
|
- {
|
|
- if (sample_index->type == HLSL_IR_CONSTANT)
|
|
- {
|
|
- struct vkd3d_shader_register *reg = &instr.srcs[2].reg;
|
|
- struct hlsl_ir_constant *index;
|
|
-
|
|
- index = hlsl_ir_constant(sample_index);
|
|
-
|
|
- memset(&instr.srcs[2], 0, sizeof(instr.srcs[2]));
|
|
- reg->type = VKD3DSPR_IMMCONST;
|
|
- reg->dimension = VSIR_DIMENSION_SCALAR;
|
|
- reg->u.immconst_u32[0] = index->value.u[0].u;
|
|
- }
|
|
- else if (version->major == 4 && version->minor == 0)
|
|
- {
|
|
- hlsl_error(tpf->ctx, &sample_index->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Expected literal sample index.");
|
|
- }
|
|
- else
|
|
- {
|
|
- sm4_src_from_node(tpf, &instr.srcs[2], sample_index, 0);
|
|
- }
|
|
-
|
|
- ++instr.src_count;
|
|
- }
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_sample(const struct tpf_compiler *tpf, const struct hlsl_ir_resource_load *load)
|
|
-{
|
|
- const struct hlsl_ir_node *texel_offset = load->texel_offset.node;
|
|
- const struct hlsl_ir_node *coords = load->coords.node;
|
|
- const struct hlsl_deref *resource = &load->resource;
|
|
- const struct hlsl_deref *sampler = &load->sampler;
|
|
- const struct hlsl_ir_node *dst = &load->node;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- switch (load->load_type)
|
|
- {
|
|
- case HLSL_RESOURCE_SAMPLE:
|
|
- instr.opcode = VKD3D_SM4_OP_SAMPLE;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_CMP:
|
|
- instr.opcode = VKD3D_SM4_OP_SAMPLE_C;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_CMP_LZ:
|
|
- instr.opcode = VKD3D_SM4_OP_SAMPLE_C_LZ;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_LOD:
|
|
- instr.opcode = VKD3D_SM4_OP_SAMPLE_LOD;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_LOD_BIAS:
|
|
- instr.opcode = VKD3D_SM4_OP_SAMPLE_B;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_GRAD:
|
|
- instr.opcode = VKD3D_SM4_OP_SAMPLE_GRAD;
|
|
- break;
|
|
-
|
|
- default:
|
|
- vkd3d_unreachable();
|
|
- }
|
|
-
|
|
- if (texel_offset)
|
|
- {
|
|
- if (!encode_texel_offset_as_aoffimmi(&instr, texel_offset))
|
|
- {
|
|
- hlsl_error(tpf->ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
|
|
- "Offset must resolve to integer literal in the range -8 to 7.");
|
|
- return;
|
|
- }
|
|
- }
|
|
-
|
|
- sm4_dst_from_node(&instr.dsts[0], dst);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
|
|
- sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask, &instr);
|
|
- sm4_src_from_deref(tpf, &instr.srcs[2], sampler, VKD3DSP_WRITEMASK_ALL, &instr);
|
|
- instr.src_count = 3;
|
|
-
|
|
- if (load->load_type == HLSL_RESOURCE_SAMPLE_LOD
|
|
- || load->load_type == HLSL_RESOURCE_SAMPLE_LOD_BIAS)
|
|
- {
|
|
- sm4_src_from_node(tpf, &instr.srcs[3], load->lod.node, VKD3DSP_WRITEMASK_ALL);
|
|
- ++instr.src_count;
|
|
- }
|
|
- else if (load->load_type == HLSL_RESOURCE_SAMPLE_GRAD)
|
|
- {
|
|
- sm4_src_from_node(tpf, &instr.srcs[3], load->ddx.node, VKD3DSP_WRITEMASK_ALL);
|
|
- sm4_src_from_node(tpf, &instr.srcs[4], load->ddy.node, VKD3DSP_WRITEMASK_ALL);
|
|
- instr.src_count += 2;
|
|
- }
|
|
- else if (load->load_type == HLSL_RESOURCE_SAMPLE_CMP
|
|
- || load->load_type == HLSL_RESOURCE_SAMPLE_CMP_LZ)
|
|
- {
|
|
- sm4_src_from_node(tpf, &instr.srcs[3], load->cmp.node, VKD3DSP_WRITEMASK_ALL);
|
|
- ++instr.src_count;
|
|
- }
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_sampleinfo(const struct tpf_compiler *tpf, const struct hlsl_ir_resource_load *load)
|
|
-{
|
|
- const struct hlsl_deref *resource = &load->resource;
|
|
- const struct hlsl_ir_node *dst = &load->node;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- VKD3D_ASSERT(dst->data_type->e.numeric.type == HLSL_TYPE_UINT || dst->data_type->e.numeric.type == HLSL_TYPE_FLOAT);
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- instr.opcode = VKD3D_SM4_OP_SAMPLE_INFO;
|
|
- if (dst->data_type->e.numeric.type == HLSL_TYPE_UINT)
|
|
- instr.extra_bits |= VKD3DSI_SAMPLE_INFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT;
|
|
-
|
|
- sm4_dst_from_node(&instr.dsts[0], dst);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- sm4_src_from_deref(tpf, &instr.srcs[0], resource, instr.dsts[0].write_mask, &instr);
|
|
- instr.src_count = 1;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_resinfo(const struct tpf_compiler *tpf, const struct hlsl_ir_resource_load *load)
|
|
-{
|
|
- const struct hlsl_deref *resource = &load->resource;
|
|
- const struct hlsl_ir_node *dst = &load->node;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- if (resource->data_type->sampler_dim == HLSL_SAMPLER_DIM_BUFFER
|
|
- || resource->data_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER)
|
|
- {
|
|
- hlsl_fixme(tpf->ctx, &load->node.loc, "resinfo for buffers.");
|
|
- return;
|
|
- }
|
|
-
|
|
- VKD3D_ASSERT(dst->data_type->e.numeric.type == HLSL_TYPE_UINT || dst->data_type->e.numeric.type == HLSL_TYPE_FLOAT);
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- instr.opcode = VKD3D_SM4_OP_RESINFO;
|
|
- if (dst->data_type->e.numeric.type == HLSL_TYPE_UINT)
|
|
- instr.extra_bits |= VKD3DSI_RESINFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT;
|
|
-
|
|
- sm4_dst_from_node(&instr.dsts[0], dst);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], load->lod.node, VKD3DSP_WRITEMASK_ALL);
|
|
- sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask, &instr);
|
|
- instr.src_count = 2;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_if(struct tpf_compiler *tpf, const struct hlsl_ir_if *iff)
|
|
-{
|
|
- struct sm4_instruction instr =
|
|
- {
|
|
- .opcode = VKD3D_SM4_OP_IF,
|
|
- .extra_bits = VKD3D_SM4_CONDITIONAL_NZ,
|
|
- .src_count = 1,
|
|
- };
|
|
-
|
|
- VKD3D_ASSERT(iff->condition.node->data_type->dimx == 1);
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], iff->condition.node, VKD3DSP_WRITEMASK_ALL);
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-
|
|
- write_sm4_block(tpf, &iff->then_block);
|
|
-
|
|
- if (!list_empty(&iff->else_block.instrs))
|
|
- {
|
|
- instr.opcode = VKD3D_SM4_OP_ELSE;
|
|
- instr.src_count = 0;
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-
|
|
- write_sm4_block(tpf, &iff->else_block);
|
|
- }
|
|
-
|
|
- instr.opcode = VKD3D_SM4_OP_ENDIF;
|
|
- instr.src_count = 0;
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_jump(const struct tpf_compiler *tpf, const struct hlsl_ir_jump *jump)
|
|
-{
|
|
- struct sm4_instruction instr = {0};
|
|
-
|
|
- switch (jump->type)
|
|
- {
|
|
- case HLSL_IR_JUMP_BREAK:
|
|
- instr.opcode = VKD3D_SM4_OP_BREAK;
|
|
- break;
|
|
-
|
|
- case HLSL_IR_JUMP_CONTINUE:
|
|
- instr.opcode = VKD3D_SM4_OP_CONTINUE;
|
|
- break;
|
|
-
|
|
- case HLSL_IR_JUMP_DISCARD_NZ:
|
|
- {
|
|
- instr.opcode = VKD3D_SM4_OP_DISCARD;
|
|
- instr.extra_bits = VKD3D_SM4_CONDITIONAL_NZ;
|
|
-
|
|
- memset(&instr.srcs[0], 0, sizeof(*instr.srcs));
|
|
- instr.src_count = 1;
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], jump->condition.node, VKD3DSP_WRITEMASK_ALL);
|
|
- break;
|
|
- }
|
|
-
|
|
- case HLSL_IR_JUMP_RETURN:
|
|
- vkd3d_unreachable();
|
|
-
|
|
- default:
|
|
- hlsl_fixme(tpf->ctx, &jump->node.loc, "Jump type %s.", hlsl_jump_type_to_string(jump->type));
|
|
- return;
|
|
- }
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-/* Does this variable's data come directly from the API user, rather than being
|
|
- * temporary or from a previous shader stage?
|
|
- * I.e. is it a uniform or VS input? */
|
|
-static bool var_is_user_input(const struct vkd3d_shader_version *version, const struct hlsl_ir_var *var)
|
|
-{
|
|
- if (var->is_uniform)
|
|
- return true;
|
|
-
|
|
- return var->is_input_semantic && version->type == VKD3D_SHADER_TYPE_VERTEX;
|
|
-}
|
|
-
|
|
-static void write_sm4_load(const struct tpf_compiler *tpf, const struct hlsl_ir_load *load)
|
|
-{
|
|
- const struct vkd3d_shader_version *version = &tpf->program->shader_version;
|
|
- const struct hlsl_type *type = load->node.data_type;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
-
|
|
- sm4_dst_from_node(&instr.dsts[0], &load->node);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- VKD3D_ASSERT(hlsl_is_numeric_type(type));
|
|
- if (type->e.numeric.type == HLSL_TYPE_BOOL && var_is_user_input(version, load->src.var))
|
|
- {
|
|
- struct hlsl_constant_value value;
|
|
-
|
|
- /* Uniform bools can be specified as anything, but internal bools always
|
|
- * have 0 for false and ~0 for true. Normalize that here. */
|
|
-
|
|
- instr.opcode = VKD3D_SM4_OP_MOVC;
|
|
-
|
|
- sm4_src_from_deref(tpf, &instr.srcs[0], &load->src, instr.dsts[0].write_mask, &instr);
|
|
-
|
|
- memset(&value, 0xff, sizeof(value));
|
|
- sm4_src_from_constant_value(&instr.srcs[1], &value, type->dimx, instr.dsts[0].write_mask);
|
|
- memset(&value, 0, sizeof(value));
|
|
- sm4_src_from_constant_value(&instr.srcs[2], &value, type->dimx, instr.dsts[0].write_mask);
|
|
- instr.src_count = 3;
|
|
- }
|
|
- else
|
|
- {
|
|
- instr.opcode = VKD3D_SM4_OP_MOV;
|
|
-
|
|
- sm4_src_from_deref(tpf, &instr.srcs[0], &load->src, instr.dsts[0].write_mask, &instr);
|
|
- instr.src_count = 1;
|
|
- }
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_loop(struct tpf_compiler *tpf, const struct hlsl_ir_loop *loop)
|
|
-{
|
|
- struct sm4_instruction instr =
|
|
- {
|
|
- .opcode = VKD3D_SM4_OP_LOOP,
|
|
- };
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-
|
|
- write_sm4_block(tpf, &loop->body);
|
|
-
|
|
- instr.opcode = VKD3D_SM4_OP_ENDLOOP;
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_gather(const struct tpf_compiler *tpf, const struct hlsl_ir_node *dst,
|
|
- const struct hlsl_deref *resource, const struct hlsl_deref *sampler,
|
|
- const struct hlsl_ir_node *coords, uint32_t swizzle, const struct hlsl_ir_node *texel_offset)
|
|
-{
|
|
- const struct vkd3d_shader_version *version = &tpf->program->shader_version;
|
|
- struct vkd3d_shader_src_param *src;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
-
|
|
- instr.opcode = VKD3D_SM4_OP_GATHER4;
|
|
-
|
|
- sm4_dst_from_node(&instr.dsts[0], dst);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[instr.src_count++], coords, VKD3DSP_WRITEMASK_ALL);
|
|
-
|
|
- if (texel_offset)
|
|
- {
|
|
- if (!encode_texel_offset_as_aoffimmi(&instr, texel_offset))
|
|
- {
|
|
- if (!vkd3d_shader_ver_ge(version, 5, 0))
|
|
- {
|
|
- hlsl_error(tpf->ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
|
|
- "Offset must resolve to integer literal in the range -8 to 7 for profiles < 5.");
|
|
- return;
|
|
- }
|
|
- instr.opcode = VKD3D_SM5_OP_GATHER4_PO;
|
|
- sm4_src_from_node(tpf, &instr.srcs[instr.src_count++], texel_offset, VKD3DSP_WRITEMASK_ALL);
|
|
- }
|
|
- }
|
|
-
|
|
- sm4_src_from_deref(tpf, &instr.srcs[instr.src_count++], resource, instr.dsts[0].write_mask, &instr);
|
|
-
|
|
- src = &instr.srcs[instr.src_count++];
|
|
- sm4_src_from_deref(tpf, src, sampler, VKD3DSP_WRITEMASK_ALL, &instr);
|
|
- src->reg.dimension = VSIR_DIMENSION_VEC4;
|
|
- src->swizzle = swizzle;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_resource_load(const struct tpf_compiler *tpf, const struct hlsl_ir_resource_load *load)
|
|
-{
|
|
- const struct hlsl_ir_node *texel_offset = load->texel_offset.node;
|
|
- const struct hlsl_ir_node *sample_index = load->sample_index.node;
|
|
- const struct hlsl_ir_node *coords = load->coords.node;
|
|
-
|
|
- if (load->sampler.var && !load->sampler.var->is_uniform)
|
|
- {
|
|
- hlsl_fixme(tpf->ctx, &load->node.loc, "Sample using non-uniform sampler variable.");
|
|
- return;
|
|
- }
|
|
-
|
|
- if (!load->resource.var->is_uniform)
|
|
- {
|
|
- hlsl_fixme(tpf->ctx, &load->node.loc, "Load from non-uniform resource variable.");
|
|
- return;
|
|
- }
|
|
-
|
|
- switch (load->load_type)
|
|
- {
|
|
- case HLSL_RESOURCE_LOAD:
|
|
- write_sm4_ld(tpf, &load->node, &load->resource,
|
|
- coords, sample_index, texel_offset, load->sampling_dim);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE:
|
|
- case HLSL_RESOURCE_SAMPLE_CMP:
|
|
- case HLSL_RESOURCE_SAMPLE_CMP_LZ:
|
|
- case HLSL_RESOURCE_SAMPLE_LOD:
|
|
- case HLSL_RESOURCE_SAMPLE_LOD_BIAS:
|
|
- case HLSL_RESOURCE_SAMPLE_GRAD:
|
|
- /* Combined sample expressions were lowered. */
|
|
- VKD3D_ASSERT(load->sampler.var);
|
|
- write_sm4_sample(tpf, load);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_GATHER_RED:
|
|
- write_sm4_gather(tpf, &load->node, &load->resource, &load->sampler, coords,
|
|
- VKD3D_SHADER_SWIZZLE(X, X, X, X), texel_offset);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_GATHER_GREEN:
|
|
- write_sm4_gather(tpf, &load->node, &load->resource, &load->sampler, coords,
|
|
- VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y), texel_offset);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_GATHER_BLUE:
|
|
- write_sm4_gather(tpf, &load->node, &load->resource, &load->sampler, coords,
|
|
- VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z), texel_offset);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_GATHER_ALPHA:
|
|
- write_sm4_gather(tpf, &load->node, &load->resource, &load->sampler, coords,
|
|
- VKD3D_SHADER_SWIZZLE(W, W, W, W), texel_offset);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_INFO:
|
|
- write_sm4_sampleinfo(tpf, load);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_RESINFO:
|
|
- write_sm4_resinfo(tpf, load);
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_PROJ:
|
|
- vkd3d_unreachable();
|
|
- }
|
|
-}
|
|
-
|
|
-static void write_sm4_resource_store(const struct tpf_compiler *tpf, const struct hlsl_ir_resource_store *store)
|
|
-{
|
|
- struct hlsl_type *resource_type = hlsl_deref_get_type(tpf->ctx, &store->resource);
|
|
- struct hlsl_ir_node *coords = store->coords.node, *value = store->value.node;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- if (!store->resource.var->is_uniform)
|
|
- {
|
|
- hlsl_fixme(tpf->ctx, &store->node.loc, "Store to non-uniform resource variable.");
|
|
- return;
|
|
- }
|
|
-
|
|
- if (resource_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER)
|
|
- {
|
|
- hlsl_fixme(tpf->ctx, &store->node.loc, "Structured buffers store is not implemented.");
|
|
- return;
|
|
- }
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
-
|
|
- sm4_register_from_deref(tpf, &instr.dsts[0].reg, &instr.dsts[0].write_mask, &store->resource, &instr);
|
|
- instr.dst_count = 1;
|
|
- if (resource_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER)
|
|
- {
|
|
- instr.opcode = VKD3D_SM5_OP_STORE_RAW;
|
|
- instr.dsts[0].write_mask = vkd3d_write_mask_from_component_count(value->data_type->dimx);
|
|
- }
|
|
- else
|
|
- {
|
|
- instr.opcode = VKD3D_SM5_OP_STORE_UAV_TYPED;
|
|
- }
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
|
|
- sm4_src_from_node(tpf, &instr.srcs[1], value, VKD3DSP_WRITEMASK_ALL);
|
|
- instr.src_count = 2;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_store(const struct tpf_compiler *tpf, const struct hlsl_ir_store *store)
|
|
-{
|
|
- const struct hlsl_ir_node *rhs = store->rhs.node;
|
|
- struct sm4_instruction instr;
|
|
- uint32_t writemask;
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- instr.opcode = VKD3D_SM4_OP_MOV;
|
|
-
|
|
- sm4_register_from_deref(tpf, &instr.dsts[0].reg, &writemask, &store->lhs, &instr);
|
|
- instr.dsts[0].write_mask = hlsl_combine_writemasks(writemask, store->writemask);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], rhs, instr.dsts[0].write_mask);
|
|
- instr.src_count = 1;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_switch(struct tpf_compiler *tpf, const struct hlsl_ir_switch *s)
|
|
-{
|
|
- const struct hlsl_ir_node *selector = s->selector.node;
|
|
- struct hlsl_ir_switch_case *c;
|
|
- struct sm4_instruction instr;
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- instr.opcode = VKD3D_SM4_OP_SWITCH;
|
|
-
|
|
- sm4_src_from_node(tpf, &instr.srcs[0], selector, VKD3DSP_WRITEMASK_ALL);
|
|
- instr.src_count = 1;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-
|
|
- LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
|
- {
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- if (c->is_default)
|
|
- {
|
|
- instr.opcode = VKD3D_SM4_OP_DEFAULT;
|
|
- }
|
|
- else
|
|
- {
|
|
- struct hlsl_constant_value value = { .u[0].u = c->value };
|
|
-
|
|
- instr.opcode = VKD3D_SM4_OP_CASE;
|
|
- sm4_src_from_constant_value(&instr.srcs[0], &value, 1, VKD3DSP_WRITEMASK_ALL);
|
|
- instr.src_count = 1;
|
|
- }
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
- write_sm4_block(tpf, &c->body);
|
|
- }
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- instr.opcode = VKD3D_SM4_OP_ENDSWITCH;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
-static void write_sm4_swizzle(const struct tpf_compiler *tpf, const struct hlsl_ir_swizzle *swizzle)
|
|
-{
|
|
- unsigned int hlsl_swizzle;
|
|
- struct sm4_instruction instr;
|
|
- uint32_t writemask;
|
|
-
|
|
- memset(&instr, 0, sizeof(instr));
|
|
- instr.opcode = VKD3D_SM4_OP_MOV;
|
|
-
|
|
- sm4_dst_from_node(&instr.dsts[0], &swizzle->node);
|
|
- instr.dst_count = 1;
|
|
-
|
|
- sm4_register_from_node(&instr.srcs[0].reg, &writemask, swizzle->val.node);
|
|
- hlsl_swizzle = hlsl_map_swizzle(hlsl_combine_swizzles(hlsl_swizzle_from_writemask(writemask),
|
|
- swizzle->swizzle, swizzle->node.data_type->dimx), instr.dsts[0].write_mask);
|
|
- instr.srcs[0].swizzle = swizzle_from_sm4(hlsl_swizzle);
|
|
- instr.src_count = 1;
|
|
-
|
|
- write_sm4_instruction(tpf, &instr);
|
|
-}
|
|
-
|
|
static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins)
|
|
{
|
|
+ struct sm4_instruction_modifier *modifier;
|
|
const struct vkd3d_sm4_opcode_info *info;
|
|
struct sm4_instruction instr = {0};
|
|
unsigned int dst_count, src_count;
|
|
@@ -5655,6 +4723,22 @@ static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_
|
|
for (unsigned int i = 0; i < ins->src_count; ++i)
|
|
instr.srcs[i] = ins->src[i];
|
|
|
|
+ if (ins->texel_offset.u || ins->texel_offset.v || ins->texel_offset.w)
|
|
+ {
|
|
+ VKD3D_ASSERT(instr.modifier_count < ARRAY_SIZE(instr.modifiers));
|
|
+ modifier = &instr.modifiers[instr.modifier_count++];
|
|
+ modifier->type = VKD3D_SM4_MODIFIER_AOFFIMMI;
|
|
+ modifier->u.aoffimmi.u = ins->texel_offset.u;
|
|
+ modifier->u.aoffimmi.v = ins->texel_offset.v;
|
|
+ modifier->u.aoffimmi.w = ins->texel_offset.w;
|
|
+ }
|
|
+
|
|
+ if (info->is_conditional_op)
|
|
+ {
|
|
+ if (ins->flags == VKD3D_SHADER_CONDITIONAL_OP_NZ)
|
|
+ instr.extra_bits = VKD3D_SM4_CONDITIONAL_NZ;
|
|
+ }
|
|
+
|
|
write_sm4_instruction(tpf, &instr);
|
|
}
|
|
|
|
@@ -5704,6 +4788,11 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_
|
|
|
|
case VKD3DSIH_ADD:
|
|
case VKD3DSIH_AND:
|
|
+ case VKD3DSIH_BREAK:
|
|
+ case VKD3DSIH_CASE:
|
|
+ case VKD3DSIH_CONTINUE:
|
|
+ case VKD3DSIH_DEFAULT:
|
|
+ case VKD3DSIH_DISCARD:
|
|
case VKD3DSIH_DIV:
|
|
case VKD3DSIH_DP2:
|
|
case VKD3DSIH_DP3:
|
|
@@ -5714,6 +4803,10 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_
|
|
case VKD3DSIH_DSY:
|
|
case VKD3DSIH_DSY_COARSE:
|
|
case VKD3DSIH_DSY_FINE:
|
|
+ case VKD3DSIH_ELSE:
|
|
+ case VKD3DSIH_ENDIF:
|
|
+ case VKD3DSIH_ENDLOOP:
|
|
+ case VKD3DSIH_ENDSWITCH:
|
|
case VKD3DSIH_EQO:
|
|
case VKD3DSIH_EXP:
|
|
case VKD3DSIH_F16TOF32:
|
|
@@ -5721,9 +4814,14 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_
|
|
case VKD3DSIH_FRC:
|
|
case VKD3DSIH_FTOI:
|
|
case VKD3DSIH_FTOU:
|
|
+ case VKD3DSIH_GATHER4:
|
|
+ case VKD3DSIH_GATHER4_PO:
|
|
case VKD3DSIH_GEO:
|
|
+ case VKD3DSIH_HS_CONTROL_POINT_PHASE:
|
|
+ case VKD3DSIH_HS_FORK_PHASE:
|
|
case VKD3DSIH_IADD:
|
|
case VKD3DSIH_IEQ:
|
|
+ case VKD3DSIH_IF:
|
|
case VKD3DSIH_IGE:
|
|
case VKD3DSIH_ILT:
|
|
case VKD3DSIH_IMAD:
|
|
@@ -5735,7 +4833,12 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_
|
|
case VKD3DSIH_ISHL:
|
|
case VKD3DSIH_ISHR:
|
|
case VKD3DSIH_ITOF:
|
|
+ case VKD3DSIH_LD:
|
|
+ case VKD3DSIH_LD2DMS:
|
|
+ case VKD3DSIH_LD_RAW:
|
|
+ case VKD3DSIH_LD_UAV_TYPED:
|
|
case VKD3DSIH_LOG:
|
|
+ case VKD3DSIH_LOOP:
|
|
case VKD3DSIH_LTO:
|
|
case VKD3DSIH_MAD:
|
|
case VKD3DSIH_MAX:
|
|
@@ -5747,14 +4850,25 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_
|
|
case VKD3DSIH_NOT:
|
|
case VKD3DSIH_OR:
|
|
case VKD3DSIH_RCP:
|
|
+ case VKD3DSIH_RESINFO:
|
|
+ case VKD3DSIH_RET:
|
|
case VKD3DSIH_ROUND_NE:
|
|
case VKD3DSIH_ROUND_NI:
|
|
case VKD3DSIH_ROUND_PI:
|
|
case VKD3DSIH_ROUND_Z:
|
|
case VKD3DSIH_RSQ:
|
|
+ case VKD3DSIH_SAMPLE:
|
|
+ case VKD3DSIH_SAMPLE_B:
|
|
+ case VKD3DSIH_SAMPLE_C:
|
|
+ case VKD3DSIH_SAMPLE_C_LZ:
|
|
+ case VKD3DSIH_SAMPLE_GRAD:
|
|
case VKD3DSIH_SAMPLE_INFO:
|
|
+ case VKD3DSIH_SAMPLE_LOD:
|
|
case VKD3DSIH_SINCOS:
|
|
case VKD3DSIH_SQRT:
|
|
+ case VKD3DSIH_STORE_RAW:
|
|
+ case VKD3DSIH_STORE_UAV_TYPED:
|
|
+ case VKD3DSIH_SWITCH:
|
|
case VKD3DSIH_UDIV:
|
|
case VKD3DSIH_UGE:
|
|
case VKD3DSIH_ULT:
|
|
@@ -5772,90 +4886,15 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_
|
|
}
|
|
}
|
|
|
|
-static void write_sm4_block(struct tpf_compiler *tpf, const struct hlsl_block *block)
|
|
+static void tpf_write_program(struct tpf_compiler *tpf, const struct vsir_program *program)
|
|
{
|
|
- const struct hlsl_ir_node *instr;
|
|
- unsigned int vsir_instr_idx;
|
|
-
|
|
- LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
|
|
- {
|
|
- if (instr->data_type)
|
|
- {
|
|
- if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR)
|
|
- {
|
|
- hlsl_fixme(tpf->ctx, &instr->loc, "Class %#x should have been lowered or removed.",
|
|
- instr->data_type->class);
|
|
- break;
|
|
- }
|
|
-
|
|
- if (!instr->reg.allocated)
|
|
- {
|
|
- VKD3D_ASSERT(instr->type == HLSL_IR_CONSTANT);
|
|
- continue;
|
|
- }
|
|
- }
|
|
-
|
|
- switch (instr->type)
|
|
- {
|
|
- case HLSL_IR_CALL:
|
|
- case HLSL_IR_CONSTANT:
|
|
- vkd3d_unreachable();
|
|
-
|
|
- case HLSL_IR_IF:
|
|
- write_sm4_if(tpf, hlsl_ir_if(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_JUMP:
|
|
- write_sm4_jump(tpf, hlsl_ir_jump(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_LOAD:
|
|
- write_sm4_load(tpf, hlsl_ir_load(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_RESOURCE_LOAD:
|
|
- write_sm4_resource_load(tpf, hlsl_ir_resource_load(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_RESOURCE_STORE:
|
|
- write_sm4_resource_store(tpf, hlsl_ir_resource_store(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_LOOP:
|
|
- write_sm4_loop(tpf, hlsl_ir_loop(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_STORE:
|
|
- write_sm4_store(tpf, hlsl_ir_store(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_SWITCH:
|
|
- write_sm4_switch(tpf, hlsl_ir_switch(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_SWIZZLE:
|
|
- write_sm4_swizzle(tpf, hlsl_ir_swizzle(instr));
|
|
- break;
|
|
-
|
|
- case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
- vsir_instr_idx = hlsl_ir_vsir_instruction_ref(instr)->vsir_instr_idx;
|
|
- tpf_handle_instruction(tpf, &tpf->program->instructions.elements[vsir_instr_idx]);
|
|
- break;
|
|
-
|
|
- default:
|
|
- hlsl_fixme(tpf->ctx, &instr->loc, "Instruction type %s.", hlsl_node_type_to_string(instr->type));
|
|
- }
|
|
- }
|
|
-}
|
|
+ unsigned int i;
|
|
|
|
-static void tpf_write_shader_function(struct tpf_compiler *tpf, struct hlsl_ir_function_decl *func)
|
|
-{
|
|
if (tpf->program->shader_version.type == VKD3D_SHADER_TYPE_COMPUTE)
|
|
tpf_dcl_thread_group(tpf, &tpf->program->thread_group_size);
|
|
|
|
- write_sm4_block(tpf, &func->body);
|
|
-
|
|
- write_sm4_ret(tpf);
|
|
+ for (i = 0; i < program->instructions.count; ++i)
|
|
+ tpf_handle_instruction(tpf, &program->instructions.elements[i]);
|
|
}
|
|
|
|
static void tpf_write_shdr(struct tpf_compiler *tpf, struct hlsl_ir_function_decl *entry_func)
|
|
@@ -5944,16 +4983,7 @@ static void tpf_write_shdr(struct tpf_compiler *tpf, struct hlsl_ir_function_dec
|
|
write_sm4_dcl_textures(tpf, resource, true);
|
|
}
|
|
|
|
- if (version->type == VKD3D_SHADER_TYPE_HULL)
|
|
- tpf_write_hs_control_point_phase(tpf);
|
|
-
|
|
- tpf_write_shader_function(tpf, entry_func);
|
|
-
|
|
- if (version->type == VKD3D_SHADER_TYPE_HULL)
|
|
- {
|
|
- tpf_write_hs_fork_phase(tpf);
|
|
- tpf_write_shader_function(tpf, ctx->patch_constant_func);
|
|
- }
|
|
+ tpf_write_program(tpf, tpf->program);
|
|
|
|
set_u32(&buffer, token_count_position, bytecode_get_size(&buffer) / sizeof(uint32_t));
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
index d751f2dc6bf..db61eec8f28 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
@@ -23,6 +23,8 @@
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
+/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */
|
|
+
|
|
static inline int char_to_int(char c)
|
|
{
|
|
if ('0' <= c && c <= '9')
|
|
@@ -805,6 +807,9 @@ struct vkd3d_shader_scan_context
|
|
|
|
struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info;
|
|
size_t combined_samplers_size;
|
|
+
|
|
+ enum vkd3d_shader_tessellator_output_primitive output_primitive;
|
|
+ enum vkd3d_shader_tessellator_partitioning partitioning;
|
|
};
|
|
|
|
static VKD3D_PRINTF_FUNC(3, 4) void vkd3d_shader_scan_error(struct vkd3d_shader_scan_context *context,
|
|
@@ -1262,6 +1267,12 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte
|
|
VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0,
|
|
instruction->declaration.structured_resource.byte_stride, false, instruction->flags);
|
|
break;
|
|
+ case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE:
|
|
+ context->output_primitive = instruction->declaration.tessellator_output_primitive;
|
|
+ break;
|
|
+ case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING:
|
|
+ context->partitioning = instruction->declaration.tessellator_partitioning;
|
|
+ break;
|
|
case VKD3DSIH_IF:
|
|
case VKD3DSIH_IFC:
|
|
cf_info = vkd3d_shader_scan_push_cf_info(context);
|
|
@@ -1502,6 +1513,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh
|
|
struct vkd3d_shader_scan_descriptor_info1 *descriptor_info1)
|
|
{
|
|
struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info;
|
|
+ struct vkd3d_shader_scan_hull_shader_tessellation_info *tessellation_info;
|
|
struct vkd3d_shader_scan_descriptor_info1 local_descriptor_info1 = {0};
|
|
struct vkd3d_shader_scan_descriptor_info *descriptor_info;
|
|
struct vkd3d_shader_scan_signature_info *signature_info;
|
|
@@ -1530,6 +1542,8 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh
|
|
descriptor_info1 = &local_descriptor_info1;
|
|
}
|
|
|
|
+ tessellation_info = vkd3d_find_struct(compile_info->next, SCAN_HULL_SHADER_TESSELLATION_INFO);
|
|
+
|
|
vkd3d_shader_scan_context_init(&context, &program->shader_version, compile_info,
|
|
descriptor_info1, combined_sampler_info, message_context);
|
|
|
|
@@ -1573,6 +1587,12 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh
|
|
if (!ret && descriptor_info)
|
|
ret = convert_descriptor_info(descriptor_info, descriptor_info1);
|
|
|
|
+ if (!ret && tessellation_info)
|
|
+ {
|
|
+ tessellation_info->output_primitive = context.output_primitive;
|
|
+ tessellation_info->partitioning = context.partitioning;
|
|
+ }
|
|
+
|
|
if (ret < 0)
|
|
{
|
|
if (combined_sampler_info)
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
index be7c0b73a22..ad04972b3fb 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
@@ -1431,6 +1431,7 @@ struct vsir_program
|
|
uint8_t diffuse_written_mask;
|
|
enum vsir_control_flow_type cf_type;
|
|
enum vsir_normalisation_level normalisation_level;
|
|
+ enum vkd3d_tessellator_domain tess_domain;
|
|
|
|
const char **block_names;
|
|
size_t block_name_count;
|
|
--
|
|
2.45.2
|
|
|