Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 9f5c18dd..38c71626 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -163,9 +163,9 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b } }
- type->bytecode_offset = put_u32(buffer, sm4_class(type) | (sm4_base_type(type) << 16)); - put_u32(buffer, type->dimy | (type->dimx << 16)); - put_u32(buffer, array_size | (field_count << 16)); + type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm4_class(type), sm4_base_type(type))); + put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx)); + put_u32(buffer, vkd3d_make_u32(array_size, field_count)); put_u32(buffer, fields_offset);
if (profile->major_version >= 5) @@ -207,7 +207,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) cbuffer_position = put_u32(&buffer, 0); put_u32(&buffer, cbuffer_count); /* bound resource count */ resource_position = put_u32(&buffer, 0); - put_u32(&buffer, (target_types[profile->type] << 16) | (profile->major_version << 8) | profile->minor_version); + put_u32(&buffer, vkd3d_make_u32(vkd3d_make_u16(profile->minor_version, profile->major_version), + target_types[profile->type])); put_u32(&buffer, 0); /* FIXME: compilation flags */ creator_position = put_u32(&buffer, 0);
@@ -371,7 +372,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) VKD3D_SM4_LIB, };
- put_u32(&buffer, (shader_types[profile->type] << 16) | (profile->major_version << 4) | profile->minor_version); + put_u32(&buffer, vkd3d_make_u32((profile->major_version << 4) | profile->minor_version, shader_types[profile->type])); put_u32(&buffer, 0); /* FIXME: instruction token count */
dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- include/vkd3d_d3dcommon.idl | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/include/vkd3d_d3dcommon.idl b/include/vkd3d_d3dcommon.idl index 0359a749..ed6f2705 100644 --- a/include/vkd3d_d3dcommon.idl +++ b/include/vkd3d_d3dcommon.idl @@ -191,6 +191,12 @@ typedef enum _D3D_SHADER_VARIABLE_TYPE D3D_SVT_RWSTRUCTURED_BUFFER, D3D_SVT_APPEND_STRUCTURED_BUFFER, D3D_SVT_CONSUME_STRUCTURED_BUFFER, + D3D_SVT_MIN8FLOAT, + D3D_SVT_MIN10FLOAT, + D3D_SVT_MIN16FLOAT, + D3D_SVT_MIN12INT, + D3D_SVT_MIN16INT, + D3D_SVT_MIN16UINT, D3D_SVT_FORCE_DWORD = 0x7fffffff, } D3D_SHADER_VARIABLE_TYPE;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- include/private/vkd3d_common.h | 14 +++ include/vkd3d_d3dcommon.idl | 37 ++++++ libs/vkd3d-shader/hlsl.h | 6 + libs/vkd3d-shader/hlsl_codegen.c | 59 ++++++--- libs/vkd3d-shader/hlsl_sm4.c | 200 ++++++++++++++++++++++++++++++- 5 files changed, 300 insertions(+), 16 deletions(-)
diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index 46a39b4d..18cc3cab 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -170,6 +170,20 @@ static inline int ascii_tolower(int c) return ascii_isupper(c) ? c - 'A' + 'a' : c; }
+static inline int ascii_strncasecmp(const char *a, const char *b, size_t n) +{ + int c_a, c_b; + + while (n--) + { + c_a = ascii_tolower(*a++); + c_b = ascii_tolower(*b++); + if (c_a != c_b || !c_a) + return c_a - c_b; + } + return 0; +} + static inline int ascii_strcasecmp(const char *a, const char *b) { int c_a, c_b; diff --git a/include/vkd3d_d3dcommon.idl b/include/vkd3d_d3dcommon.idl index ed6f2705..4859d145 100644 --- a/include/vkd3d_d3dcommon.idl +++ b/include/vkd3d_d3dcommon.idl @@ -88,6 +88,43 @@ typedef enum D3D_CBUFFER_TYPE D3D_CT_RESOURCE_BIND_INFO, } D3D_CBUFFER_TYPE;
+typedef enum D3D_NAME +{ + D3D_NAME_UNDEFINED, + D3D_NAME_POSITION, + D3D_NAME_CLIP_DISTANCE, + D3D_NAME_CULL_DISTANCE, + D3D_NAME_RENDER_TARGET_ARRAY_INDEX, + D3D_NAME_VIEWPORT_ARRAY_INDEX, + D3D_NAME_VERTEX_ID, + D3D_NAME_PRIMITIVE_ID, + D3D_NAME_INSTANCE_ID, + D3D_NAME_IS_FRONT_FACE, + D3D_NAME_SAMPLE_INDEX, + D3D_NAME_FINAL_QUAD_EDGE_TESSFACTOR, + D3D_NAME_FINAL_QUAD_INSIDE_TESSFACTOR, + D3D_NAME_FINAL_TRI_EDGE_TESSFACTOR, + D3D_NAME_FINAL_TRI_INSIDE_TESSFACTOR, + D3D_NAME_FINAL_LINE_DETAIL_TESSFACTOR, + D3D_NAME_FINAL_LINE_DENSITY_TESSFACTOR, + D3D_NAME_BARYCENTRICS = 23, + D3D_NAME_SHADINGRATE, + D3D_NAME_CULLPRIMITIVE, + D3D_NAME_TARGET = 64, + D3D_NAME_DEPTH, + D3D_NAME_COVERAGE, + D3D_NAME_DEPTH_GREATER_EQUAL, + D3D_NAME_DEPTH_LESS_EQUAL, +} D3D_NAME; + +typedef enum D3D_REGISTER_COMPONENT_TYPE +{ + D3D_REGISTER_COMPONENT_UNKNOWN, + D3D_REGISTER_COMPONENT_UINT32, + D3D_REGISTER_COMPONENT_SINT32, + D3D_REGISTER_COMPONENT_FLOAT32, +} D3D_REGISTER_COMPONENT_TYPE; + typedef enum _D3D_SHADER_INPUT_FLAGS { D3D_SIF_USERPACKED = 0x01, diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 41c16b07..9860ed7a 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -22,7 +22,9 @@
#include "vkd3d_shader_private.h" #include "rbtree.h" +#include "vkd3d_d3dcommon.h" #include "vkd3d_d3dx9shader.h" +#include "sm4.h"
/* The general IR structure is inspired by Mesa GLSL hir, even though the code * ends up being quite different in practice. Anyway, here comes the relevant @@ -683,6 +685,10 @@ bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem bool hlsl_sm1_usage_from_semantic(const struct hlsl_semantic *semantic, D3DDECLUSAGE *usage, uint32_t *usage_idx); int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
+bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, + const struct hlsl_semantic *semantic, bool output, D3D_NAME *usage); +bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, + bool output, enum vkd3d_sm4_register_type *type, uint32_t *reg); int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hlsl); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index b5f7832f..939b356c 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1012,13 +1012,26 @@ static void allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functio
static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, unsigned int *counter, bool output) { + static const char *shader_names[] = + { + [VKD3D_SHADER_TYPE_PIXEL] = "Pixel", + [VKD3D_SHADER_TYPE_VERTEX] = "Vertex", + [VKD3D_SHADER_TYPE_GEOMETRY] = "Geometry", + [VKD3D_SHADER_TYPE_HULL] = "Hull", + [VKD3D_SHADER_TYPE_DOMAIN] = "Domain", + [VKD3D_SHADER_TYPE_COMPUTE] = "Compute", + }; + + unsigned int type; + uint32_t reg; + bool builtin; + assert(var->semantic.name);
if (ctx->profile->major_version < 4) { - D3DSHADER_PARAM_REGISTER_TYPE type; - uint32_t reg, usage_idx; D3DDECLUSAGE usage; + uint32_t usage_idx;
if (!hlsl_sm1_usage_from_semantic(&var->semantic, &usage, &usage_idx)) { @@ -1027,19 +1040,35 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var return; }
- if (hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, &type, ®)) - { - TRACE("%s %s semantic %s[%u] matches predefined register %#x[%u].\n", - ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL ? "Pixel" : "Vertex", output ? "output" : "input", - var->semantic.name, var->semantic.index, type, reg); - } - else + if ((!output && !var->last_read) || (output && !var->first_write)) + return; + + builtin = hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, &type, ®); + } + else + { + D3D_NAME usage; + + if (!hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage)) { - var->reg.allocated = true; - var->reg.id = (*counter)++; - var->reg.writemask = (1 << var->data_type->dimx) - 1; - TRACE("Allocated %s to %s.\n", var->name, debug_register(output ? 'o' : 'v', var->reg, var->data_type)); + hlsl_error(ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, + "Invalid semantic '%s'.", var->semantic.name); + return; } + builtin = hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, ®); + } + + if (builtin) + { + TRACE("%s %s semantic %s[%u] matches predefined register %#x[%u].\n", shader_names[ctx->profile->type], + output ? "output" : "input", var->semantic.name, var->semantic.index, type, reg); + } + else + { + var->reg.allocated = true; + var->reg.id = (*counter)++; + var->reg.writemask = (1 << var->data_type->dimx) - 1; + TRACE("Allocated %s to %s.\n", var->name, debug_register(output ? 'o' : 'v', var->reg, var->data_type)); } }
@@ -1050,9 +1079,9 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (var->is_input_semantic && var->last_read) + if (var->is_input_semantic) allocate_semantic_register(ctx, var, &input_counter, false); - if (var->is_output_semantic && var->first_write) + if (var->is_output_semantic) allocate_semantic_register(ctx, var, &output_counter, true); } } diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 38c71626..894c513f 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -23,6 +23,201 @@ #include "vkd3d_d3dcommon.h" #include "sm4.h"
+bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, + bool output, enum vkd3d_sm4_register_type *type, uint32_t *reg) +{ + unsigned int i; + + static const struct + { + const char *semantic; + bool output; + enum vkd3d_shader_type shader_type; + enum vkd3d_sm4_register_type type; + bool has_idx; + } + register_table[] = + { + {"sv_primitiveid", false, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SM4_RT_PRIMID, false}, + + /* Put sv_target in this table, instead of letting it fall through to + * default varying allocation, so that the register index matches the + * usage index. */ + {"color", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_OUTPUT, true}, + {"depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_DEPTHOUT, false}, + {"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_DEPTHOUT, false}, + {"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_OUTPUT, true}, + }; + + for (i = 0; i < ARRAY_SIZE(register_table); ++i) + { + if (!ascii_strcasecmp(semantic->name, register_table[i].semantic) + && output == register_table[i].output + && ctx->profile->type == register_table[i].shader_type) + { + *type = register_table[i].type; + *reg = register_table[i].has_idx ? semantic->index : ~0u; + return true; + } + } + + return false; +} + +bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, + bool output, D3D_NAME *usage) +{ + unsigned int i; + + static const struct + { + const char *name; + bool output; + enum vkd3d_shader_type shader_type; + D3DDECLUSAGE usage; + } + semantics[] = + { + {"position", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION}, + {"sv_position", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION}, + {"sv_primitiveid", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_PRIMITIVE_ID}, + + {"position", true, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION}, + {"sv_position", true, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION}, + {"sv_primitiveid", true, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_PRIMITIVE_ID}, + + {"position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, + {"sv_position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, + + {"color", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET}, + {"depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH}, + {"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET}, + {"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH}, + + {"sv_position", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_UNDEFINED}, + + {"position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, + {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, + }; + + for (i = 0; i < ARRAY_SIZE(semantics); ++i) + { + if (!ascii_strcasecmp(semantic->name, semantics[i].name) + && output == semantics[i].output + && ctx->profile->type == semantics[i].shader_type + && !ascii_strncasecmp(semantic->name, "sv_", 3)) + { + *usage = semantics[i].usage; + return true; + } + } + + if (!ascii_strncasecmp(semantic->name, "sv_", 3)) + return false; + + *usage = D3D_NAME_UNDEFINED; + return true; +} + +static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, bool output) +{ + struct vkd3d_bytecode_buffer buffer = {0}; + struct vkd3d_string_buffer *string; + const struct hlsl_ir_var *var; + size_t count_position; + unsigned int i; + bool ret; + + count_position = put_u32(&buffer, 0); + put_u32(&buffer, 8); /* unknown */ + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + unsigned int width = (1u << var->data_type->dimx) - 1, use_mask; + enum vkd3d_sm4_register_type type; + uint32_t usage_idx, reg_idx; + D3D_NAME usage; + + if ((output && !var->is_output_semantic) || (!output && !var->is_input_semantic)) + continue; + + ret = hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage); + assert(ret); + usage_idx = var->semantic.index; + + if (!hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, ®_idx)) + { + assert(var->reg.allocated); + type = VKD3D_SM4_RT_INPUT; + reg_idx = var->reg.id; + } + + use_mask = width; /* FIXME: accurately report use mask */ + if (output) + use_mask = 0xf ^ use_mask; + + /* Special pixel shader semantics (TARGET, DEPTH, COVERAGE). */ + if (usage >= 64) + usage = 0; + + put_u32(&buffer, 0); /* name */ + put_u32(&buffer, usage_idx); + put_u32(&buffer, usage); + switch (var->data_type->base_type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: + put_u32(&buffer, D3D_REGISTER_COMPONENT_FLOAT32); + break; + + case HLSL_TYPE_INT: + put_u32(&buffer, D3D_REGISTER_COMPONENT_SINT32); + break; + + case HLSL_TYPE_BOOL: + case HLSL_TYPE_UINT: + put_u32(&buffer, D3D_REGISTER_COMPONENT_UINT32); + break; + + default: + if ((string = hlsl_type_to_string(ctx, var->data_type))) + hlsl_error(ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Invalid data type %s for semantic variable %s.", string->buffer, var->name); + hlsl_release_string_buffer(ctx, string); + put_u32(&buffer, D3D_REGISTER_COMPONENT_UNKNOWN); + } + put_u32(&buffer, reg_idx); + put_u32(&buffer, vkd3d_make_u16(width, use_mask)); + } + + i = 0; + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + const char *semantic = var->semantic.name; + size_t string_offset; + D3D_NAME usage; + + if ((output && !var->is_output_semantic) || (!output && !var->is_input_semantic)) + continue; + + hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage); + + if (usage == D3D_NAME_TARGET && !ascii_strcasecmp(semantic, "color")) + string_offset = put_string(&buffer, "SV_Target"); + else if (usage == D3D_NAME_DEPTH && !ascii_strcasecmp(semantic, "depth")) + string_offset = put_string(&buffer, "SV_Depth"); + else if (usage == D3D_NAME_POSITION && !ascii_strcasecmp(semantic, "position")) + string_offset = put_string(&buffer, "SV_Position"); + else + string_offset = put_string(&buffer, semantic); + set_u32(&buffer, (2 + i++ * 6) * sizeof(uint32_t), string_offset); + } + + set_u32(&buffer, count_position, i); + + dxbc_writer_add_section(dxbc, output ? TAG_OSGN : TAG_ISGN, buffer.data, buffer.size); +} + static const struct hlsl_type *get_array_type(const struct hlsl_type *type) { if (type->type == HLSL_CLASS_ARRAY) @@ -386,10 +581,13 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
dxbc_writer_init(&dxbc);
+ write_sm4_signature(ctx, &dxbc, false); + write_sm4_signature(ctx, &dxbc, true); write_sm4_rdef(ctx, &dxbc); write_sm4_shdr(ctx, &dxbc);
- ret = dxbc_writer_write(&dxbc, out); + if (!(ret = ctx->result)) + ret = dxbc_writer_write(&dxbc, out); for (i = 0; i < dxbc.section_count; ++i) vkd3d_free((void *)dxbc.sections[i].data); return ret;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
On Fri, Aug 20, 2021 at 1:45 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
include/private/vkd3d_common.h | 14 +++ include/vkd3d_d3dcommon.idl | 37 ++++++ libs/vkd3d-shader/hlsl.h | 6 + libs/vkd3d-shader/hlsl_codegen.c | 59 ++++++--- libs/vkd3d-shader/hlsl_sm4.c | 200 ++++++++++++++++++++++++++++++- 5 files changed, 300 insertions(+), 16 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index b5f7832f..939b356c 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1012,13 +1012,26 @@ static void allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functio
static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, unsigned int *counter, bool output) {
static const char *shader_names[] =
{
[VKD3D_SHADER_TYPE_PIXEL] = "Pixel",
[VKD3D_SHADER_TYPE_VERTEX] = "Vertex",
[VKD3D_SHADER_TYPE_GEOMETRY] = "Geometry",
[VKD3D_SHADER_TYPE_HULL] = "Hull",
[VKD3D_SHADER_TYPE_DOMAIN] = "Domain",
[VKD3D_SHADER_TYPE_COMPUTE] = "Compute",
};
unsigned int type;
uint32_t reg;
bool builtin;
assert(var->semantic.name);
if (ctx->profile->major_version < 4) {
D3DSHADER_PARAM_REGISTER_TYPE type;
uint32_t reg, usage_idx; D3DDECLUSAGE usage;
uint32_t usage_idx; if (!hlsl_sm1_usage_from_semantic(&var->semantic, &usage, &usage_idx)) {
@@ -1027,19 +1040,35 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var return; }
if (hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, &type, ®))
{
TRACE("%s %s semantic %s[%u] matches predefined register %#x[%u].\n",
ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL ? "Pixel" : "Vertex", output ? "output" : "input",
var->semantic.name, var->semantic.index, type, reg);
}
else
if ((!output && !var->last_read) || (output && !var->first_write))
return;
builtin = hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, &type, ®);
This appears to slip in a functional change, where now we don't allocate registers for SM1 "user" (not system value / predefined register) inputs / outputs if they're unused. That's not the case as this is just moving a check from allocate_semantic_registers(). As it turns out, things aren't quite working right for those semantics anyway.
Let me go fully OT and digress into the details of this SM1 issue. Assume we have a PS with this signature:
float4 main(in float4 color : COLOR, in float4 normal : NORMAL) : SV_TARGET
and compile it for the ps_2_0 profile. If both our inputs are used, they will be both allocated to v0, which seems bad. If normal isn't used, because of the change above it won't be allocated, but since write_sm1_semantic_dcl() doesn't check for the allocated flag it will generate a dcl instruction anyway (to v0, since the allocation info is zero-initialized).
There are a few things to fix here. First of all, these "user" semantics are supposed to be mapped to the t# registers in ps_2_0 (there are 2 color inputs, v0-1, and 8 t0-7 "texcoords", but actually, generic inputs). Then we need to make sure to not step onto registers used by "builtin" semantics. I suggest reworking allocate_semantic_registers() so that both builtin and user inputs / outputs get allocation info; also keep track of the register type for allocations (maybe as SM-specific values); make sure that user inputs / outputs don't step over already allocated registers. Finally, have everything downstream from register allocation solely refer to the allocation data. I haven't really tried to write the patches so there might be something / a lot missing in the above.
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 38c71626..894c513f 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c
+bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
bool output, D3D_NAME *usage)
+{
- unsigned int i;
- static const struct
- {
const char *name;
bool output;
enum vkd3d_shader_type shader_type;
D3DDECLUSAGE usage;
- }
- semantics[] =
- {
{"position", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION},
{"sv_position", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION},
{"sv_primitiveid", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_PRIMITIVE_ID},
{"position", true, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION},
{"sv_position", true, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION},
{"sv_primitiveid", true, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_PRIMITIVE_ID},
{"position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION},
{"sv_position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION},
{"color", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET},
{"depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH},
{"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET},
{"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH},
{"sv_position", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_UNDEFINED},
{"position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION},
{"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION},
- };
Eventually we might want to introduce bitmask flags for the shader type and group up identical lines together (I imagine this will become quite a bit more verbose with tessellation shaders).
- for (i = 0; i < ARRAY_SIZE(semantics); ++i)
- {
if (!ascii_strcasecmp(semantic->name, semantics[i].name)
&& output == semantics[i].output
&& ctx->profile->type == semantics[i].shader_type
&& !ascii_strncasecmp(semantic->name, "sv_", 3))
{
*usage = semantics[i].usage;
return true;
}
- }
- if (!ascii_strncasecmp(semantic->name, "sv_", 3))
return false;
- *usage = D3D_NAME_UNDEFINED;
- return true;
+}
I don't quite understand what's going on here. If I read it correctly you're basically ignoring all the table entries that don't start with "sv_". Is there some planned extension of this function where it will start to do something different?
+static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, bool output) +{
- struct vkd3d_bytecode_buffer buffer = {0};
- struct vkd3d_string_buffer *string;
- const struct hlsl_ir_var *var;
- size_t count_position;
- unsigned int i;
- bool ret;
- count_position = put_u32(&buffer, 0);
- put_u32(&buffer, 8); /* unknown */
- LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
- {
unsigned int width = (1u << var->data_type->dimx) - 1, use_mask;
enum vkd3d_sm4_register_type type;
uint32_t usage_idx, reg_idx;
D3D_NAME usage;
if ((output && !var->is_output_semantic) || (!output && !var->is_input_semantic))
continue;
ret = hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage);
assert(ret);
usage_idx = var->semantic.index;
if (!hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, ®_idx))
{
assert(var->reg.allocated);
type = VKD3D_SM4_RT_INPUT;
reg_idx = var->reg.id;
}
Somewhat similarly here, type doesn't seem to be used at all (yet).
use_mask = width; /* FIXME: accurately report use mask */
if (output)
use_mask = 0xf ^ use_mask;
Huh, that's interesting. I wonder if we're taking that into account elsewhere.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 116 +++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 894c513f..029dc3de 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -549,10 +549,120 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) dxbc_writer_add_section(dxbc, TAG_RDEF, buffer.data, buffer.size); }
+struct sm4_register +{ + enum vkd3d_sm4_register_type type; + uint32_t idx[2]; + unsigned int idx_count; + enum vkd3d_sm4_dimension dim; +}; + +struct sm4_instruction +{ + enum vkd3d_sm4_opcode opcode; + + struct + { + struct sm4_register reg; + unsigned int writemask; + } dst; + + struct + { + struct sm4_register reg; + unsigned int swizzle; + } srcs[2]; + unsigned int src_count; + + unsigned int has_dst; +}; + +static unsigned int sm4_swizzle_type(enum vkd3d_sm4_register_type type) +{ + switch (type) + { + case VKD3D_SM4_RT_CONSTBUFFER: + return VKD3D_SM4_SWIZZLE_VEC4; + + default: + FIXME("Unhandled register type %#x.\n", type); + return VKD3D_SM4_SWIZZLE_VEC4; + } +} + +static uint32_t sm4_encode_register(const struct sm4_register *reg) +{ + return (reg->type << VKD3D_SM4_REGISTER_TYPE_SHIFT) + | (reg->idx_count << VKD3D_SM4_REGISTER_ORDER_SHIFT) + | (reg->dim << VKD3D_SM4_DIMENSION_SHIFT); +} + +static uint32_t sm4_register_order(const struct sm4_register *reg) +{ + uint32_t order = 1; + if (reg->type == VKD3D_SM4_RT_IMMCONST) + order += reg->dim == VKD3D_SM4_DIMENSION_VEC4 ? 4 : 1; + order += reg->idx_count; + return order; +} + +static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const struct sm4_instruction *instr) +{ + uint32_t token = instr->opcode; + unsigned int size = 1, i, j; + + if (instr->has_dst) + size += sm4_register_order(&instr->dst.reg); + for (i = 0; i < instr->src_count; ++i) + size += sm4_register_order(&instr->srcs[i].reg); + + token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT); + put_u32(buffer, token); + + if (instr->has_dst) + { + token = sm4_encode_register(&instr->dst.reg); + if (instr->dst.reg.dim == VKD3D_SM4_DIMENSION_VEC4) + token |= instr->dst.writemask << VKD3D_SM4_WRITEMASK_SHIFT; + put_u32(buffer, token); + + for (j = 0; j < instr->dst.reg.idx_count; ++j) + put_u32(buffer, instr->dst.reg.idx[j]); + } + + for (i = 0; i < instr->src_count; ++i) + { + token = sm4_encode_register(&instr->srcs[i].reg); + token |= sm4_swizzle_type(instr->srcs[i].reg.type) << VKD3D_SM4_SWIZZLE_TYPE_SHIFT; + token |= instr->srcs[i].swizzle << VKD3D_SM4_SWIZZLE_SHIFT; + put_u32(buffer, token); + + for (j = 0; j < instr->srcs[i].reg.idx_count; ++j) + put_u32(buffer, instr->srcs[i].reg.idx[j]); + } +} + +static void write_sm4_dcl_constant_buffer(struct vkd3d_bytecode_buffer *buffer, const struct hlsl_buffer *cbuffer) +{ + const struct sm4_instruction instr = + { + .opcode = VKD3D_SM4_OP_DCL_CONSTANT_BUFFER, + + .srcs[0].reg.dim = VKD3D_SM4_DIMENSION_VEC4, + .srcs[0].reg.type = VKD3D_SM4_RT_CONSTBUFFER, + .srcs[0].reg.idx = {cbuffer->reg.id, (cbuffer->used_size + 3) / 4}, + .srcs[0].reg.idx_count = 2, + .srcs[0].swizzle = HLSL_SWIZZLE(X, Y, Z, W), + .src_count = 1, + }; + write_sm4_instruction(buffer, &instr); +} + static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) { const struct hlsl_profile_info *profile = ctx->profile; struct vkd3d_bytecode_buffer buffer = {0}; + const struct hlsl_buffer *cbuffer;
static const uint16_t shader_types[VKD3D_SHADER_TYPE_COUNT] = { @@ -570,6 +680,12 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) put_u32(&buffer, vkd3d_make_u32((profile->major_version << 4) | profile->minor_version, shader_types[profile->type])); put_u32(&buffer, 0); /* FIXME: instruction token count */
+ LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) + { + if (cbuffer->reg.allocated) + write_sm4_dcl_constant_buffer(&buffer, cbuffer); + } + dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
On Fri, Aug 20, 2021 at 1:45 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl_sm4.c | 116 +++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 894c513f..029dc3de 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -549,10 +549,120 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) dxbc_writer_add_section(dxbc, TAG_RDEF, buffer.data, buffer.size); }
+struct sm4_register +{
- enum vkd3d_sm4_register_type type;
- uint32_t idx[2];
- unsigned int idx_count;
- enum vkd3d_sm4_dimension dim;
+};
+struct sm4_instruction +{
- enum vkd3d_sm4_opcode opcode;
- struct
- {
struct sm4_register reg;
unsigned int writemask;
- } dst;
- struct
- {
struct sm4_register reg;
unsigned int swizzle;
- } srcs[2];
- unsigned int src_count;
- unsigned int has_dst;
+};
I think there are SM4 instructions with 2 dest registers. Just something to keep in mind for the future.
On Sun, 22 Aug 2021 at 21:14, Matteo Bruni matteo.mystral@gmail.com wrote:
I think there are SM4 instructions with 2 dest registers. Just something to keep in mind for the future.
Yes, several. For example, "sincos", "udiv", "umul", and "swapc".
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl_codegen.c | 4 +- libs/vkd3d-shader/hlsl_sm4.c | 117 ++++++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 9860ed7a..80cea512 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -688,7 +688,7 @@ int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, bool output, D3D_NAME *usage); bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, - bool output, enum vkd3d_sm4_register_type *type, uint32_t *reg); + bool output, enum vkd3d_sm4_register_type *type, bool *has_idx); int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hlsl); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 939b356c..a1d6e8e9 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1048,6 +1048,7 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var else { D3D_NAME usage; + bool has_idx;
if (!hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage)) { @@ -1055,7 +1056,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var "Invalid semantic '%s'.", var->semantic.name); return; } - builtin = hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, ®); + if ((builtin = hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, &has_idx))) + reg = has_idx ? var->semantic.index : 0; }
if (builtin) diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 029dc3de..92f854c0 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -24,7 +24,7 @@ #include "sm4.h"
bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, - bool output, enum vkd3d_sm4_register_type *type, uint32_t *reg) + bool output, enum vkd3d_sm4_register_type *type, bool *has_idx) { unsigned int i;
@@ -56,7 +56,7 @@ bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem && ctx->profile->type == register_table[i].shader_type) { *type = register_table[i].type; - *reg = register_table[i].has_idx ? semantic->index : ~0u; + *has_idx = register_table[i].has_idx; return true; } } @@ -137,6 +137,7 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, enum vkd3d_sm4_register_type type; uint32_t usage_idx, reg_idx; D3D_NAME usage; + bool has_idx;
if ((output && !var->is_output_semantic) || (!output && !var->is_input_semantic)) continue; @@ -145,7 +146,11 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, assert(ret); usage_idx = var->semantic.index;
- if (!hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, ®_idx)) + if (hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, &has_idx)) + { + reg_idx = has_idx ? var->semantic.index : ~0u; + } + else { assert(var->reg.allocated); type = VKD3D_SM4_RT_INPUT; @@ -574,6 +579,9 @@ struct sm4_instruction } srcs[2]; unsigned int src_count;
+ uint32_t idx[2]; + unsigned int idx_count; + unsigned int has_dst; };
@@ -582,6 +590,7 @@ static unsigned int sm4_swizzle_type(enum vkd3d_sm4_register_type type) switch (type) { case VKD3D_SM4_RT_CONSTBUFFER: + case VKD3D_SM4_RT_INPUT: return VKD3D_SM4_SWIZZLE_VEC4;
default: @@ -615,6 +624,7 @@ static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const st size += sm4_register_order(&instr->dst.reg); for (i = 0; i < instr->src_count; ++i) size += sm4_register_order(&instr->srcs[i].reg); + size += instr->idx_count;
token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT); put_u32(buffer, token); @@ -640,6 +650,9 @@ static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const st for (j = 0; j < instr->srcs[i].reg.idx_count; ++j) put_u32(buffer, instr->srcs[i].reg.idx[j]); } + + for (j = 0; j < instr->idx_count; ++j) + put_u32(buffer, instr->idx[j]); }
static void write_sm4_dcl_constant_buffer(struct vkd3d_bytecode_buffer *buffer, const struct hlsl_buffer *cbuffer) @@ -658,11 +671,103 @@ static void write_sm4_dcl_constant_buffer(struct vkd3d_bytecode_buffer *buffer, write_sm4_instruction(buffer, &instr); }
+static void write_sm4_dcl_semantic(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_var *var) +{ + const struct hlsl_profile_info *profile = ctx->profile; + const bool output = var->is_output_semantic; + D3D_NAME usage; + bool has_idx; + + struct sm4_instruction instr = + { + .dst.reg.dim = VKD3D_SM4_DIMENSION_VEC4, + .has_dst = 1, + }; + + if (hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &instr.dst.reg.type, &has_idx)) + { + if (has_idx) + { + instr.dst.reg.idx[0] = var->semantic.index; + instr.dst.reg.idx_count = 1; + } + else + { + instr.dst.reg.idx_count = 0; + } + instr.dst.writemask = (1 << var->data_type->dimx) - 1; + } + else + { + instr.dst.reg.type = output ? VKD3D_SM4_RT_OUTPUT : VKD3D_SM4_RT_INPUT; + instr.dst.reg.idx[0] = var->reg.id; + instr.dst.reg.idx_count = 1; + instr.dst.writemask = var->reg.writemask; + } + + if (instr.dst.reg.type == VKD3D_SM4_RT_DEPTHOUT) + instr.dst.reg.dim = VKD3D_SM4_DIMENSION_SCALAR; + + hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage); + + if (var->is_input_semantic) + { + switch (usage) + { + case D3D_NAME_UNDEFINED: + instr.opcode = (profile->type == VKD3D_SHADER_TYPE_PIXEL) + ? VKD3D_SM4_OP_DCL_INPUT_PS : VKD3D_SM4_OP_DCL_INPUT; + break; + + case D3D_NAME_INSTANCE_ID: + case D3D_NAME_PRIMITIVE_ID: + case D3D_NAME_VERTEX_ID: + instr.opcode = (profile->type == VKD3D_SHADER_TYPE_PIXEL) + ? VKD3D_SM4_OP_DCL_INPUT_PS_SGV : VKD3D_SM4_OP_DCL_INPUT_SGV; + break; + + default: + instr.opcode = (profile->type == VKD3D_SHADER_TYPE_PIXEL) + ? VKD3D_SM4_OP_DCL_INPUT_PS_SIV : VKD3D_SM4_OP_DCL_INPUT_SIV; + break; + } + + if (profile->type == VKD3D_SHADER_TYPE_PIXEL) + instr.opcode |= VKD3DSIM_LINEAR << VKD3D_SM4_INTERPOLATION_MODE_SHIFT; + } + else + { + if (usage == D3D_NAME_UNDEFINED || profile->type == VKD3D_SHADER_TYPE_PIXEL) + instr.opcode = VKD3D_SM4_OP_DCL_OUTPUT; + else + instr.opcode = VKD3D_SM4_OP_DCL_OUTPUT_SIV; + } + + switch (usage) + { + case D3D_NAME_COVERAGE: + case D3D_NAME_DEPTH: + case D3D_NAME_DEPTH_GREATER_EQUAL: + case D3D_NAME_DEPTH_LESS_EQUAL: + case D3D_NAME_TARGET: + case D3D_NAME_UNDEFINED: + break; + + default: + instr.idx_count = 1; + instr.idx[0] = usage; + break; + } + + write_sm4_instruction(buffer, &instr); +} + static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) { const struct hlsl_profile_info *profile = ctx->profile; struct vkd3d_bytecode_buffer buffer = {0}; const struct hlsl_buffer *cbuffer; + const struct hlsl_ir_var *var;
static const uint16_t shader_types[VKD3D_SHADER_TYPE_COUNT] = { @@ -686,6 +791,12 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) write_sm4_dcl_constant_buffer(&buffer, cbuffer); }
+ 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)) + write_sm4_dcl_semantic(ctx, &buffer, var); + } + dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
On Fri, Aug 20, 2021 at 1:45 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl_codegen.c | 4 +- libs/vkd3d-shader/hlsl_sm4.c | 117 ++++++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 029dc3de..92f854c0 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -658,11 +671,103 @@ static void write_sm4_dcl_constant_buffer(struct vkd3d_bytecode_buffer *buffer, write_sm4_instruction(buffer, &instr); }
+static void write_sm4_dcl_semantic(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_var *var) +{
- const struct hlsl_profile_info *profile = ctx->profile;
- const bool output = var->is_output_semantic;
- D3D_NAME usage;
- bool has_idx;
- struct sm4_instruction instr =
- {
.dst.reg.dim = VKD3D_SM4_DIMENSION_VEC4,
.has_dst = 1,
- };
- if (hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &instr.dst.reg.type, &has_idx))
- {
if (has_idx)
{
instr.dst.reg.idx[0] = var->semantic.index;
instr.dst.reg.idx_count = 1;
}
else
{
instr.dst.reg.idx_count = 0;
}
instr.dst.writemask = (1 << var->data_type->dimx) - 1;
- }
- else
- {
instr.dst.reg.type = output ? VKD3D_SM4_RT_OUTPUT : VKD3D_SM4_RT_INPUT;
instr.dst.reg.idx[0] = var->reg.id;
instr.dst.reg.idx_count = 1;
instr.dst.writemask = var->reg.writemask;
- }
- if (instr.dst.reg.type == VKD3D_SM4_RT_DEPTHOUT)
instr.dst.reg.dim = VKD3D_SM4_DIMENSION_SCALAR;
- hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage);
- if (var->is_input_semantic)
- {
switch (usage)
{
case D3D_NAME_UNDEFINED:
instr.opcode = (profile->type == VKD3D_SHADER_TYPE_PIXEL)
? VKD3D_SM4_OP_DCL_INPUT_PS : VKD3D_SM4_OP_DCL_INPUT;
break;
case D3D_NAME_INSTANCE_ID:
case D3D_NAME_PRIMITIVE_ID:
case D3D_NAME_VERTEX_ID:
instr.opcode = (profile->type == VKD3D_SHADER_TYPE_PIXEL)
? VKD3D_SM4_OP_DCL_INPUT_PS_SGV : VKD3D_SM4_OP_DCL_INPUT_SGV;
break;
default:
instr.opcode = (profile->type == VKD3D_SHADER_TYPE_PIXEL)
? VKD3D_SM4_OP_DCL_INPUT_PS_SIV : VKD3D_SM4_OP_DCL_INPUT_SIV;
break;
}
if (profile->type == VKD3D_SHADER_TYPE_PIXEL)
instr.opcode |= VKD3DSIM_LINEAR << VKD3D_SM4_INTERPOLATION_MODE_SHIFT;
This probably deserves a FIXME I guess?
Mostly unrelated to the patch, I see that we currently don't parse the centroid modifier. Just mentioning it for a possible, separate follow up patch.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl_codegen.c | 4 ++++ libs/vkd3d-shader/hlsl_sm4.c | 16 ++++++++++++++++ 3 files changed, 21 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 80cea512..9b579b72 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -469,6 +469,7 @@ struct hlsl_ctx struct hlsl_vec4 *values; size_t count, size; } constant_defs; + uint32_t temp_count; };
enum hlsl_error_level diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index a1d6e8e9..c2aeb7b0 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -685,6 +685,7 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl struct liveness { size_t size; + uint32_t reg_count; struct { /* 0 if not live yet. */ @@ -747,6 +748,7 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct liveness * ret.id = component_idx / 4; ret.writemask = writemask; ret.allocated = true; + liveness->reg_count = max(liveness->reg_count, ret.id + 1); return ret; }
@@ -782,6 +784,7 @@ static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct liveness *liv liveness->regs[component_idx + i].last_read = last_read; ret.id = component_idx / 4; ret.allocated = true; + liveness->reg_count = max(liveness->reg_count, ret.id + align(component_count, 4)); return ret; }
@@ -1008,6 +1011,7 @@ static void allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functio { struct liveness liveness = {0}; allocate_temp_registers_recurse(ctx, entry_func->body, &liveness); + ctx->temp_count = liveness.reg_count; }
static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, unsigned int *counter, bool output) diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 92f854c0..a66bcaae 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -762,6 +762,19 @@ static void write_sm4_dcl_semantic(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b write_sm4_instruction(buffer, &instr); }
+static void write_sm4_dcl_temps(struct vkd3d_bytecode_buffer *buffer, uint32_t temp_count) +{ + struct sm4_instruction instr = + { + .opcode = VKD3D_SM4_OP_DCL_TEMPS, + + .idx = {temp_count}, + .idx_count = 1, + }; + + write_sm4_instruction(buffer, &instr); +} + static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) { const struct hlsl_profile_info *profile = ctx->profile; @@ -797,6 +810,9 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) write_sm4_dcl_semantic(ctx, &buffer, var); }
+ if (ctx->temp_count) + write_sm4_dcl_temps(&buffer, ctx->temp_count); + dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index a66bcaae..253aa24d 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -775,6 +775,16 @@ static void write_sm4_dcl_temps(struct vkd3d_bytecode_buffer *buffer, uint32_t t write_sm4_instruction(buffer, &instr); }
+static void write_sm4_ret(struct vkd3d_bytecode_buffer *buffer) +{ + struct sm4_instruction instr = + { + .opcode = VKD3D_SM4_OP_RET, + }; + + write_sm4_instruction(buffer, &instr); +} + static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) { const struct hlsl_profile_info *profile = ctx->profile; @@ -813,6 +823,8 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) if (ctx->temp_count) write_sm4_dcl_temps(&buffer, ctx->temp_count);
+ write_sm4_ret(&buffer); + dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 253aa24d..15927671 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -791,6 +791,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) struct vkd3d_bytecode_buffer buffer = {0}; const struct hlsl_buffer *cbuffer; const struct hlsl_ir_var *var; + size_t token_count_position;
static const uint16_t shader_types[VKD3D_SHADER_TYPE_COUNT] = { @@ -806,7 +807,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) };
put_u32(&buffer, vkd3d_make_u32((profile->major_version << 4) | profile->minor_version, shader_types[profile->type])); - put_u32(&buffer, 0); /* FIXME: instruction token count */ + token_count_position = put_u32(&buffer, 0);
LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) { @@ -825,6 +826,8 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
write_sm4_ret(&buffer);
+ set_u32(&buffer, token_count_position, bytecode_get_size(&buffer) / sizeof(uint32_t)); + dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com