mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader/hlsl: Write SM4 signatures.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Matteo Bruni <mbruni@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
486c525dc1
commit
464dae2c46
@ -166,6 +166,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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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, ®))
|
||||
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))
|
||||
{
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user