mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
1824 lines
74 KiB
Diff
1824 lines
74 KiB
Diff
From c55e0d0e093a7c99c0a45f7084d81b7477a5e025 Mon Sep 17 00:00:00 2001
|
|
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
|
Date: Sat, 14 Sep 2024 10:18:09 +1000
|
|
Subject: [PATCH] Updated vkd3d to 4c03cda3c77123a71590b872acdc216e3625c109.
|
|
|
|
---
|
|
libs/vkd3d/Makefile.in | 1 +
|
|
libs/vkd3d/include/vkd3d_shader.h | 4 +
|
|
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 258 +---------------
|
|
libs/vkd3d/libs/vkd3d-shader/dxil.c | 2 +-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 3 +-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 63 ++--
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 275 ++++++++++++++++-
|
|
libs/vkd3d/libs/vkd3d-shader/ir.c | 282 ++++++++++--------
|
|
libs/vkd3d/libs/vkd3d-shader/tpf.c | 251 +++++++++++++++-
|
|
.../libs/vkd3d-shader/vkd3d_shader_main.c | 9 +
|
|
.../libs/vkd3d-shader/vkd3d_shader_private.h | 16 +-
|
|
11 files changed, 738 insertions(+), 426 deletions(-)
|
|
|
|
diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in
|
|
index 94e4833dc9a..b073790d986 100644
|
|
--- a/libs/vkd3d/Makefile.in
|
|
+++ b/libs/vkd3d/Makefile.in
|
|
@@ -25,6 +25,7 @@ SOURCES = \
|
|
libs/vkd3d-shader/hlsl_codegen.c \
|
|
libs/vkd3d-shader/hlsl_constant_ops.c \
|
|
libs/vkd3d-shader/ir.c \
|
|
+ libs/vkd3d-shader/msl.c \
|
|
libs/vkd3d-shader/preproc.l \
|
|
libs/vkd3d-shader/preproc.y \
|
|
libs/vkd3d-shader/spirv.c \
|
|
diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
|
|
index 5737d27c0e9..46feff35138 100644
|
|
--- a/libs/vkd3d/include/vkd3d_shader.h
|
|
+++ b/libs/vkd3d/include/vkd3d_shader.h
|
|
@@ -1087,6 +1087,10 @@ enum vkd3d_shader_target_type
|
|
* Output is a raw FX section without container. \since 1.11
|
|
*/
|
|
VKD3D_SHADER_TARGET_FX,
|
|
+ /**
|
|
+ * A 'Metal Shading Language' shader. \since 1.14
|
|
+ */
|
|
+ VKD3D_SHADER_TARGET_MSL,
|
|
|
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE),
|
|
};
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
index e7d1d2420c6..b69b70c6304 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
@@ -1272,7 +1272,8 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st
|
|
sm1->end = &code[token_count];
|
|
|
|
/* Estimate instruction count to avoid reallocation in most shaders. */
|
|
- if (!vsir_program_init(program, compile_info, &version, code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
|
|
+ if (!vsir_program_init(program, compile_info, &version,
|
|
+ code_size != ~(size_t)0 ? token_count / 4u + 4 : 16, VSIR_CF_STRUCTURED))
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
|
|
vkd3d_shader_parser_init(&sm1->p, program, message_context, compile_info->source_name);
|
|
@@ -1961,112 +1962,6 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct s
|
|
write_sm1_src_register(buffer, &instr->srcs[i]);
|
|
};
|
|
|
|
-static void sm1_map_src_swizzle(struct sm1_src_register *src, unsigned int map_writemask)
|
|
-{
|
|
- src->swizzle = hlsl_map_swizzle(src->swizzle, map_writemask);
|
|
-}
|
|
-
|
|
-static void d3dbc_write_unary_op(struct d3dbc_compiler *d3dbc, enum vkd3d_sm1_opcode opcode,
|
|
- const struct hlsl_reg *dst, const struct hlsl_reg *src,
|
|
- enum vkd3d_shader_src_modifier src_mod, enum vkd3d_shader_dst_modifier dst_mod)
|
|
-{
|
|
- struct sm1_instruction instr =
|
|
- {
|
|
- .opcode = opcode,
|
|
-
|
|
- .dst.type = VKD3DSPR_TEMP,
|
|
- .dst.mod = dst_mod,
|
|
- .dst.writemask = dst->writemask,
|
|
- .dst.reg = dst->id,
|
|
- .has_dst = 1,
|
|
-
|
|
- .srcs[0].type = VKD3DSPR_TEMP,
|
|
- .srcs[0].swizzle = hlsl_swizzle_from_writemask(src->writemask),
|
|
- .srcs[0].reg = src->id,
|
|
- .srcs[0].mod = src_mod,
|
|
- .src_count = 1,
|
|
- };
|
|
-
|
|
- sm1_map_src_swizzle(&instr.srcs[0], instr.dst.writemask);
|
|
- d3dbc_write_instruction(d3dbc, &instr);
|
|
-}
|
|
-
|
|
-static void d3dbc_write_cast(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr)
|
|
-{
|
|
- struct hlsl_ir_expr *expr = hlsl_ir_expr(instr);
|
|
- const struct hlsl_ir_node *arg1 = expr->operands[0].node;
|
|
- const struct hlsl_type *dst_type = expr->node.data_type;
|
|
- const struct hlsl_type *src_type = arg1->data_type;
|
|
- struct hlsl_ctx *ctx = d3dbc->ctx;
|
|
-
|
|
- /* Narrowing casts were already lowered. */
|
|
- VKD3D_ASSERT(src_type->dimx == dst_type->dimx);
|
|
-
|
|
- switch (dst_type->e.numeric.type)
|
|
- {
|
|
- case HLSL_TYPE_HALF:
|
|
- case HLSL_TYPE_FLOAT:
|
|
- switch (src_type->e.numeric.type)
|
|
- {
|
|
- case HLSL_TYPE_INT:
|
|
- case HLSL_TYPE_UINT:
|
|
- case HLSL_TYPE_BOOL:
|
|
- /* Integrals are internally represented as floats, so no change is necessary.*/
|
|
- case HLSL_TYPE_HALF:
|
|
- case HLSL_TYPE_FLOAT:
|
|
- d3dbc_write_unary_op(d3dbc, VKD3D_SM1_OP_MOV, &instr->reg, &arg1->reg, 0, 0);
|
|
- break;
|
|
-
|
|
- case HLSL_TYPE_DOUBLE:
|
|
- hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to float.");
|
|
- break;
|
|
-
|
|
- default:
|
|
- vkd3d_unreachable();
|
|
- }
|
|
- break;
|
|
-
|
|
- case HLSL_TYPE_INT:
|
|
- case HLSL_TYPE_UINT:
|
|
- switch(src_type->e.numeric.type)
|
|
- {
|
|
- case HLSL_TYPE_HALF:
|
|
- case HLSL_TYPE_FLOAT:
|
|
- /* A compilation pass turns these into FLOOR+REINTERPRET, so we should not
|
|
- * reach this case unless we are missing something. */
|
|
- hlsl_fixme(ctx, &instr->loc, "Unlowered SM1 cast from float to integer.");
|
|
- break;
|
|
- case HLSL_TYPE_INT:
|
|
- case HLSL_TYPE_UINT:
|
|
- d3dbc_write_unary_op(d3dbc, VKD3D_SM1_OP_MOV, &instr->reg, &arg1->reg, 0, 0);
|
|
- break;
|
|
-
|
|
- 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;
|
|
-
|
|
- default:
|
|
- vkd3d_unreachable();
|
|
- }
|
|
- break;
|
|
-
|
|
- case HLSL_TYPE_DOUBLE:
|
|
- hlsl_fixme(ctx, &instr->loc, "SM1 cast to double.");
|
|
- break;
|
|
-
|
|
- case HLSL_TYPE_BOOL:
|
|
- /* Casts to bool should have already been lowered. */
|
|
- default:
|
|
- hlsl_fixme(ctx, &expr->node.loc, "SM1 cast from %s to %s.",
|
|
- debug_hlsl_type(ctx, src_type), debug_hlsl_type(ctx, dst_type));
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir(
|
|
struct d3dbc_compiler *d3dbc, enum vkd3d_shader_opcode vkd3d_opcode)
|
|
{
|
|
@@ -2308,6 +2203,9 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str
|
|
case VKD3DSIH_MUL:
|
|
case VKD3DSIH_SINCOS:
|
|
case VKD3DSIH_SLT:
|
|
+ case VKD3DSIH_TEX:
|
|
+ case VKD3DSIH_TEXKILL:
|
|
+ case VKD3DSIH_TEXLDD:
|
|
d3dbc_write_vsir_simple_instruction(d3dbc, ins);
|
|
break;
|
|
|
|
@@ -2366,8 +2264,8 @@ static void d3dbc_write_semantic_dcl(struct d3dbc_compiler *d3dbc,
|
|
put_u32(buffer, token);
|
|
|
|
token = (1u << 31);
|
|
- token |= usage << D3DSP_DCL_USAGE_SHIFT;
|
|
- token |= usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT;
|
|
+ token |= usage << VKD3D_SM1_DCL_USAGE_SHIFT;
|
|
+ token |= usage_idx << VKD3D_SM1_DCL_USAGE_INDEX_SHIFT;
|
|
put_u32(buffer, token);
|
|
|
|
reg.writemask = element->mask;
|
|
@@ -2401,36 +2299,6 @@ static void d3dbc_write_semantic_dcls(struct d3dbc_compiler *d3dbc)
|
|
}
|
|
}
|
|
|
|
-static void d3dbc_write_expr(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr)
|
|
-{
|
|
- struct hlsl_ir_expr *expr = hlsl_ir_expr(instr);
|
|
- struct hlsl_ir_node *arg1 = expr->operands[0].node;
|
|
- struct hlsl_ctx *ctx = d3dbc->ctx;
|
|
-
|
|
- VKD3D_ASSERT(instr->reg.allocated);
|
|
-
|
|
- if (expr->op == HLSL_OP1_REINTERPRET)
|
|
- {
|
|
- d3dbc_write_unary_op(d3dbc, VKD3D_SM1_OP_MOV, &instr->reg, &arg1->reg, 0, 0);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (expr->op == HLSL_OP1_CAST)
|
|
- {
|
|
- d3dbc_write_cast(d3dbc, instr);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (instr->data_type->e.numeric.type != HLSL_TYPE_FLOAT)
|
|
- {
|
|
- /* These need to be lowered. */
|
|
- hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression.");
|
|
- return;
|
|
- }
|
|
-
|
|
- hlsl_fixme(ctx, &instr->loc, "SM1 \"%s\" expression.", debug_hlsl_expr_op(expr->op));
|
|
-}
|
|
-
|
|
static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_block *block);
|
|
|
|
static void d3dbc_write_if(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr)
|
|
@@ -2473,106 +2341,6 @@ static void d3dbc_write_if(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_no
|
|
d3dbc_write_instruction(d3dbc, &sm1_endif);
|
|
}
|
|
|
|
-static void d3dbc_write_jump(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr)
|
|
-{
|
|
- const struct hlsl_ir_jump *jump = hlsl_ir_jump(instr);
|
|
-
|
|
- switch (jump->type)
|
|
- {
|
|
- case HLSL_IR_JUMP_DISCARD_NEG:
|
|
- {
|
|
- struct hlsl_reg *reg = &jump->condition.node->reg;
|
|
-
|
|
- struct sm1_instruction sm1_instr =
|
|
- {
|
|
- .opcode = VKD3D_SM1_OP_TEXKILL,
|
|
-
|
|
- .dst.type = VKD3DSPR_TEMP,
|
|
- .dst.reg = reg->id,
|
|
- .dst.writemask = reg->writemask,
|
|
- .has_dst = 1,
|
|
- };
|
|
-
|
|
- d3dbc_write_instruction(d3dbc, &sm1_instr);
|
|
- break;
|
|
- }
|
|
-
|
|
- default:
|
|
- hlsl_fixme(d3dbc->ctx, &jump->node.loc, "Jump type %s.", hlsl_jump_type_to_string(jump->type));
|
|
- }
|
|
-}
|
|
-
|
|
-static void d3dbc_write_resource_load(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr)
|
|
-{
|
|
- const struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr);
|
|
- struct hlsl_ir_node *coords = load->coords.node;
|
|
- struct hlsl_ir_node *ddx = load->ddx.node;
|
|
- struct hlsl_ir_node *ddy = load->ddy.node;
|
|
- unsigned int sampler_offset, reg_id;
|
|
- struct hlsl_ctx *ctx = d3dbc->ctx;
|
|
- struct sm1_instruction sm1_instr;
|
|
-
|
|
- sampler_offset = hlsl_offset_from_deref_safe(ctx, &load->resource);
|
|
- reg_id = load->resource.var->regs[HLSL_REGSET_SAMPLERS].index + sampler_offset;
|
|
-
|
|
- sm1_instr = (struct sm1_instruction)
|
|
- {
|
|
- .dst.type = VKD3DSPR_TEMP,
|
|
- .dst.reg = instr->reg.id,
|
|
- .dst.writemask = instr->reg.writemask,
|
|
- .has_dst = 1,
|
|
-
|
|
- .srcs[0].type = VKD3DSPR_TEMP,
|
|
- .srcs[0].reg = coords->reg.id,
|
|
- .srcs[0].swizzle = hlsl_swizzle_from_writemask(coords->reg.writemask),
|
|
-
|
|
- .srcs[1].type = VKD3DSPR_COMBINED_SAMPLER,
|
|
- .srcs[1].reg = reg_id,
|
|
- .srcs[1].swizzle = hlsl_swizzle_from_writemask(VKD3DSP_WRITEMASK_ALL),
|
|
-
|
|
- .src_count = 2,
|
|
- };
|
|
-
|
|
- switch (load->load_type)
|
|
- {
|
|
- case HLSL_RESOURCE_SAMPLE:
|
|
- sm1_instr.opcode = VKD3D_SM1_OP_TEX;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_PROJ:
|
|
- sm1_instr.opcode = VKD3D_SM1_OP_TEX;
|
|
- sm1_instr.opcode |= VKD3DSI_TEXLD_PROJECT << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_LOD_BIAS:
|
|
- sm1_instr.opcode = VKD3D_SM1_OP_TEX;
|
|
- sm1_instr.opcode |= VKD3DSI_TEXLD_BIAS << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT;
|
|
- break;
|
|
-
|
|
- case HLSL_RESOURCE_SAMPLE_GRAD:
|
|
- sm1_instr.opcode = VKD3D_SM1_OP_TEXLDD;
|
|
-
|
|
- sm1_instr.srcs[2].type = VKD3DSPR_TEMP;
|
|
- sm1_instr.srcs[2].reg = ddx->reg.id;
|
|
- sm1_instr.srcs[2].swizzle = hlsl_swizzle_from_writemask(ddx->reg.writemask);
|
|
-
|
|
- sm1_instr.srcs[3].type = VKD3DSPR_TEMP;
|
|
- sm1_instr.srcs[3].reg = ddy->reg.id;
|
|
- sm1_instr.srcs[3].swizzle = hlsl_swizzle_from_writemask(ddy->reg.writemask);
|
|
-
|
|
- sm1_instr.src_count += 2;
|
|
- break;
|
|
-
|
|
- default:
|
|
- hlsl_fixme(ctx, &instr->loc, "Resource load type %u.", load->load_type);
|
|
- return;
|
|
- }
|
|
-
|
|
- VKD3D_ASSERT(instr->reg.allocated);
|
|
-
|
|
- d3dbc_write_instruction(d3dbc, &sm1_instr);
|
|
-}
|
|
-
|
|
static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_block *block)
|
|
{
|
|
struct vkd3d_shader_instruction *vsir_instr;
|
|
@@ -2596,10 +2364,6 @@ static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_bl
|
|
case HLSL_IR_CALL:
|
|
vkd3d_unreachable();
|
|
|
|
- case HLSL_IR_EXPR:
|
|
- d3dbc_write_expr(d3dbc, instr);
|
|
- break;
|
|
-
|
|
case HLSL_IR_IF:
|
|
if (hlsl_version_ge(ctx, 2, 1))
|
|
d3dbc_write_if(d3dbc, instr);
|
|
@@ -2607,14 +2371,6 @@ static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_bl
|
|
hlsl_fixme(ctx, &instr->loc, "Flatten \"if\" conditionals branches.");
|
|
break;
|
|
|
|
- case HLSL_IR_JUMP:
|
|
- d3dbc_write_jump(d3dbc, instr);
|
|
- break;
|
|
-
|
|
- case HLSL_IR_RESOURCE_LOAD:
|
|
- d3dbc_write_resource_load(d3dbc, instr);
|
|
- break;
|
|
-
|
|
case HLSL_IR_VSIR_INSTRUCTION_REF:
|
|
vsir_instr_idx = hlsl_ir_vsir_instruction_ref(instr)->vsir_instr_idx;
|
|
vsir_instr = &d3dbc->program->instructions.elements[vsir_instr_idx];
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
index 1c62a305d30..ee78b6251f9 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
@@ -10303,7 +10303,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro
|
|
|
|
/* Estimate instruction count to avoid reallocation in most shaders. */
|
|
count = max(token_count, 400) - 400;
|
|
- if (!vsir_program_init(program, compile_info, &version, (count + (count >> 2)) / 2u + 10))
|
|
+ if (!vsir_program_init(program, compile_info, &version, (count + (count >> 2)) / 2u + 10, VSIR_CF_BLOCKS))
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
vkd3d_shader_parser_init(&sm6->p, program, message_context, compile_info->source_name);
|
|
sm6->ptr = &sm6->start[1];
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
index bdd0e401770..eece693b48c 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
|
|
@@ -603,6 +602,8 @@ struct hlsl_ir_function_decl
|
|
unsigned int attr_count;
|
|
const struct hlsl_attribute *const *attrs;
|
|
|
|
+ bool early_depth_test;
|
|
+
|
|
/* Synthetic boolean variable marking whether a return statement has been
|
|
* executed. Needed to deal with return statements in non-uniform control
|
|
* flow, since some backends can't handle them. */
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
index eabf072befb..60e196c63cc 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
@@ -1673,25 +1673,36 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct hlsl_block *bl
|
|
return expr;
|
|
}
|
|
|
|
-static void check_integer_type(struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr)
|
|
+static bool type_is_integer(enum hlsl_base_type type)
|
|
{
|
|
- const struct hlsl_type *type = instr->data_type;
|
|
- struct vkd3d_string_buffer *string;
|
|
-
|
|
- switch (type->e.numeric.type)
|
|
+ switch (type)
|
|
{
|
|
case HLSL_TYPE_BOOL:
|
|
case HLSL_TYPE_INT:
|
|
case HLSL_TYPE_UINT:
|
|
- break;
|
|
+ return true;
|
|
|
|
- default:
|
|
- if ((string = hlsl_type_to_string(ctx, type)))
|
|
- hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
- "Expression type '%s' is not integer.", string->buffer);
|
|
- hlsl_release_string_buffer(ctx, string);
|
|
- break;
|
|
+ case HLSL_TYPE_DOUBLE:
|
|
+ case HLSL_TYPE_FLOAT:
|
|
+ case HLSL_TYPE_HALF:
|
|
+ return false;
|
|
}
|
|
+
|
|
+ vkd3d_unreachable();
|
|
+}
|
|
+
|
|
+static void check_integer_type(struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr)
|
|
+{
|
|
+ const struct hlsl_type *type = instr->data_type;
|
|
+ struct vkd3d_string_buffer *string;
|
|
+
|
|
+ if (type_is_integer(type->e.numeric.type))
|
|
+ return;
|
|
+
|
|
+ if ((string = hlsl_type_to_string(ctx, type)))
|
|
+ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
|
+ "Expression type '%s' is not integer.", string->buffer);
|
|
+ hlsl_release_string_buffer(ctx, string);
|
|
}
|
|
|
|
static struct hlsl_ir_node *add_unary_arithmetic_expr(struct hlsl_ctx *ctx, struct hlsl_block *block,
|
|
@@ -3033,7 +3044,7 @@ static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx,
|
|
{
|
|
struct hlsl_type *type = arg->data_type;
|
|
|
|
- if (type->e.numeric.type == HLSL_TYPE_FLOAT || type->e.numeric.type == HLSL_TYPE_HALF)
|
|
+ if (!type_is_integer(type->e.numeric.type))
|
|
return arg;
|
|
|
|
type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy);
|
|
@@ -3121,14 +3132,12 @@ static bool elementwise_intrinsic_convert_args(struct hlsl_ctx *ctx,
|
|
static bool elementwise_intrinsic_float_convert_args(struct hlsl_ctx *ctx,
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
|
{
|
|
- enum hlsl_base_type base_type;
|
|
struct hlsl_type *type;
|
|
|
|
if (!(type = elementwise_intrinsic_get_common_type(ctx, params, loc)))
|
|
return false;
|
|
-
|
|
- base_type = type->e.numeric.type == HLSL_TYPE_HALF ? HLSL_TYPE_HALF : HLSL_TYPE_FLOAT;
|
|
- type = hlsl_get_numeric_type(ctx, type->class, base_type, type->dimx, type->dimy);
|
|
+ if (type_is_integer(type->e.numeric.type))
|
|
+ type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy);
|
|
|
|
return convert_args(ctx, params, type, loc);
|
|
}
|
|
@@ -3156,6 +3165,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx,
|
|
const struct parse_initializer *params, const struct vkd3d_shader_location *loc, bool asin_mode)
|
|
{
|
|
struct hlsl_ir_function_decl *func;
|
|
+ struct hlsl_ir_node *arg;
|
|
struct hlsl_type *type;
|
|
char *body;
|
|
|
|
@@ -3179,8 +3189,9 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx,
|
|
|
|
const char *fn_name = asin_mode ? fn_name_asin : fn_name_acos;
|
|
|
|
- type = params->args[0]->data_type;
|
|
- type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy);
|
|
+ if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
|
|
+ return false;
|
|
+ type = arg->data_type;
|
|
|
|
if (!(body = hlsl_sprintf_alloc(ctx, template,
|
|
type->name, fn_name, type->name,
|
|
@@ -3552,9 +3563,8 @@ static bool intrinsic_cross(struct hlsl_ctx *ctx,
|
|
struct hlsl_type *cast_type;
|
|
enum hlsl_base_type base;
|
|
|
|
- if (arg1->data_type->e.numeric.type == HLSL_TYPE_HALF && arg2->data_type->e.numeric.type == HLSL_TYPE_HALF)
|
|
- base = HLSL_TYPE_HALF;
|
|
- else
|
|
+ base = expr_common_base_type(arg1->data_type->e.numeric.type, arg2->data_type->e.numeric.type);
|
|
+ if (type_is_integer(base))
|
|
base = HLSL_TYPE_FLOAT;
|
|
|
|
cast_type = hlsl_get_vector_type(ctx, base, 3);
|
|
@@ -3725,15 +3735,14 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx,
|
|
return false;
|
|
}
|
|
|
|
+ if (!(arg = intrinsic_float_convert_arg(ctx, params, arg, loc)))
|
|
+ return false;
|
|
+
|
|
dim = min(type->dimx, type->dimy);
|
|
if (dim == 1)
|
|
- {
|
|
- if (!(arg = intrinsic_float_convert_arg(ctx, params, arg, loc)))
|
|
- return false;
|
|
return hlsl_add_load_component(ctx, params->instrs, arg, 0, loc);
|
|
- }
|
|
|
|
- typename = type->e.numeric.type == HLSL_TYPE_HALF ? "half" : "float";
|
|
+ typename = hlsl_get_scalar_type(ctx, arg->data_type->e.numeric.type)->name;
|
|
template = templates[dim];
|
|
|
|
switch (dim)
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
index 2d80b524913..93f19360953 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
@@ -6027,7 +6027,7 @@ static void parse_patchconstantfunc_attribute(struct hlsl_ctx *ctx, const struct
|
|
"Patch constant function \"%s\" is not defined.", name);
|
|
}
|
|
|
|
-static void parse_entry_function_attributes(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *entry_func)
|
|
+static void parse_entry_function_attributes(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
|
|
{
|
|
const struct hlsl_profile_info *profile = ctx->profile;
|
|
unsigned int i;
|
|
@@ -6049,6 +6049,8 @@ static void parse_entry_function_attributes(struct hlsl_ctx *ctx, const struct h
|
|
parse_partitioning_attribute(ctx, attr);
|
|
else if (!strcmp(attr->name, "patchconstantfunc") && profile->type == VKD3D_SHADER_TYPE_HULL)
|
|
parse_patchconstantfunc_attribute(ctx, attr);
|
|
+ else if (!strcmp(attr->name, "earlydepthstencil") && profile->type == VKD3D_SHADER_TYPE_PIXEL)
|
|
+ entry_func->early_depth_test = true;
|
|
else
|
|
hlsl_warning(ctx, &entry_func->attrs[i]->loc, VKD3D_SHADER_WARNING_HLSL_UNKNOWN_ATTRIBUTE,
|
|
"Ignoring unknown attribute \"%s\".", entry_func->attrs[i]->name);
|
|
@@ -6684,15 +6686,110 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi
|
|
hlsl_replace_node(instr, vsir_instr);
|
|
}
|
|
|
|
+static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, struct hlsl_ir_expr *expr)
|
|
+{
|
|
+ const struct hlsl_type *src_type, *dst_type;
|
|
+ const struct hlsl_ir_node *arg1, *instr;
|
|
+
|
|
+ arg1 = expr->operands[0].node;
|
|
+ src_type = arg1->data_type;
|
|
+ instr = &expr->node;
|
|
+ dst_type = instr->data_type;
|
|
+
|
|
+ /* Narrowing casts were already lowered. */
|
|
+ VKD3D_ASSERT(src_type->dimx == dst_type->dimx);
|
|
+
|
|
+ switch (dst_type->e.numeric.type)
|
|
+ {
|
|
+ case HLSL_TYPE_HALF:
|
|
+ case HLSL_TYPE_FLOAT:
|
|
+ switch (src_type->e.numeric.type)
|
|
+ {
|
|
+ case HLSL_TYPE_INT:
|
|
+ case HLSL_TYPE_UINT:
|
|
+ case HLSL_TYPE_BOOL:
|
|
+ /* Integrals are internally represented as floats, so no change is necessary.*/
|
|
+ case HLSL_TYPE_HALF:
|
|
+ case HLSL_TYPE_FLOAT:
|
|
+ sm1_generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true);
|
|
+ return true;
|
|
+
|
|
+ case HLSL_TYPE_DOUBLE:
|
|
+ hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to float.");
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ vkd3d_unreachable();
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case HLSL_TYPE_INT:
|
|
+ case HLSL_TYPE_UINT:
|
|
+ switch(src_type->e.numeric.type)
|
|
+ {
|
|
+ case HLSL_TYPE_HALF:
|
|
+ case HLSL_TYPE_FLOAT:
|
|
+ /* A compilation pass turns these into FLOOR+REINTERPRET, so we should not
|
|
+ * reach this case unless we are missing something. */
|
|
+ hlsl_fixme(ctx, &instr->loc, "Unlowered SM1 cast from float to integer.");
|
|
+ break;
|
|
+
|
|
+ case HLSL_TYPE_INT:
|
|
+ case HLSL_TYPE_UINT:
|
|
+ sm1_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;
|
|
+
|
|
+ default:
|
|
+ vkd3d_unreachable();
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case HLSL_TYPE_DOUBLE:
|
|
+ hlsl_fixme(ctx, &instr->loc, "SM1 cast to double.");
|
|
+ break;
|
|
+
|
|
+ case HLSL_TYPE_BOOL:
|
|
+ /* Casts to bool should have already been lowered. */
|
|
+ default:
|
|
+ hlsl_fixme(ctx, &expr->node.loc, "SM1 cast from %s to %s.",
|
|
+ debug_hlsl_type(ctx, src_type), debug_hlsl_type(ctx, dst_type));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
struct hlsl_ir_expr *expr)
|
|
{
|
|
+ struct hlsl_ir_node *instr = &expr->node;
|
|
+
|
|
+ if (expr->op != HLSL_OP1_REINTERPRET && expr->op != HLSL_OP1_CAST
|
|
+ && instr->data_type->e.numeric.type != HLSL_TYPE_FLOAT)
|
|
+ {
|
|
+ /* These need to be lowered. */
|
|
+ hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression.");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
switch (expr->op)
|
|
{
|
|
case HLSL_OP1_ABS:
|
|
sm1_generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_ABS, 0, 0, true);
|
|
break;
|
|
|
|
+ case HLSL_OP1_CAST:
|
|
+ return sm1_generate_vsir_instr_expr_cast(ctx, program, expr);
|
|
+
|
|
case HLSL_OP1_COS_REDUCED:
|
|
VKD3D_ASSERT(expr->node.reg.writemask == VKD3DSP_WRITEMASK_0);
|
|
sm1_generate_vsir_instr_expr_sincos(ctx, program, expr);
|
|
@@ -6722,6 +6819,10 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr
|
|
sm1_generate_vsir_instr_expr_per_component_instr_op(ctx, program, expr, VKD3DSIH_RCP);
|
|
break;
|
|
|
|
+ case HLSL_OP1_REINTERPRET:
|
|
+ sm1_generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true);
|
|
+ break;
|
|
+
|
|
case HLSL_OP1_RSQ:
|
|
sm1_generate_vsir_instr_expr_per_component_instr_op(ctx, program, expr, VKD3DSIH_RSQ);
|
|
break;
|
|
@@ -6858,29 +6959,52 @@ static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx,
|
|
unsigned int writemask;
|
|
struct hlsl_reg reg;
|
|
|
|
- reg = hlsl_reg_from_deref(ctx, deref);
|
|
- register_index = reg.id;
|
|
- writemask = reg.writemask;
|
|
+ if (hlsl_type_is_resource(deref->var->data_type))
|
|
+ {
|
|
+ unsigned int sampler_offset;
|
|
+
|
|
+ type = VKD3DSPR_COMBINED_SAMPLER;
|
|
|
|
- if (deref->var->is_uniform)
|
|
+ sampler_offset = hlsl_offset_from_deref_safe(ctx, deref);
|
|
+ register_index = deref->var->regs[HLSL_REGSET_SAMPLERS].index + sampler_offset;
|
|
+ writemask = VKD3DSP_WRITEMASK_ALL;
|
|
+ }
|
|
+ else if (deref->var->is_uniform)
|
|
{
|
|
- VKD3D_ASSERT(reg.allocated);
|
|
type = VKD3DSPR_CONST;
|
|
+
|
|
+ reg = hlsl_reg_from_deref(ctx, deref);
|
|
+ register_index = reg.id;
|
|
+ writemask = reg.writemask;
|
|
+ VKD3D_ASSERT(reg.allocated);
|
|
}
|
|
else if (deref->var->is_input_semantic)
|
|
{
|
|
version.major = ctx->profile->major_version;
|
|
version.minor = ctx->profile->minor_version;
|
|
version.type = ctx->profile->type;
|
|
- if (!hlsl_sm1_register_from_semantic(&version, deref->var->semantic.name,
|
|
+ if (hlsl_sm1_register_from_semantic(&version, deref->var->semantic.name,
|
|
deref->var->semantic.index, false, &type, ®ister_index))
|
|
{
|
|
- VKD3D_ASSERT(reg.allocated);
|
|
+ writemask = (1 << deref->var->data_type->dimx) - 1;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
type = VKD3DSPR_INPUT;
|
|
+
|
|
+ reg = hlsl_reg_from_deref(ctx, deref);
|
|
register_index = reg.id;
|
|
+ writemask = reg.writemask;
|
|
+ VKD3D_ASSERT(reg.allocated);
|
|
}
|
|
- else
|
|
- writemask = (1 << deref->var->data_type->dimx) - 1;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ type = VKD3DSPR_TEMP;
|
|
+
|
|
+ reg = hlsl_reg_from_deref(ctx, deref);
|
|
+ register_index = reg.id;
|
|
+ writemask = reg.writemask;
|
|
}
|
|
|
|
vsir_register_init(&src_param->reg, type, VKD3D_DATA_FLOAT, 1);
|
|
@@ -6924,6 +7048,91 @@ static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr
|
|
hlsl_replace_node(instr, vsir_instr);
|
|
}
|
|
|
|
+static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, struct hlsl_ir_resource_load *load)
|
|
+{
|
|
+ struct vkd3d_shader_instruction_array *instructions = &program->instructions;
|
|
+ struct hlsl_ir_node *coords = load->coords.node;
|
|
+ struct hlsl_ir_node *ddx = load->ddx.node;
|
|
+ struct hlsl_ir_node *ddy = load->ddy.node;
|
|
+ struct hlsl_ir_node *instr = &load->node;
|
|
+ struct vkd3d_shader_dst_param *dst_param;
|
|
+ struct vkd3d_shader_src_param *src_param;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ struct hlsl_ir_node *vsir_instr;
|
|
+ enum vkd3d_shader_opcode opcode;
|
|
+ unsigned int src_count = 2;
|
|
+ uint32_t flags = 0;
|
|
+
|
|
+ VKD3D_ASSERT(instr->reg.allocated);
|
|
+
|
|
+ switch (load->load_type)
|
|
+ {
|
|
+ case HLSL_RESOURCE_SAMPLE:
|
|
+ opcode = VKD3DSIH_TEX;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_PROJ:
|
|
+ opcode = VKD3DSIH_TEX;
|
|
+ flags |= VKD3DSI_TEXLD_PROJECT;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_LOD_BIAS:
|
|
+ opcode = VKD3DSIH_TEX;
|
|
+ flags |= VKD3DSI_TEXLD_BIAS;
|
|
+ break;
|
|
+
|
|
+ case HLSL_RESOURCE_SAMPLE_GRAD:
|
|
+ opcode = VKD3DSIH_TEXLDD;
|
|
+ src_count += 2;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ hlsl_fixme(ctx, &instr->loc, "Resource load type %u.", load->load_type);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, src_count)))
|
|
+ return;
|
|
+ ins->flags = flags;
|
|
+
|
|
+ dst_param = &ins->dst[0];
|
|
+ vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1);
|
|
+ dst_param->reg.idx[0].offset = instr->reg.id;
|
|
+ dst_param->write_mask = instr->reg.writemask;
|
|
+
|
|
+ src_param = &ins->src[0];
|
|
+ vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1);
|
|
+ src_param->reg.idx[0].offset = coords->reg.id;
|
|
+ src_param->swizzle = sm1_generate_vsir_get_src_swizzle(coords->reg.writemask, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ sm1_generate_vsir_init_src_param_from_deref(ctx, &ins->src[1], &load->resource,
|
|
+ VKD3DSP_WRITEMASK_ALL, &ins->location);
|
|
+
|
|
+ if (load->load_type == HLSL_RESOURCE_SAMPLE_GRAD)
|
|
+ {
|
|
+ src_param = &ins->src[2];
|
|
+ vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1);
|
|
+ src_param->reg.idx[0].offset = ddx->reg.id;
|
|
+ src_param->swizzle = sm1_generate_vsir_get_src_swizzle(ddx->reg.writemask, VKD3DSP_WRITEMASK_ALL);
|
|
+
|
|
+ src_param = &ins->src[3];
|
|
+ vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1);
|
|
+ src_param->reg.idx[0].offset = ddy->reg.id;
|
|
+ src_param->swizzle = sm1_generate_vsir_get_src_swizzle(ddy->reg.writemask, VKD3DSP_WRITEMASK_ALL);
|
|
+ }
|
|
+
|
|
+ if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, instructions->count - 1, instr->data_type,
|
|
+ &instr->reg, &instr->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 sm1_generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, struct vsir_program *program,
|
|
struct hlsl_ir_swizzle *swizzle_instr)
|
|
{
|
|
@@ -6996,6 +7205,42 @@ static void sm1_generate_vsir_instr_store(struct hlsl_ctx *ctx, struct vsir_prog
|
|
hlsl_replace_node(instr, vsir_instr);
|
|
}
|
|
|
|
+static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx,
|
|
+ struct vsir_program *program, struct hlsl_ir_jump *jump)
|
|
+{
|
|
+ struct vkd3d_shader_instruction_array *instructions = &program->instructions;
|
|
+ struct hlsl_ir_node *condition = jump->condition.node;
|
|
+ struct hlsl_ir_node *instr = &jump->node;
|
|
+ struct vkd3d_shader_dst_param *dst_param;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ struct hlsl_ir_node *vsir_instr;
|
|
+
|
|
+ if (jump->type == HLSL_IR_JUMP_DISCARD_NEG)
|
|
+ {
|
|
+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_TEXKILL, 1, 0)))
|
|
+ return;
|
|
+
|
|
+ dst_param = &ins->dst[0];
|
|
+ vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1);
|
|
+ dst_param->reg.idx[0].offset = condition->reg.id;
|
|
+ dst_param->write_mask = condition->reg.writemask;
|
|
+
|
|
+ if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx,
|
|
+ instructions->count - 1, instr->data_type, NULL, &instr->loc)))
|
|
+ {
|
|
+ ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ list_add_before(&instr->entry, &vsir_instr->entry);
|
|
+ hlsl_replace_node(instr, vsir_instr);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ hlsl_fixme(ctx, &instr->loc, "Jump type %s.", hlsl_jump_type_to_string(jump->type));
|
|
+ }
|
|
+}
|
|
+
|
|
static bool sm1_generate_vsir_instr(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
|
|
{
|
|
struct vsir_program *program = context;
|
|
@@ -7009,10 +7254,18 @@ static bool sm1_generate_vsir_instr(struct hlsl_ctx *ctx, struct hlsl_ir_node *i
|
|
case HLSL_IR_EXPR:
|
|
return sm1_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr));
|
|
|
|
+ case HLSL_IR_JUMP:
|
|
+ sm1_generate_vsir_instr_jump(ctx, program, hlsl_ir_jump(instr));
|
|
+ return true;
|
|
+
|
|
case HLSL_IR_LOAD:
|
|
sm1_generate_vsir_instr_load(ctx, program, hlsl_ir_load(instr));
|
|
return true;
|
|
|
|
+ case HLSL_IR_RESOURCE_LOAD:
|
|
+ sm1_generate_vsir_instr_resource_load(ctx, program, hlsl_ir_resource_load(instr));
|
|
+ return true;
|
|
+
|
|
case HLSL_IR_STORE:
|
|
sm1_generate_vsir_instr_store(ctx, program, hlsl_ir_store(instr));
|
|
return true;
|
|
@@ -7041,7 +7294,7 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
|
|
version.major = ctx->profile->major_version;
|
|
version.minor = ctx->profile->minor_version;
|
|
version.type = ctx->profile->type;
|
|
- if (!vsir_program_init(program, NULL, &version, 0))
|
|
+ if (!vsir_program_init(program, NULL, &version, 0, VSIR_CF_STRUCTURED))
|
|
{
|
|
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
|
|
return;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
index 6cef85fdc84..4b79a058b6f 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
@@ -74,7 +74,7 @@ static int convert_parameter_info(const struct vkd3d_shader_compile_info *compil
|
|
}
|
|
|
|
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
|
|
- const struct vkd3d_shader_version *version, unsigned int reserve)
|
|
+ const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type)
|
|
{
|
|
memset(program, 0, sizeof(*program));
|
|
|
|
@@ -96,6 +96,7 @@ bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_c
|
|
}
|
|
|
|
program->shader_version = *version;
|
|
+ program->cf_type = cf_type;
|
|
return shader_instruction_array_init(&program->instructions, reserve);
|
|
}
|
|
|
|
@@ -2803,6 +2804,8 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi
|
|
struct cf_flattener flattener = {.program = program};
|
|
enum vkd3d_result result;
|
|
|
|
+ VKD3D_ASSERT(program->cf_type == VSIR_CF_STRUCTURED);
|
|
+
|
|
if ((result = cf_flattener_iterate_instruction_array(&flattener, message_context)) >= 0)
|
|
{
|
|
vkd3d_free(program->instructions.elements);
|
|
@@ -2810,6 +2813,7 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi
|
|
program->instructions.capacity = flattener.instruction_capacity;
|
|
program->instructions.count = flattener.instruction_count;
|
|
program->block_count = flattener.block_id;
|
|
+ program->cf_type = VSIR_CF_BLOCKS;
|
|
}
|
|
else
|
|
{
|
|
@@ -2877,6 +2881,8 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs
|
|
struct vkd3d_shader_instruction *instructions = NULL;
|
|
struct lower_switch_to_if_ladder_block_mapping *block_map = NULL;
|
|
|
|
+ VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
|
|
+
|
|
if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count))
|
|
goto fail;
|
|
|
|
@@ -3069,6 +3075,8 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_
|
|
struct ssas_to_temps_alloc alloc = {0};
|
|
unsigned int current_label = 0;
|
|
|
|
+ VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
|
|
+
|
|
if (!(block_info = vkd3d_calloc(program->block_count, sizeof(*block_info))))
|
|
{
|
|
ERR("Failed to allocate block info array.\n");
|
|
@@ -5289,6 +5297,8 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program,
|
|
enum vkd3d_result ret;
|
|
size_t i;
|
|
|
|
+ VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
|
|
+
|
|
target.jump_target_temp_idx = program->temp_count;
|
|
target.temp_count = program->temp_count + 1;
|
|
|
|
@@ -5336,6 +5346,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program,
|
|
program->instructions.capacity = target.ins_capacity;
|
|
program->instructions.count = target.ins_count;
|
|
program->temp_count = target.temp_count;
|
|
+ program->cf_type = VSIR_CF_STRUCTURED;
|
|
|
|
return VKD3D_OK;
|
|
|
|
@@ -5469,6 +5480,8 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru
|
|
enum vkd3d_result ret;
|
|
size_t i;
|
|
|
|
+ VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
|
|
+
|
|
for (i = 0; i < program->instructions.count;)
|
|
{
|
|
struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
|
|
@@ -5701,12 +5714,6 @@ struct validation_context
|
|
enum vkd3d_result status;
|
|
bool dcl_temps_found;
|
|
enum vkd3d_shader_opcode phase;
|
|
- enum cf_type
|
|
- {
|
|
- CF_TYPE_UNKNOWN = 0,
|
|
- CF_TYPE_STRUCTURED,
|
|
- CF_TYPE_BLOCKS,
|
|
- } cf_type;
|
|
bool inside_block;
|
|
|
|
struct validation_context_temp_data
|
|
@@ -6119,13 +6126,13 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx,
|
|
return true;
|
|
}
|
|
|
|
-static const char *name_from_cf_type(enum cf_type type)
|
|
+static const char *name_from_cf_type(enum vsir_control_flow_type type)
|
|
{
|
|
switch (type)
|
|
{
|
|
- case CF_TYPE_STRUCTURED:
|
|
+ case VSIR_CF_STRUCTURED:
|
|
return "structured";
|
|
- case CF_TYPE_BLOCKS:
|
|
+ case VSIR_CF_BLOCKS:
|
|
return "block-based";
|
|
default:
|
|
vkd3d_unreachable();
|
|
@@ -6133,15 +6140,122 @@ static const char *name_from_cf_type(enum cf_type type)
|
|
}
|
|
|
|
static void vsir_validate_cf_type(struct validation_context *ctx,
|
|
- const struct vkd3d_shader_instruction *instruction, enum cf_type expected_type)
|
|
+ const struct vkd3d_shader_instruction *instruction, enum vsir_control_flow_type expected_type)
|
|
{
|
|
- VKD3D_ASSERT(ctx->cf_type != CF_TYPE_UNKNOWN);
|
|
- VKD3D_ASSERT(expected_type != CF_TYPE_UNKNOWN);
|
|
- if (ctx->cf_type != expected_type)
|
|
+ if (ctx->program->cf_type != expected_type)
|
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.",
|
|
- instruction->opcode, name_from_cf_type(ctx->cf_type));
|
|
+ instruction->opcode, name_from_cf_type(ctx->program->cf_type));
|
|
+}
|
|
+
|
|
+static void vsir_validator_push_block(struct validation_context *ctx, enum vkd3d_shader_opcode opcode)
|
|
+{
|
|
+ if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
|
|
+ {
|
|
+ ctx->status = VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+ return;
|
|
+ }
|
|
+ ctx->blocks[ctx->depth++] = opcode;
|
|
+}
|
|
+
|
|
+static void vsir_validate_dcl_temps(struct validation_context *ctx,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ if (ctx->dcl_temps_found)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS,
|
|
+ "Duplicate DCL_TEMPS instruction.");
|
|
+ if (instruction->declaration.count > ctx->program->temp_count)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS,
|
|
+ "Invalid DCL_TEMPS count %u, expected at most %u.",
|
|
+ instruction->declaration.count, ctx->program->temp_count);
|
|
+ ctx->dcl_temps_found = true;
|
|
+}
|
|
+
|
|
+static void vsir_validate_else(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW,
|
|
+ "ELSE instruction doesn't terminate IF block.");
|
|
+ else
|
|
+ ctx->blocks[ctx->depth - 1] = VKD3DSIH_ELSE;
|
|
+}
|
|
+
|
|
+static void vsir_validate_endif(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ if (ctx->depth == 0 || (ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF
|
|
+ && ctx->blocks[ctx->depth - 1] != VKD3DSIH_ELSE))
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW,
|
|
+ "ENDIF instruction doesn't terminate IF/ELSE block.");
|
|
+ else
|
|
+ --ctx->depth;
|
|
+}
|
|
+
|
|
+static void vsir_validate_endloop(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_LOOP)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW,
|
|
+ "ENDLOOP instruction doesn't terminate LOOP block.");
|
|
+ else
|
|
+ --ctx->depth;
|
|
+}
|
|
+
|
|
+static void vsir_validate_endrep(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_REP)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW,
|
|
+ "ENDREP instruction doesn't terminate REP block.");
|
|
+ else
|
|
+ --ctx->depth;
|
|
+}
|
|
+
|
|
+static void vsir_validate_if(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ vsir_validator_push_block(ctx, VKD3DSIH_IF);
|
|
+}
|
|
+
|
|
+static void vsir_validate_ifc(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ vsir_validator_push_block(ctx, VKD3DSIH_IF);
|
|
+}
|
|
+
|
|
+static void vsir_validate_loop(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ vsir_validate_src_count(ctx, instruction, ctx->program->shader_version.major <= 3 ? 2 : 0);
|
|
+ vsir_validator_push_block(ctx, VKD3DSIH_LOOP);
|
|
}
|
|
|
|
+static void vsir_validate_rep(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
+ vsir_validator_push_block(ctx, VKD3DSIH_REP);
|
|
+}
|
|
+
|
|
+struct vsir_validator_instruction_desc
|
|
+{
|
|
+ unsigned int dst_param_count;
|
|
+ unsigned int src_param_count;
|
|
+ void (*validate)(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction);
|
|
+};
|
|
+
|
|
+static const struct vsir_validator_instruction_desc vsir_validator_instructions[] =
|
|
+{
|
|
+ [VKD3DSIH_DCL_TEMPS] = {0, 0, vsir_validate_dcl_temps},
|
|
+ [VKD3DSIH_ELSE] = {0, 0, vsir_validate_else},
|
|
+ [VKD3DSIH_ENDIF] = {0, 0, vsir_validate_endif},
|
|
+ [VKD3DSIH_ENDLOOP] = {0, 0, vsir_validate_endloop},
|
|
+ [VKD3DSIH_ENDREP] = {0, 0, vsir_validate_endrep},
|
|
+ [VKD3DSIH_IF] = {0, 1, vsir_validate_if},
|
|
+ [VKD3DSIH_IFC] = {0, 2, vsir_validate_ifc},
|
|
+ [VKD3DSIH_LOOP] = {0, ~0u, vsir_validate_loop},
|
|
+ [VKD3DSIH_REP] = {0, 1, vsir_validate_rep},
|
|
+};
|
|
+
|
|
static void vsir_validate_instruction(struct validation_context *ctx)
|
|
{
|
|
const struct vkd3d_shader_version *version = &ctx->program->shader_version;
|
|
@@ -6254,24 +6368,8 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
|
"Instruction %#x appear before any phase instruction in a hull shader.",
|
|
instruction->opcode);
|
|
|
|
- /* We support two different control flow types in shaders:
|
|
- * block-based, like DXIL and SPIR-V, and structured, like D3DBC
|
|
- * and TPF. The shader is detected as block-based when its first
|
|
- * instruction, except for NOP, DCL_* and phases, is a LABEL.
|
|
- * Currently we mandate that each shader is either purely block-based or
|
|
- * purely structured. In principle we could allow structured
|
|
- * constructs in a block, provided they are confined in a single
|
|
- * block, but need for that hasn't arisen yet, so we don't. */
|
|
- if (ctx->cf_type == CF_TYPE_UNKNOWN && instruction->opcode != VKD3DSIH_NOP
|
|
- && !vsir_instruction_is_dcl(instruction))
|
|
- {
|
|
- if (instruction->opcode == VKD3DSIH_LABEL)
|
|
- ctx->cf_type = CF_TYPE_BLOCKS;
|
|
- else
|
|
- ctx->cf_type = CF_TYPE_STRUCTURED;
|
|
- }
|
|
-
|
|
- if (ctx->cf_type == CF_TYPE_BLOCKS && !vsir_instruction_is_dcl(instruction))
|
|
+ if (ctx->program->cf_type == VSIR_CF_BLOCKS && !vsir_instruction_is_dcl(instruction)
|
|
+ && instruction->opcode != VKD3DSIH_NOP)
|
|
{
|
|
switch (instruction->opcode)
|
|
{
|
|
@@ -6300,98 +6398,26 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
|
}
|
|
}
|
|
|
|
- switch (instruction->opcode)
|
|
+ if (instruction->opcode < ARRAY_SIZE(vsir_validator_instructions))
|
|
{
|
|
- case VKD3DSIH_DCL_TEMPS:
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 0);
|
|
- if (ctx->dcl_temps_found)
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, "Duplicate DCL_TEMPS instruction.");
|
|
- if (instruction->declaration.count > ctx->program->temp_count)
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS,
|
|
- "Invalid DCL_TEMPS count %u, expected at most %u.",
|
|
- instruction->declaration.count, ctx->program->temp_count);
|
|
- ctx->dcl_temps_found = true;
|
|
- break;
|
|
-
|
|
- case VKD3DSIH_IF:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 1);
|
|
- if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
|
|
- return;
|
|
- ctx->blocks[ctx->depth++] = instruction->opcode;
|
|
- break;
|
|
+ const struct vsir_validator_instruction_desc *desc;
|
|
|
|
- case VKD3DSIH_IFC:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 2);
|
|
- if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
|
|
- return;
|
|
- ctx->blocks[ctx->depth++] = VKD3DSIH_IF;
|
|
- break;
|
|
+ desc = &vsir_validator_instructions[instruction->opcode];
|
|
|
|
- case VKD3DSIH_ELSE:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 0);
|
|
- if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF)
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ELSE instruction doesn't terminate IF block.");
|
|
- else
|
|
- ctx->blocks[ctx->depth - 1] = instruction->opcode;
|
|
- break;
|
|
-
|
|
- case VKD3DSIH_ENDIF:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 0);
|
|
- if (ctx->depth == 0 || (ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF && ctx->blocks[ctx->depth - 1] != VKD3DSIH_ELSE))
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDIF instruction doesn't terminate IF/ELSE block.");
|
|
- else
|
|
- --ctx->depth;
|
|
- break;
|
|
-
|
|
- case VKD3DSIH_LOOP:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, version->major <= 3 ? 2 : 0);
|
|
- if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
|
|
- return;
|
|
- ctx->blocks[ctx->depth++] = instruction->opcode;
|
|
- break;
|
|
-
|
|
- case VKD3DSIH_ENDLOOP:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 0);
|
|
- if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_LOOP)
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDLOOP instruction doesn't terminate LOOP block.");
|
|
- else
|
|
- --ctx->depth;
|
|
- break;
|
|
-
|
|
- case VKD3DSIH_REP:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 1);
|
|
- if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
|
|
- return;
|
|
- ctx->blocks[ctx->depth++] = instruction->opcode;
|
|
- break;
|
|
-
|
|
- case VKD3DSIH_ENDREP:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
- vsir_validate_dst_count(ctx, instruction, 0);
|
|
- vsir_validate_src_count(ctx, instruction, 0);
|
|
- if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_REP)
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDREP instruction doesn't terminate REP block.");
|
|
- else
|
|
- --ctx->depth;
|
|
- break;
|
|
+ if (desc->validate)
|
|
+ {
|
|
+ if (desc->dst_param_count != ~0u)
|
|
+ vsir_validate_dst_count(ctx, instruction, desc->dst_param_count);
|
|
+ if (desc->src_param_count != ~0u)
|
|
+ vsir_validate_src_count(ctx, instruction, desc->src_param_count);
|
|
+ desc->validate(ctx, instruction);
|
|
+ }
|
|
+ }
|
|
|
|
+ switch (instruction->opcode)
|
|
+ {
|
|
case VKD3DSIH_SWITCH:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
vsir_validate_dst_count(ctx, instruction, 0);
|
|
vsir_validate_src_count(ctx, instruction, 1);
|
|
if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
|
|
@@ -6400,7 +6426,7 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
|
break;
|
|
|
|
case VKD3DSIH_ENDSWITCH:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED);
|
|
vsir_validate_dst_count(ctx, instruction, 0);
|
|
vsir_validate_src_count(ctx, instruction, 0);
|
|
if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_SWITCH)
|
|
@@ -6415,7 +6441,7 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
|
break;
|
|
|
|
case VKD3DSIH_LABEL:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS);
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_BLOCKS);
|
|
vsir_validate_dst_count(ctx, instruction, 0);
|
|
vsir_validate_src_count(ctx, instruction, 1);
|
|
if (instruction->src_count >= 1 && !vsir_register_is_label(&instruction->src[0].reg))
|
|
@@ -6425,7 +6451,7 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
|
break;
|
|
|
|
case VKD3DSIH_BRANCH:
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS);
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_BLOCKS);
|
|
vsir_validate_dst_count(ctx, instruction, 0);
|
|
if (!vsir_validate_src_min_count(ctx, instruction, 1))
|
|
break;
|
|
@@ -6465,7 +6491,7 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
|
{
|
|
unsigned int case_count;
|
|
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS);
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_BLOCKS);
|
|
vsir_validate_dst_count(ctx, instruction, 0);
|
|
/* Parameters are source, default label, merge label and
|
|
* then pairs of constant value and case label. */
|
|
@@ -6510,7 +6536,7 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
|
{
|
|
unsigned int incoming_count;
|
|
|
|
- vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS);
|
|
+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_BLOCKS);
|
|
vsir_validate_dst_count(ctx, instruction, 1);
|
|
vsir_validate_src_min_count(ctx, instruction, 2);
|
|
if (instruction->src_count % 2 != 0)
|
|
@@ -6590,7 +6616,8 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c
|
|
if (!(ctx.ssas = vkd3d_calloc(ctx.program->ssa_count, sizeof(*ctx.ssas))))
|
|
goto fail;
|
|
|
|
- for (ctx.instruction_idx = 0; ctx.instruction_idx < program->instructions.count; ++ctx.instruction_idx)
|
|
+ for (ctx.instruction_idx = 0; ctx.instruction_idx < program->instructions.count
|
|
+ && ctx.status != VKD3D_ERROR_OUT_OF_MEMORY; ++ctx.instruction_idx)
|
|
vsir_validate_instruction(&ctx);
|
|
|
|
ctx.invalid_instruction_idx = true;
|
|
@@ -6685,7 +6712,8 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t
|
|
vsir_transform(&ctx, vsir_program_remove_dead_code);
|
|
vsir_transform(&ctx, vsir_program_normalise_combined_samplers);
|
|
|
|
- if (compile_info->target_type != VKD3D_SHADER_TARGET_GLSL)
|
|
+ if (compile_info->target_type != VKD3D_SHADER_TARGET_GLSL
|
|
+ && compile_info->target_type != VKD3D_SHADER_TARGET_MSL)
|
|
vsir_transform(&ctx, vsir_program_flatten_control_flow_constructs);
|
|
}
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
index b76a596bb60..a9d6c9e7c13 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
@@ -23,6 +23,7 @@
|
|
|
|
#include "hlsl.h"
|
|
#include "vkd3d_shader_private.h"
|
|
+#include "d3dcommon.h"
|
|
|
|
#define SM4_MAX_SRC_COUNT 6
|
|
#define SM4_MAX_DST_COUNT 2
|
|
@@ -616,6 +617,33 @@ enum vkd3d_sm4_shader_data_type
|
|
VKD3D_SM4_SHADER_DATA_MESSAGE = 0x4,
|
|
};
|
|
|
|
+enum vkd3d_sm4_stat_field
|
|
+{
|
|
+ VKD3D_STAT_UNUSED = 0,
|
|
+ VKD3D_STAT_INSTR_COUNT,
|
|
+ VKD3D_STAT_MOV,
|
|
+ VKD3D_STAT_MOVC,
|
|
+ VKD3D_STAT_CONV,
|
|
+ VKD3D_STAT_FLOAT,
|
|
+ VKD3D_STAT_INT,
|
|
+ VKD3D_STAT_UINT,
|
|
+ VKD3D_STAT_EMIT,
|
|
+ VKD3D_STAT_CUT,
|
|
+ VKD3D_STAT_SAMPLE,
|
|
+ VKD3D_STAT_SAMPLE_C,
|
|
+ VKD3D_STAT_SAMPLE_GRAD,
|
|
+ VKD3D_STAT_SAMPLE_BIAS,
|
|
+ VKD3D_STAT_LOAD,
|
|
+ VKD3D_STAT_STORE,
|
|
+ VKD3D_STAT_COUNT,
|
|
+};
|
|
+
|
|
+struct vkd3d_sm4_stat_field_info
|
|
+{
|
|
+ enum vkd3d_sm4_opcode opcode;
|
|
+ enum vkd3d_sm4_stat_field field;
|
|
+};
|
|
+
|
|
struct sm4_index_range
|
|
{
|
|
unsigned int index;
|
|
@@ -634,6 +662,7 @@ struct vkd3d_sm4_lookup_tables
|
|
const struct vkd3d_sm4_opcode_info *opcode_info_from_sm4[VKD3D_SM4_OP_COUNT];
|
|
const struct vkd3d_sm4_register_type_info *register_type_info_from_sm4[VKD3D_SM4_REGISTER_TYPE_COUNT];
|
|
const struct vkd3d_sm4_register_type_info *register_type_info_from_vkd3d[VKD3DSPR_COUNT];
|
|
+ const struct vkd3d_sm4_stat_field_info *stat_field_from_sm4[VKD3D_SM4_OP_COUNT];
|
|
};
|
|
|
|
struct vkd3d_shader_sm4_parser
|
|
@@ -1330,11 +1359,17 @@ static const enum vkd3d_shader_register_precision register_precision_table[] =
|
|
/* VKD3D_SM4_REGISTER_PRECISION_MIN_UINT_16 */ VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16,
|
|
};
|
|
|
|
+struct sm4_stat
|
|
+{
|
|
+ uint32_t fields[VKD3D_STAT_COUNT];
|
|
+};
|
|
+
|
|
struct tpf_writer
|
|
{
|
|
struct hlsl_ctx *ctx;
|
|
struct vkd3d_bytecode_buffer *buffer;
|
|
struct vkd3d_sm4_lookup_tables lookup;
|
|
+ struct sm4_stat *stat;
|
|
};
|
|
|
|
static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
|
|
@@ -1662,6 +1697,120 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
|
|
{VKD3D_SM5_RT_OUTPUT_STENCIL_REF, VKD3DSPR_OUTSTENCILREF, VKD3D_SM4_SWIZZLE_VEC4},
|
|
};
|
|
|
|
+ static const struct vkd3d_sm4_stat_field_info stat_field_table[] =
|
|
+ {
|
|
+ {VKD3D_SM4_OP_MOV, VKD3D_STAT_MOV},
|
|
+ {VKD3D_SM4_OP_MOVC, VKD3D_STAT_MOVC},
|
|
+ {VKD3D_SM5_OP_DMOV, VKD3D_STAT_MOV},
|
|
+ {VKD3D_SM5_OP_DMOVC, VKD3D_STAT_MOVC},
|
|
+
|
|
+ {VKD3D_SM4_OP_ITOF, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM4_OP_FTOI, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM4_OP_FTOU, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM4_OP_UTOF, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_DTOU, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_UTOD, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_DTOF, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_FTOD, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_DTOI, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_ITOD, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_F32TOF16, VKD3D_STAT_CONV},
|
|
+ {VKD3D_SM5_OP_F16TOF32, VKD3D_STAT_CONV},
|
|
+
|
|
+ {VKD3D_SM4_OP_ADD, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_DIV, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_DP2, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_DP3, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_DP4, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_EQ, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_EXP, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_FRC, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_GE, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_LT, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_MAD, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_MIN, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_MAX, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_MUL, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_NE, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_ROUND_NE, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_ROUND_NI, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_ROUND_PI, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_ROUND_Z, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_RSQ, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_SQRT, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM4_OP_SINCOS, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_RCP, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DADD, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DMAX, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DMIN, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DMUL, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DEQ, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DGE, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DLT, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DNE, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DDIV, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DFMA, VKD3D_STAT_FLOAT},
|
|
+ {VKD3D_SM5_OP_DRCP, VKD3D_STAT_FLOAT},
|
|
+
|
|
+ {VKD3D_SM4_OP_IADD, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_IEQ, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_IGE, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_ILT, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_IMAD, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_IMAX, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_IMIN, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_IMUL, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_INE, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_INEG, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_ISHL, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_ISHR, VKD3D_STAT_INT},
|
|
+ {VKD3D_SM4_OP_ITOF, VKD3D_STAT_INT},
|
|
+
|
|
+ {VKD3D_SM4_OP_UDIV, VKD3D_STAT_UINT},
|
|
+ {VKD3D_SM4_OP_ULT, VKD3D_STAT_UINT},
|
|
+ {VKD3D_SM4_OP_UGE, VKD3D_STAT_UINT},
|
|
+ {VKD3D_SM4_OP_UMUL, VKD3D_STAT_UINT},
|
|
+ {VKD3D_SM4_OP_UMAX, VKD3D_STAT_UINT},
|
|
+ {VKD3D_SM4_OP_UMIN, VKD3D_STAT_UINT},
|
|
+ {VKD3D_SM4_OP_USHR, VKD3D_STAT_UINT},
|
|
+
|
|
+ {VKD3D_SM4_OP_EMIT, VKD3D_STAT_EMIT},
|
|
+ {VKD3D_SM4_OP_CUT, VKD3D_STAT_CUT},
|
|
+ {VKD3D_SM5_OP_EMIT_STREAM, VKD3D_STAT_EMIT},
|
|
+ {VKD3D_SM5_OP_CUT_STREAM, VKD3D_STAT_CUT},
|
|
+
|
|
+ {VKD3D_SM4_OP_SAMPLE, VKD3D_STAT_SAMPLE},
|
|
+ {VKD3D_SM4_OP_SAMPLE_LOD, VKD3D_STAT_SAMPLE},
|
|
+ {VKD3D_SM5_OP_SAMPLE_LOD_S, VKD3D_STAT_SAMPLE},
|
|
+ {VKD3D_SM5_OP_SAMPLE_CL_S, VKD3D_STAT_SAMPLE},
|
|
+ {VKD3D_SM4_OP_GATHER4, VKD3D_STAT_SAMPLE},
|
|
+ {VKD3D_SM5_OP_GATHER4_PO, VKD3D_STAT_SAMPLE},
|
|
+ {VKD3D_SM4_OP_SAMPLE_C, VKD3D_STAT_SAMPLE_C},
|
|
+ {VKD3D_SM4_OP_SAMPLE_C_LZ, VKD3D_STAT_SAMPLE_C},
|
|
+ {VKD3D_SM5_OP_SAMPLE_C_LZ_S, VKD3D_STAT_SAMPLE_C},
|
|
+ {VKD3D_SM5_OP_SAMPLE_C_CL_S, VKD3D_STAT_SAMPLE_C},
|
|
+ {VKD3D_SM5_OP_GATHER4_C, VKD3D_STAT_SAMPLE_C},
|
|
+ {VKD3D_SM5_OP_GATHER4_PO_C, VKD3D_STAT_SAMPLE_C},
|
|
+ {VKD3D_SM4_OP_SAMPLE_GRAD, VKD3D_STAT_SAMPLE_GRAD},
|
|
+ {VKD3D_SM5_OP_SAMPLE_GRAD_CL_S, VKD3D_STAT_SAMPLE_GRAD},
|
|
+ {VKD3D_SM4_OP_SAMPLE_B, VKD3D_STAT_SAMPLE_BIAS},
|
|
+
|
|
+ {VKD3D_SM4_OP_LD, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM4_OP_LD2DMS, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD_UAV_TYPED, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD_RAW, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD_STRUCTURED, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD_S, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD2DMS_S, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD_UAV_TYPED_S, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD_RAW_S, VKD3D_STAT_LOAD},
|
|
+ {VKD3D_SM5_OP_LD_STRUCTURED_S, VKD3D_STAT_LOAD},
|
|
+
|
|
+ {VKD3D_SM5_OP_STORE_UAV_TYPED, VKD3D_STAT_STORE},
|
|
+ {VKD3D_SM5_OP_STORE_RAW, VKD3D_STAT_STORE},
|
|
+ {VKD3D_SM5_OP_STORE_STRUCTURED,VKD3D_STAT_STORE},
|
|
+ };
|
|
+
|
|
memset(lookup, 0, sizeof(*lookup));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(opcode_table); ++i)
|
|
@@ -1678,12 +1827,21 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
|
|
lookup->register_type_info_from_sm4[info->sm4_type] = info;
|
|
lookup->register_type_info_from_vkd3d[info->vkd3d_type] = info;
|
|
}
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(stat_field_table); ++i)
|
|
+ {
|
|
+ const struct vkd3d_sm4_stat_field_info *info = &stat_field_table[i];
|
|
+
|
|
+ lookup->stat_field_from_sm4[info->opcode] = info;
|
|
+ }
|
|
}
|
|
|
|
-static void tpf_writer_init(struct tpf_writer *tpf, struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer)
|
|
+static void tpf_writer_init(struct tpf_writer *tpf, struct hlsl_ctx *ctx, struct sm4_stat *stat,
|
|
+ struct vkd3d_bytecode_buffer *buffer)
|
|
{
|
|
tpf->ctx = ctx;
|
|
tpf->buffer = buffer;
|
|
+ tpf->stat = stat;
|
|
init_sm4_lookup_tables(&tpf->lookup);
|
|
}
|
|
|
|
@@ -1721,6 +1879,16 @@ static enum vkd3d_sm4_swizzle_type vkd3d_sm4_get_default_swizzle_type(
|
|
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)
|
|
+{
|
|
+ const struct vkd3d_sm4_stat_field_info *field_info;
|
|
+
|
|
+ if (sm4_opcode >= VKD3D_SM4_OP_COUNT || !(field_info = lookup->stat_field_from_sm4[sm4_opcode]))
|
|
+ return VKD3D_STAT_UNUSED;
|
|
+ return field_info->field;
|
|
+}
|
|
+
|
|
static enum vkd3d_data_type map_data_type(char t)
|
|
{
|
|
switch (t)
|
|
@@ -2553,7 +2721,7 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro
|
|
version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
|
|
|
|
/* Estimate instruction count to avoid reallocation in most shaders. */
|
|
- if (!vsir_program_init(program, compile_info, &version, token_count / 7u + 20))
|
|
+ if (!vsir_program_init(program, compile_info, &version, token_count / 7u + 20, VSIR_CF_STRUCTURED))
|
|
return false;
|
|
vkd3d_shader_parser_init(&sm4->p, program, message_context, compile_info->source_name);
|
|
sm4->ptr = sm4->start;
|
|
@@ -4187,6 +4355,7 @@ static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4
|
|
{
|
|
struct vkd3d_bytecode_buffer *buffer = tpf->buffer;
|
|
uint32_t token = instr->opcode | instr->extra_bits;
|
|
+ enum vkd3d_sm4_stat_field stat_field;
|
|
unsigned int size, i, j;
|
|
size_t token_position;
|
|
|
|
@@ -4219,6 +4388,11 @@ static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4
|
|
size = (bytecode_get_size(buffer) - token_position) / sizeof(uint32_t);
|
|
token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT);
|
|
set_u32(buffer, token_position, token);
|
|
+
|
|
+ ++tpf->stat->fields[VKD3D_STAT_INSTR_COUNT];
|
|
+
|
|
+ stat_field = get_stat_field_from_sm4_opcode(&tpf->lookup, instr->opcode & VKD3D_SM4_OPCODE_MASK);
|
|
+ ++tpf->stat->fields[stat_field];
|
|
}
|
|
|
|
static bool encode_texel_offset_as_aoffimmi(struct sm4_instruction *instr,
|
|
@@ -4579,6 +4753,17 @@ static void write_sm4_dcl_thread_group(const struct tpf_writer *tpf, const uint3
|
|
write_sm4_instruction(tpf, &instr);
|
|
}
|
|
|
|
+static void write_sm4_dcl_global_flags(const struct tpf_writer *tpf, uint32_t flags)
|
|
+{
|
|
+ struct sm4_instruction instr =
|
|
+ {
|
|
+ .opcode = VKD3D_SM4_OP_DCL_GLOBAL_FLAGS,
|
|
+ .extra_bits = flags << VKD3D_SM4_GLOBAL_FLAGS_SHIFT,
|
|
+ };
|
|
+
|
|
+ write_sm4_instruction(tpf, &instr);
|
|
+}
|
|
+
|
|
static void write_sm4_ret(const struct tpf_writer *tpf)
|
|
{
|
|
struct sm4_instruction instr =
|
|
@@ -6017,8 +6202,8 @@ static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_bloc
|
|
}
|
|
}
|
|
|
|
-static void write_sm4_shdr(struct hlsl_ctx *ctx,
|
|
- const struct hlsl_ir_function_decl *entry_func, struct dxbc_writer *dxbc)
|
|
+static void write_sm4_shdr(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *entry_func,
|
|
+ struct sm4_stat *stat, struct dxbc_writer *dxbc)
|
|
{
|
|
const struct hlsl_profile_info *profile = ctx->profile;
|
|
struct vkd3d_bytecode_buffer buffer = {0};
|
|
@@ -6043,7 +6228,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
|
|
VKD3D_SM4_LIB,
|
|
};
|
|
|
|
- tpf_writer_init(&tpf, ctx, &buffer);
|
|
+ tpf_writer_init(&tpf, ctx, stat, &buffer);
|
|
|
|
extern_resources = sm4_get_extern_resources(ctx, &extern_resources_count);
|
|
|
|
@@ -6068,6 +6253,9 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
|
|
write_sm4_dcl_textures(&tpf, resource, true);
|
|
}
|
|
|
|
+ if (entry_func->early_depth_test && profile->major_version >= 5)
|
|
+ write_sm4_dcl_global_flags(&tpf, VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL);
|
|
+
|
|
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
|
|
{
|
|
if ((var->is_input_semantic && var->last_read) || (var->is_output_semantic && var->first_write))
|
|
@@ -6135,8 +6323,58 @@ static void write_sm4_sfi0(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
|
|
vkd3d_free(flags);
|
|
}
|
|
|
|
+static void write_sm4_stat(struct hlsl_ctx *ctx, const struct sm4_stat *stat, struct dxbc_writer *dxbc)
|
|
+{
|
|
+ struct vkd3d_bytecode_buffer buffer = {0};
|
|
+
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_INSTR_COUNT]);
|
|
+ put_u32(&buffer, 0); /* Temp count */
|
|
+ put_u32(&buffer, 0); /* Def count */
|
|
+ put_u32(&buffer, 0); /* DCL count */
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_FLOAT]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_INT]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_UINT]);
|
|
+ put_u32(&buffer, 0); /* Static flow control count */
|
|
+ put_u32(&buffer, 0); /* Dynamic flow control count */
|
|
+ put_u32(&buffer, 0); /* Macro instruction count */
|
|
+ put_u32(&buffer, 0); /* Temp array count */
|
|
+ put_u32(&buffer, 0); /* Array instr count */
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_CUT]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_EMIT]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_SAMPLE]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_LOAD]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_SAMPLE_C]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_SAMPLE_BIAS]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_SAMPLE_GRAD]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_MOV]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_MOVC]);
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_CONV]);
|
|
+ put_u32(&buffer, 0); /* Bitwise instructions */
|
|
+ put_u32(&buffer, 0); /* Input primitive */
|
|
+ put_u32(&buffer, 0); /* GS output topology */
|
|
+ put_u32(&buffer, 0); /* GS max output vertex count */
|
|
+ put_u32(&buffer, 0); /* Unknown */
|
|
+ put_u32(&buffer, 0); /* Unknown */
|
|
+ put_u32(&buffer, 0); /* Sample frequency */
|
|
+
|
|
+ if (hlsl_version_ge(ctx, 5, 0))
|
|
+ {
|
|
+ put_u32(&buffer, 0); /* GS instance count */
|
|
+ put_u32(&buffer, 0); /* Control point count */
|
|
+ put_u32(&buffer, 0); /* HS output primitive */
|
|
+ put_u32(&buffer, 0); /* HS partitioning */
|
|
+ put_u32(&buffer, 0); /* Tessellator domain */
|
|
+ put_u32(&buffer, 0); /* Barrier instructions */
|
|
+ put_u32(&buffer, 0); /* Interlocked instructions */
|
|
+ put_u32(&buffer, stat->fields[VKD3D_STAT_STORE]);
|
|
+ }
|
|
+
|
|
+ add_section(ctx, dxbc, TAG_STAT, &buffer);
|
|
+}
|
|
+
|
|
int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out)
|
|
{
|
|
+ struct sm4_stat stat = {0};
|
|
struct dxbc_writer dxbc;
|
|
size_t i;
|
|
int ret;
|
|
@@ -6146,8 +6384,9 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
|
|
write_sm4_signature(ctx, &dxbc, false);
|
|
write_sm4_signature(ctx, &dxbc, true);
|
|
write_sm4_rdef(ctx, &dxbc);
|
|
- write_sm4_shdr(ctx, entry_func, &dxbc);
|
|
+ write_sm4_shdr(ctx, entry_func, &stat, &dxbc);
|
|
write_sm4_sfi0(ctx, &dxbc);
|
|
+ write_sm4_stat(ctx, &stat, &dxbc);
|
|
|
|
if (!(ret = ctx->result))
|
|
ret = dxbc_writer_write(&dxbc, out);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
index 60be996ae24..ee98a504a5b 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
@@ -535,6 +535,8 @@ static const char *shader_get_target_type_suffix(enum vkd3d_shader_target_type t
|
|
return "glsl";
|
|
case VKD3D_SHADER_TARGET_FX:
|
|
return "fx";
|
|
+ case VKD3D_SHADER_TARGET_MSL:
|
|
+ return "msl";
|
|
default:
|
|
FIXME("Unhandled target type %#x.\n", type);
|
|
return "bin";
|
|
@@ -1646,6 +1648,10 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
|
|
vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
|
|
break;
|
|
|
|
+ case VKD3D_SHADER_TARGET_MSL:
|
|
+ ret = msl_compile(program, config_flags, compile_info, message_context);
|
|
+ break;
|
|
+
|
|
default:
|
|
/* Validation should prevent us from reaching this. */
|
|
vkd3d_unreachable();
|
|
@@ -1945,6 +1951,9 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
|
|
VKD3D_SHADER_TARGET_D3D_ASM,
|
|
#ifdef VKD3D_SHADER_UNSUPPORTED_GLSL
|
|
VKD3D_SHADER_TARGET_GLSL,
|
|
+#endif
|
|
+#ifdef VKD3D_SHADER_UNSUPPORTED_MSL
|
|
+ VKD3D_SHADER_TARGET_MSL,
|
|
#endif
|
|
};
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
index bc369ec6866..8866780132e 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
@@ -238,6 +238,8 @@ enum vkd3d_shader_error
|
|
VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019,
|
|
|
|
VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300,
|
|
+
|
|
+ VKD3D_SHADER_ERROR_MSL_INTERNAL = 10000,
|
|
};
|
|
|
|
enum vkd3d_shader_opcode
|
|
@@ -1362,6 +1364,12 @@ enum vkd3d_shader_config_flags
|
|
VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001,
|
|
};
|
|
|
|
+enum vsir_control_flow_type
|
|
+{
|
|
+ VSIR_CF_STRUCTURED,
|
|
+ VSIR_CF_BLOCKS,
|
|
+};
|
|
+
|
|
struct vsir_program
|
|
{
|
|
struct vkd3d_shader_version shader_version;
|
|
@@ -1381,6 +1389,7 @@ struct vsir_program
|
|
unsigned int temp_count;
|
|
unsigned int ssa_count;
|
|
bool use_vocp;
|
|
+ enum vsir_control_flow_type cf_type;
|
|
|
|
const char **block_names;
|
|
size_t block_name_count;
|
|
@@ -1393,7 +1402,7 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
|
|
const struct vkd3d_shader_parameter1 *vsir_program_get_parameter(
|
|
const struct vsir_program *program, enum vkd3d_shader_parameter_name name);
|
|
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
|
|
- const struct vkd3d_shader_version *version, unsigned int reserve);
|
|
+ const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type);
|
|
enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t config_flags,
|
|
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context);
|
|
enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t config_flags,
|
|
@@ -1593,6 +1602,9 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags,
|
|
const struct vkd3d_shader_compile_info *compile_info,
|
|
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
|
|
|
|
+int msl_compile(struct vsir_program *program, uint64_t config_flags,
|
|
+ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context);
|
|
+
|
|
enum vkd3d_md5_variant
|
|
{
|
|
VKD3D_MD5_STANDARD,
|
|
@@ -1872,7 +1884,7 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
|
|
#define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t))
|
|
#define VKD3D_DXBC_CHUNK_ALIGNMENT sizeof(uint32_t)
|
|
|
|
-#define DXBC_MAX_SECTION_COUNT 5
|
|
+#define DXBC_MAX_SECTION_COUNT 6
|
|
|
|
struct dxbc_writer
|
|
{
|
|
--
|
|
2.45.2
|
|
|