Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • wine/vkd3d
  • stefan/vkd3d
  • cmccarthy/vkd3d
  • giomasce/vkd3d
  • fcasas/vkd3d
  • jactry/vkd3d
  • ReDress/vkd3d
  • mstorsjo/vkd3d
  • huw/vkd3d
  • julliard/vkd3d
  • bshanks/vkd3d
  • zfigura/vkd3d
  • hverbeet/vkd3d
  • DarkShadow44/vkd3d
  • nsivov/vkd3d
  • dhary686/vkd3d
  • Mystral/vkd3d
  • maljaf/vkd3d
  • smcv/vkd3d
  • flibitijibibo/vkd3d
  • q4a/vkd3d
  • jsikorski/vkd3d
  • alesliehughes/vkd3d-alesliehughes
  • vitorhnn/vkd3d
  • agusev/vkd3d
  • etang-cw/vkd3d
  • petrathekat/vkd3d
  • simon.mr995/vkd3d
  • sgwaki/vkd3d
  • jacek/vkd3d
  • fweimer/vkd3d
  • Clara/vkd3d
  • disini/vkd3d
  • antenabr2/vkd3d
  • gilvbp/vkd3d
  • yshui/vkd3d
  • shaunren/vkd3d
  • jennetsaryyewa96/vkd3d
  • Jamesattay/vkd3d
  • zacemmneeto77/vkd3d
  • GermanAizek/vkd3d
  • opespinach/vkd3d
  • ruslanboyka201/vkd3d
  • navi/vkd3d
  • Feifan/vkd3d
  • yashmhmdly172/vkd3d
  • Sec32fun32/vkd3d
  • ritalat/vkd3d
  • ivyl/vkd3d
  • baikaishiuc/vkd3d
  • austin987/vkd3d
  • TornadoCookie/vkd3d
52 results
Show changes
Commits on Source (10)
......@@ -989,7 +989,7 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi
*parser = &sm1->p;
return VKD3D_OK;
return sm1->p.failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK;
}
bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
......@@ -1832,7 +1832,12 @@ static void write_sm1_store(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *
if (store->lhs.var->is_output_semantic)
{
if (!hlsl_sm1_register_from_semantic(ctx, &store->lhs.var->semantic,
if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL && ctx->profile->major_version == 1)
{
sm1_instr.dst.type = D3DSPR_TEMP;
sm1_instr.dst.reg = 0;
}
else if (!hlsl_sm1_register_from_semantic(ctx, &store->lhs.var->semantic,
true, &sm1_instr.dst.type, &sm1_instr.dst.reg))
{
assert(reg.allocated);
......
......@@ -322,12 +322,12 @@ int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
}
static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *s)
struct vkd3d_shader_message_context *message_context, struct shader_signature *s)
{
bool has_stream_index, has_min_precision;
struct vkd3d_shader_signature_element *e;
const char *data = section->data.code;
uint32_t count, header_size;
struct signature_element *e;
const char *ptr = data;
unsigned int i;
......@@ -389,6 +389,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
read_dword(&ptr, &e[i].sysval_semantic);
read_dword(&ptr, &e[i].component_type);
read_dword(&ptr, &e[i].register_index);
e[i].register_count = 1;
read_dword(&ptr, &mask);
e[i].mask = mask & 0xff;
e[i].used_mask = (mask >> 8) & 0xff;
......@@ -423,7 +424,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
static int isgn_handler(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, void *ctx)
{
struct vkd3d_shader_signature *is = ctx;
struct shader_signature *is = ctx;
if (section->tag != TAG_ISGN)
return VKD3D_OK;
......@@ -431,13 +432,13 @@ static int isgn_handler(const struct vkd3d_shader_dxbc_section_desc *section,
if (is->elements)
{
FIXME("Multiple input signatures.\n");
vkd3d_shader_free_shader_signature(is);
shader_signature_cleanup(is);
}
return shader_parse_signature(section, message_context, is);
}
int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature)
struct vkd3d_shader_message_context *message_context, struct shader_signature *signature)
{
int ret;
......@@ -516,9 +517,9 @@ static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section,
void free_shader_desc(struct vkd3d_shader_desc *desc)
{
vkd3d_shader_free_shader_signature(&desc->input_signature);
vkd3d_shader_free_shader_signature(&desc->output_signature);
vkd3d_shader_free_shader_signature(&desc->patch_constant_signature);
shader_signature_cleanup(&desc->input_signature);
shader_signature_cleanup(&desc->output_signature);
shader_signature_cleanup(&desc->patch_constant_signature);
}
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
......
......@@ -1369,6 +1369,11 @@ bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index)
return type->class == HLSL_CLASS_MATRIX && !hlsl_type_is_row_major(type);
}
bool hlsl_index_is_resource_access(struct hlsl_ir_index *index)
{
return index->val.node->data_type->class == HLSL_CLASS_OBJECT;
}
struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *val,
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc)
{
......
......@@ -1106,6 +1106,7 @@ struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl
const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs);
bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index);
bool hlsl_index_is_resource_access(struct hlsl_ir_index *index);
struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *val,
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc);
......
......@@ -712,39 +712,6 @@ static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, str
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
const struct vkd3d_shader_location *loc);
static struct hlsl_ir_node *add_zero_mipmap_level(struct hlsl_ctx *ctx, struct list *instrs,
struct hlsl_ir_node *index, unsigned int dim_count, const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_load *coords_load;
struct hlsl_deref coords_deref;
struct hlsl_ir_constant *zero;
struct hlsl_ir_store *store;
struct hlsl_ir_var *coords;
if (!(coords = hlsl_new_synthetic_var(ctx, "coords",
hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count + 1), loc)))
return NULL;
hlsl_init_simple_deref_from_var(&coords_deref, coords);
if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, index, (1u << dim_count) - 1, loc)))
return NULL;
list_add_tail(instrs, &store->node.entry);
if (!(zero = hlsl_new_uint_constant(ctx, 0, loc)))
return NULL;
list_add_tail(instrs, &zero->node.entry);
if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, &zero->node, 1u << dim_count, loc)))
return NULL;
list_add_tail(instrs, &store->node.entry);
if (!(coords_load = hlsl_new_var_load(ctx, coords, loc)))
return NULL;
list_add_tail(instrs, &coords_load->node.entry);
return &coords_load->node;
}
static bool add_array_access(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *array,
struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc)
{
......@@ -755,9 +722,7 @@ static bool add_array_access(struct hlsl_ctx *ctx, struct list *instrs, struct h
&& (expr_type->base_type == HLSL_TYPE_TEXTURE || expr_type->base_type == HLSL_TYPE_UAV)
&& expr_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC)
{
struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_LOAD};
unsigned int dim_count = hlsl_sampler_dim_count(expr_type->sampler_dim);
struct hlsl_ir_node *resource_load;
if (index_type->class > HLSL_CLASS_VECTOR || index_type->dimx != dim_count)
{
......@@ -774,16 +739,10 @@ static bool add_array_access(struct hlsl_ctx *ctx, struct list *instrs, struct h
hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count), &index->loc)))
return false;
if (!(index = add_zero_mipmap_level(ctx, instrs, index, dim_count, loc)))
if (!(return_index = hlsl_new_index(ctx, array, index, loc)))
return false;
list_add_tail(instrs, &return_index->entry);
load_params.format = expr_type->e.resource_format;
load_params.resource = array;
load_params.coords = index;
if (!(resource_load = hlsl_new_resource_load(ctx, &load_params, loc)))
return false;
list_add_tail(instrs, &resource_load->entry);
return true;
}
......@@ -1716,7 +1675,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in
if (!(rhs = add_implicit_conversion(ctx, instrs, rhs, lhs_type, &rhs->loc)))
return NULL;
while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_RESOURCE_LOAD && lhs->type != HLSL_IR_INDEX)
while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_INDEX)
{
if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST)
{
......@@ -1753,17 +1712,18 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in
}
}
if (lhs->type == HLSL_IR_RESOURCE_LOAD)
if (lhs->type == HLSL_IR_INDEX && hlsl_index_is_resource_access(hlsl_ir_index(lhs)))
{
struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(lhs);
struct hlsl_ir_node *coords = hlsl_ir_index(lhs)->idx.node;
struct hlsl_deref resource_deref;
struct hlsl_type *resource_type;
struct hlsl_ir_swizzle *coords;
struct hlsl_ir_node *store;
unsigned int dim_count;
/* Such an lvalue was produced by an index expression. */
assert(load->load_type == HLSL_RESOURCE_LOAD);
resource_type = hlsl_deref_get_type(ctx, &load->resource);
if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, hlsl_ir_index(lhs)->val.node))
return NULL;
resource_type = hlsl_deref_get_type(ctx, &resource_deref);
assert(resource_type->class == HLSL_CLASS_OBJECT);
assert(resource_type->base_type == HLSL_TYPE_TEXTURE || resource_type->base_type == HLSL_TYPE_UAV);
......@@ -1777,17 +1737,17 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK,
"Resource store expressions must write to all components.");
/* Remove the (implicit) mipmap level from the load expression. */
assert(load->coords.node->data_type->class == HLSL_CLASS_VECTOR);
assert(load->coords.node->data_type->base_type == HLSL_TYPE_UINT);
assert(load->coords.node->data_type->dimx == dim_count + 1);
if (!(coords = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), dim_count, load->coords.node, &lhs->loc)))
return NULL;
list_add_tail(instrs, &coords->node.entry);
assert(coords->data_type->class == HLSL_CLASS_VECTOR);
assert(coords->data_type->base_type == HLSL_TYPE_UINT);
assert(coords->data_type->dimx == dim_count);
if (!(store = hlsl_new_resource_store(ctx, &load->resource, &coords->node, rhs, &lhs->loc)))
if (!(store = hlsl_new_resource_store(ctx, &resource_deref, coords, rhs, &lhs->loc)))
{
hlsl_cleanup_deref(&resource_deref);
return NULL;
}
list_add_tail(instrs, &store->entry);
hlsl_cleanup_deref(&resource_deref);
}
else if (lhs->type == HLSL_IR_INDEX && hlsl_index_is_noncontiguous(hlsl_ir_index(lhs)))
{
......
......@@ -858,11 +858,48 @@ static bool lower_calls(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *
return true;
}
static struct hlsl_ir_node *add_zero_mipmap_level(struct hlsl_ctx *ctx, struct hlsl_ir_node *index,
const struct vkd3d_shader_location *loc)
{
unsigned int dim_count = index->data_type->dimx;
struct hlsl_ir_load *coords_load;
struct hlsl_deref coords_deref;
struct hlsl_ir_constant *zero;
struct hlsl_ir_store *store;
struct hlsl_ir_var *coords;
assert(dim_count < 4);
if (!(coords = hlsl_new_synthetic_var(ctx, "coords",
hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count + 1), loc)))
return NULL;
hlsl_init_simple_deref_from_var(&coords_deref, coords);
if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, index, (1u << dim_count) - 1, loc)))
return NULL;
list_add_after(&index->entry, &store->node.entry);
if (!(zero = hlsl_new_uint_constant(ctx, 0, loc)))
return NULL;
list_add_after(&store->node.entry, &zero->node.entry);
if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, &zero->node, 1u << dim_count, loc)))
return NULL;
list_add_after(&zero->node.entry, &store->node.entry);
if (!(coords_load = hlsl_new_var_load(ctx, coords, loc)))
return NULL;
list_add_after(&store->node.entry, &coords_load->node.entry);
return &coords_load->node;
}
/* hlsl_ir_index nodes are a parse-time construct used to represent array indexing and struct
* record access before knowing if they will be used in the lhs of an assignment --in which case
* they are lowered into a deref-- or as the load of an element within a larger value.
* For the latter case, this pass takes care of lowering hlsl_ir_indexes into individual
* hlsl_ir_loads. */
* hlsl_ir_loads, or individual hlsl_ir_resource_loads, in case the indexing is a
* resource access. */
static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_deref var_deref;
......@@ -877,6 +914,32 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
index = hlsl_ir_index(instr);
val = index->val.node;
if (hlsl_index_is_resource_access(index))
{
unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim);
struct hlsl_ir_node *coords = index->idx.node;
struct hlsl_resource_load_params params = {0};
struct hlsl_ir_node *load;
assert(coords->data_type->class == HLSL_CLASS_VECTOR);
assert(coords->data_type->base_type == HLSL_TYPE_UINT);
assert(coords->data_type->dimx == dim_count);
if (!(coords = add_zero_mipmap_level(ctx, coords, &instr->loc)))
return false;
params.type = HLSL_RESOURCE_LOAD;
params.resource = val;
params.coords = coords;
params.format = val->data_type->e.resource_format;
if (!(load = hlsl_new_resource_load(ctx, &params, &instr->loc)))
return false;
list_add_before(&instr->entry, &load->entry);
hlsl_replace_node(instr, load);
return true;
}
if (!(var = hlsl_new_synthetic_var(ctx, "index-val", val->data_type, &instr->loc)))
return false;
hlsl_init_simple_deref_from_var(&var_deref, var);
......@@ -2680,127 +2743,140 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
compute_liveness_recurse(&entry_func->body, 0, 0);
}
struct liveness
struct register_allocator
{
size_t size;
uint32_t reg_count;
struct
size_t count, capacity;
/* Highest register index that has been allocated.
* Used to declare sm4 temp count. */
uint32_t max_reg;
struct allocation
{
/* 0 if not live yet. */
unsigned int last_read;
} *regs;
uint32_t reg;
unsigned int writemask;
unsigned int first_write, last_read;
} *allocations;
};
static unsigned int get_available_writemask(struct liveness *liveness,
unsigned int first_write, unsigned int component_idx, unsigned int reg_size)
static unsigned int get_available_writemask(const struct register_allocator *allocator,
unsigned int first_write, unsigned int last_read, uint32_t reg_idx)
{
unsigned int i, writemask = 0, count = 0;
unsigned int writemask = VKD3DSP_WRITEMASK_ALL;
size_t i;
for (i = 0; i < 4; ++i)
for (i = 0; i < allocator->count; ++i)
{
if (liveness->regs[component_idx + i].last_read <= first_write)
{
writemask |= 1u << i;
if (++count == reg_size)
return writemask;
}
const struct allocation *allocation = &allocator->allocations[i];
/* We do not overlap if first write == last read:
* this is the case where we are allocating the result of that
* expression, e.g. "add r0, r0, r1". */
if (allocation->reg == reg_idx
&& first_write < allocation->last_read && last_read > allocation->first_write)
writemask &= ~allocation->writemask;
if (!writemask)
break;
}
return 0;
return writemask;
}
static bool resize_liveness(struct hlsl_ctx *ctx, struct liveness *liveness, size_t new_count)
static void record_allocation(struct hlsl_ctx *ctx, struct register_allocator *allocator,
uint32_t reg_idx, unsigned int writemask, unsigned int first_write, unsigned int last_read)
{
size_t old_capacity = liveness->size;
struct allocation *allocation;
if (!hlsl_array_reserve(ctx, (void **)&liveness->regs, &liveness->size, new_count, sizeof(*liveness->regs)))
return false;
if (!hlsl_array_reserve(ctx, (void **)&allocator->allocations, &allocator->capacity,
allocator->count + 1, sizeof(*allocator->allocations)))
return;
if (liveness->size > old_capacity)
memset(liveness->regs + old_capacity, 0, (liveness->size - old_capacity) * sizeof(*liveness->regs));
return true;
allocation = &allocator->allocations[allocator->count++];
allocation->reg = reg_idx;
allocation->writemask = writemask;
allocation->first_write = first_write;
allocation->last_read = last_read;
allocator->max_reg = max(allocator->max_reg, reg_idx);
}
/* reg_size is the number of register components to be reserved, while component_count is the number
* of components for the register's writemask. In SM1, floats and vectors allocate the whole
* register, even if they don't use it completely. */
static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct liveness *liveness,
static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_allocator *allocator,
unsigned int first_write, unsigned int last_read, unsigned int reg_size,
unsigned int component_count)
{
unsigned int component_idx, writemask, i;
struct hlsl_reg ret = {0};
unsigned int writemask;
uint32_t reg_idx;
assert(component_count <= reg_size);
for (component_idx = 0; component_idx < liveness->size; component_idx += 4)
for (reg_idx = 0;; ++reg_idx)
{
if ((writemask = get_available_writemask(liveness, first_write, component_idx, reg_size)))
writemask = get_available_writemask(allocator, first_write, last_read, reg_idx);
if (vkd3d_popcount(writemask) >= reg_size)
{
writemask = hlsl_combine_writemasks(writemask, (1u << reg_size) - 1);
break;
}
}
if (component_idx == liveness->size)
{
if (!resize_liveness(ctx, liveness, component_idx + 4))
return ret;
writemask = (1u << reg_size) - 1;
}
for (i = 0; i < 4; ++i)
{
if (writemask & (1u << i))
liveness->regs[component_idx + i].last_read = last_read;
}
ret.id = component_idx / 4;
record_allocation(ctx, allocator, reg_idx, writemask, first_write, last_read);
ret.id = reg_idx;
ret.writemask = hlsl_combine_writemasks(writemask, (1u << component_count) - 1);
ret.allocated = true;
liveness->reg_count = max(liveness->reg_count, ret.id + 1);
return ret;
}
static bool is_range_available(struct liveness *liveness, unsigned int first_write,
unsigned int component_idx, unsigned int reg_size)
static bool is_range_available(const struct register_allocator *allocator,
unsigned int first_write, unsigned int last_read, uint32_t reg_idx, unsigned int reg_size)
{
unsigned int i;
uint32_t i;
for (i = 0; i < reg_size; i += 4)
for (i = 0; i < (reg_size / 4); ++i)
{
if (!get_available_writemask(liveness, first_write, component_idx + i, 4))
if (get_available_writemask(allocator, first_write, last_read, reg_idx + i) != VKD3DSP_WRITEMASK_ALL)
return false;
}
return true;
}
static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct liveness *liveness,
static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allocator *allocator,
unsigned int first_write, unsigned int last_read, unsigned int reg_size)
{
unsigned int i, component_idx;
struct hlsl_reg ret = {0};
uint32_t reg_idx;
unsigned int i;
for (component_idx = 0; component_idx < liveness->size; component_idx += 4)
for (reg_idx = 0;; ++reg_idx)
{
if (is_range_available(liveness, first_write, component_idx,
min(reg_size, liveness->size - component_idx)))
if (is_range_available(allocator, first_write, last_read, reg_idx, reg_size))
break;
}
if (!resize_liveness(ctx, liveness, component_idx + reg_size))
return ret;
for (i = 0; i < reg_size; ++i)
liveness->regs[component_idx + i].last_read = last_read;
ret.id = component_idx / 4;
for (i = 0; i < reg_size / 4; ++i)
record_allocation(ctx, allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, first_write, last_read);
ret.id = reg_idx;
ret.allocated = true;
liveness->reg_count = max(liveness->reg_count, ret.id + align(reg_size, 4));
return ret;
}
static struct hlsl_reg allocate_numeric_registers_for_type(struct hlsl_ctx *ctx, struct liveness *liveness,
static struct hlsl_reg allocate_numeric_registers_for_type(struct hlsl_ctx *ctx, struct register_allocator *allocator,
unsigned int first_write, unsigned int last_read, const struct hlsl_type *type)
{
unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC];
if (type->class <= HLSL_CLASS_VECTOR)
return allocate_register(ctx, liveness, first_write, last_read, reg_size, type->dimx);
return allocate_register(ctx, allocator, first_write, last_read, reg_size, type->dimx);
else
return allocate_range(ctx, liveness, first_write, last_read, reg_size);
return allocate_range(ctx, allocator, first_write, last_read, reg_size);
}
static const char *debug_register(char class, struct hlsl_reg reg, const struct hlsl_type *type)
......@@ -2819,14 +2895,15 @@ static const char *debug_register(char class, struct hlsl_reg reg, const struct
return vkd3d_dbg_sprintf("%c%u%s", class, reg.id, debug_hlsl_writemask(reg.writemask));
}
static void allocate_variable_temp_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct liveness *liveness)
static void allocate_variable_temp_register(struct hlsl_ctx *ctx,
struct hlsl_ir_var *var, struct register_allocator *allocator)
{
if (var->is_input_semantic || var->is_output_semantic || var->is_uniform)
return;
if (!var->regs[HLSL_REGSET_NUMERIC].allocated && var->last_read)
{
var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, liveness,
var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, allocator,
var->first_write, var->last_read, var->data_type);
TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, debug_register('r',
......@@ -2834,7 +2911,8 @@ static void allocate_variable_temp_register(struct hlsl_ctx *ctx, struct hlsl_ir
}
}
static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct liveness *liveness)
static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx,
struct hlsl_block *block, struct register_allocator *allocator)
{
struct hlsl_ir_node *instr;
......@@ -2842,7 +2920,7 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_bl
{
if (!instr->reg.allocated && instr->last_read)
{
instr->reg = allocate_numeric_registers_for_type(ctx, liveness, instr->index, instr->last_read,
instr->reg = allocate_numeric_registers_for_type(ctx, allocator, instr->index, instr->last_read,
instr->data_type);
TRACE("Allocated anonymous expression @%u to %s (liveness %u-%u).\n", instr->index,
debug_register('r', instr->reg, instr->data_type), instr->index, instr->last_read);
......@@ -2853,8 +2931,8 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_bl
case HLSL_IR_IF:
{
struct hlsl_ir_if *iff = hlsl_ir_if(instr);
allocate_temp_registers_recurse(ctx, &iff->then_block, liveness);
allocate_temp_registers_recurse(ctx, &iff->else_block, liveness);
allocate_temp_registers_recurse(ctx, &iff->then_block, allocator);
allocate_temp_registers_recurse(ctx, &iff->else_block, allocator);
break;
}
......@@ -2863,21 +2941,21 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_bl
struct hlsl_ir_load *load = hlsl_ir_load(instr);
/* We need to at least allocate a variable for undefs.
* FIXME: We should probably find a way to remove them instead. */
allocate_variable_temp_register(ctx, load->src.var, liveness);
allocate_variable_temp_register(ctx, load->src.var, allocator);
break;
}
case HLSL_IR_LOOP:
{
struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
allocate_temp_registers_recurse(ctx, &loop->body, liveness);
allocate_temp_registers_recurse(ctx, &loop->body, allocator);
break;
}
case HLSL_IR_STORE:
{
struct hlsl_ir_store *store = hlsl_ir_store(instr);
allocate_variable_temp_register(ctx, store->lhs.var, liveness);
allocate_variable_temp_register(ctx, store->lhs.var, allocator);
break;
}
......@@ -2887,7 +2965,8 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_bl
}
}
static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct liveness *liveness)
static void allocate_const_registers_recurse(struct hlsl_ctx *ctx,
struct hlsl_block *block, struct register_allocator *allocator)
{
struct hlsl_constant_defs *defs = &ctx->constant_defs;
struct hlsl_ir_node *instr;
......@@ -2903,7 +2982,7 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_b
unsigned int x, y, i, writemask, end_reg;
unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC];
constant->reg = allocate_numeric_registers_for_type(ctx, liveness, 1, UINT_MAX, type);
constant->reg = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type);
TRACE("Allocated constant @%u to %s.\n", instr->index, debug_register('c', constant->reg, type));
if (!hlsl_array_reserve(ctx, (void **)&defs->values, &defs->size,
......@@ -2968,15 +3047,15 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_b
case HLSL_IR_IF:
{
struct hlsl_ir_if *iff = hlsl_ir_if(instr);
allocate_const_registers_recurse(ctx, &iff->then_block, liveness);
allocate_const_registers_recurse(ctx, &iff->else_block, liveness);
allocate_const_registers_recurse(ctx, &iff->then_block, allocator);
allocate_const_registers_recurse(ctx, &iff->else_block, allocator);
break;
}
case HLSL_IR_LOOP:
{
struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
allocate_const_registers_recurse(ctx, &loop->body, liveness);
allocate_const_registers_recurse(ctx, &loop->body, allocator);
break;
}
......@@ -2988,10 +3067,10 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_b
static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
{
struct liveness liveness = {0};
struct register_allocator allocator = {0};
struct hlsl_ir_var *var;
allocate_const_registers_recurse(ctx, &entry_func->body, &liveness);
allocate_const_registers_recurse(ctx, &entry_func->body, &allocator);
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
......@@ -3002,12 +3081,14 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi
if (reg_size == 0)
continue;
var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, &liveness,
var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, &allocator,
1, UINT_MAX, var->data_type);
TRACE("Allocated %s to %s.\n", var->name,
debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type));
}
}
vkd3d_free(allocator.allocations);
}
/* Simple greedy temporary register allocation pass that just assigns a unique
......@@ -3016,10 +3097,28 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi
* does not handle constants. */
static void allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
{
struct liveness liveness = {0};
allocate_temp_registers_recurse(ctx, &entry_func->body, &liveness);
ctx->temp_count = liveness.reg_count;
vkd3d_free(liveness.regs);
struct register_allocator allocator = {0};
/* ps_1_* outputs are special and go in temp register 0. */
if (ctx->profile->major_version == 1 && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
{
size_t i;
for (i = 0; i < entry_func->parameters.count; ++i)
{
const struct hlsl_ir_var *var = entry_func->parameters.vars[i];
if (var->is_output_semantic)
{
record_allocation(ctx, &allocator, 0, VKD3DSP_WRITEMASK_ALL, var->first_write, var->last_read);
break;
}
}
}
allocate_temp_registers_recurse(ctx, &entry_func->body, &allocator);
ctx->temp_count = allocator.max_reg + 1;
vkd3d_free(allocator.allocations);
}
static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, unsigned int *counter, bool output)
......@@ -3045,6 +3144,10 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var
D3DDECLUSAGE usage;
uint32_t usage_idx;
/* ps_1_* outputs are special and go in temp register 0. */
if (ctx->profile->major_version == 1 && output && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
return;
builtin = hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, &type, &reg);
if (!builtin && !hlsl_sm1_usage_from_semantic(&var->semantic, &usage, &usage_idx))
{
......
......@@ -320,7 +320,7 @@ static bool shader_dst_param_normalise_outpointid(struct vkd3d_shader_dst_param
}
static void shader_dst_param_io_init(struct vkd3d_shader_dst_param *param,
const struct vkd3d_shader_signature_element *e, enum vkd3d_shader_register_type reg_type)
const struct signature_element *e, enum vkd3d_shader_register_type reg_type)
{
param->write_mask = e->mask;
param->modifiers = 0;
......@@ -329,11 +329,11 @@ static void shader_dst_param_io_init(struct vkd3d_shader_dst_param *param,
}
static enum vkd3d_result shader_normaliser_emit_hs_input(struct vkd3d_shader_normaliser *normaliser,
const struct vkd3d_shader_signature *s, unsigned int input_control_point_count, unsigned int dst)
const struct shader_signature *s, unsigned int input_control_point_count, unsigned int dst)
{
const struct vkd3d_shader_signature_element *e;
struct vkd3d_shader_instruction *ins;
struct vkd3d_shader_dst_param *param;
const struct signature_element *e;
unsigned int i, count;
for (i = 0, count = 1; i < s->element_count; ++i)
......@@ -380,7 +380,7 @@ static enum vkd3d_result shader_normaliser_emit_hs_input(struct vkd3d_shader_nor
}
enum vkd3d_result shader_normaliser_normalise_hull_shader_control_point_io(struct vkd3d_shader_normaliser *normaliser,
const struct vkd3d_shader_signature *input_signature)
const struct shader_signature *input_signature)
{
struct vkd3d_shader_instruction_array *instructions = &normaliser->instructions;
unsigned int input_control_point_count;
......
......@@ -2243,9 +2243,9 @@ struct spirv_compiler
const struct vkd3d_shader_spirv_target_info *spirv_target_info;
bool after_declarations_section;
const struct vkd3d_shader_signature *input_signature;
const struct vkd3d_shader_signature *output_signature;
const struct vkd3d_shader_signature *patch_constant_signature;
const struct shader_signature *input_signature;
const struct shader_signature *output_signature;
const struct shader_signature *patch_constant_signature;
const struct vkd3d_shader_transform_feedback_info *xfb_info;
struct vkd3d_shader_output_info
{
......@@ -2329,8 +2329,8 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve
const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location)
{
const struct vkd3d_shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature;
const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature;
const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature;
const struct shader_signature *output_signature = &shader_desc->output_signature;
const struct vkd3d_shader_interface_info *shader_interface;
const struct vkd3d_shader_descriptor_offset_info *offset_info;
const struct vkd3d_shader_spirv_target_info *target_info;
......@@ -4258,8 +4258,8 @@ static const struct vkd3d_spirv_builtin *vkd3d_get_spirv_builtin(const struct sp
return NULL;
}
static const struct vkd3d_shader_signature_element *vkd3d_find_signature_element_for_reg(
const struct vkd3d_shader_signature *signature, unsigned int *signature_element_index,
static const struct signature_element *vkd3d_find_signature_element_for_reg(
const struct shader_signature *signature, unsigned int *signature_element_index,
unsigned int reg_idx, DWORD write_mask)
{
unsigned int signature_idx;
......@@ -4342,7 +4342,7 @@ static const struct vkd3d_shader_phase *spirv_compiler_get_current_shader_phase(
}
static void spirv_compiler_decorate_xfb_output(struct spirv_compiler *compiler,
uint32_t id, unsigned int component_count, const struct vkd3d_shader_signature_element *signature_element)
uint32_t id, unsigned int component_count, const struct signature_element *signature_element)
{
const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info;
const struct vkd3d_shader_transform_feedback_element *xfb_element;
......@@ -4423,7 +4423,7 @@ static uint32_t spirv_compiler_emit_builtin_variable(struct spirv_compiler *comp
return id;
}
static bool needs_private_io_variable(const struct vkd3d_shader_signature *signature,
static bool needs_private_io_variable(const struct shader_signature *signature,
unsigned int reg_idx, const struct vkd3d_spirv_builtin *builtin,
unsigned int *component_count, unsigned int *out_write_mask)
{
......@@ -4443,7 +4443,7 @@ static bool needs_private_io_variable(const struct vkd3d_shader_signature *signa
for (i = 0, count = 0; i < signature->element_count; ++i)
{
const struct vkd3d_shader_signature_element *current = &signature->elements[i];
const struct signature_element *current = &signature->elements[i];
if (current->register_index != reg_idx)
continue;
......@@ -4478,10 +4478,10 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
enum vkd3d_shader_interpolation_mode interpolation_mode)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_signature_element *signature_element;
const struct vkd3d_shader_signature *shader_signature;
const struct vkd3d_shader_register *reg = &dst->reg;
unsigned int component_idx, input_component_count;
const struct signature_element *signature_element;
const struct shader_signature *shader_signature;
enum vkd3d_shader_component_type component_type;
uint32_t type_id, ptr_type_id, float_type_id;
const struct vkd3d_spirv_builtin *builtin;
......@@ -4786,8 +4786,7 @@ static bool is_dual_source_blending(const struct spirv_compiler *compiler)
return compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && info && info->dual_source_blending;
}
static void calculate_clip_or_cull_distance_mask(const struct vkd3d_shader_signature_element *e,
uint32_t *mask)
static void calculate_clip_or_cull_distance_mask(const struct signature_element *e, uint32_t *mask)
{
if (e->semantic_index >= sizeof(*mask) * CHAR_BIT / VKD3D_VEC4_SIZE)
{
......@@ -4799,11 +4798,11 @@ static void calculate_clip_or_cull_distance_mask(const struct vkd3d_shader_signa
}
static uint32_t calculate_sysval_array_mask(struct spirv_compiler *compiler,
const struct vkd3d_shader_signature *signature, enum vkd3d_shader_input_sysval_semantic sysval)
const struct shader_signature *signature, enum vkd3d_shader_input_sysval_semantic sysval)
{
const struct vkd3d_shader_signature_element *e;
const struct vkd3d_spirv_builtin *sig_builtin;
const struct vkd3d_spirv_builtin *builtin;
const struct signature_element *e;
uint32_t signature_idx, mask = 0;
if (!(builtin = get_spirv_builtin_for_sysval(compiler, sysval)))
......@@ -4829,7 +4828,7 @@ static uint32_t calculate_sysval_array_mask(struct spirv_compiler *compiler,
/* Emits arrayed SPIR-V built-in variables. */
static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler *compiler)
{
const struct vkd3d_shader_signature *output_signature = compiler->output_signature;
const struct shader_signature *output_signature = compiler->output_signature;
uint32_t clip_distance_mask = 0, clip_distance_id = 0;
uint32_t cull_distance_mask = 0, cull_distance_id = 0;
const struct vkd3d_spirv_builtin *builtin;
......@@ -4837,7 +4836,7 @@ static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler *
for (i = 0; i < output_signature->element_count; ++i)
{
const struct vkd3d_shader_signature_element *e = &output_signature->elements[i];
const struct signature_element *e = &output_signature->elements[i];
switch (e->sysval_semantic)
{
......@@ -4872,7 +4871,7 @@ static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler *
for (i = 0; i < output_signature->element_count; ++i)
{
const struct vkd3d_shader_signature_element *e = &output_signature->elements[i];
const struct signature_element *e = &output_signature->elements[i];
switch (e->sysval_semantic)
{
......@@ -4956,11 +4955,11 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler,
const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_signature_element *signature_element;
const struct vkd3d_shader_signature *shader_signature;
const struct vkd3d_shader_register *reg = &dst->reg;
unsigned int component_idx, output_component_count;
const struct signature_element *signature_element;
enum vkd3d_shader_component_type component_type;
const struct shader_signature *shader_signature;
const struct vkd3d_spirv_builtin *builtin;
struct vkd3d_symbol *symbol = NULL;
bool use_private_variable = false;
......@@ -5123,7 +5122,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler,
}
static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *compiler,
const struct vkd3d_shader_signature_element *e)
const struct signature_element *e)
{
enum vkd3d_shader_input_sysval_semantic sysval;
const struct vkd3d_spirv_builtin *builtin;
......@@ -5142,14 +5141,14 @@ static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *com
}
static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler,
const struct vkd3d_shader_signature *signature, const struct vkd3d_shader_signature_element *output,
const struct shader_signature *signature, const struct signature_element *output,
const struct vkd3d_shader_output_info *output_info,
uint32_t output_index_id, uint32_t val_id, unsigned int write_mask)
{
unsigned int dst_write_mask, use_mask, uninit_mask, swizzle, mask;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id;
const struct vkd3d_shader_signature_element *element;
const struct signature_element *element;
unsigned int i, index, array_idx;
uint32_t output_id;
......@@ -5238,7 +5237,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler *
uint32_t param_type_id[MAX_REG_OUTPUT + 1], param_id[MAX_REG_OUTPUT + 1] = {0};
uint32_t void_id, type_id, ptr_type_id, function_type_id, function_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_signature *signature;
const struct shader_signature *signature;
uint32_t output_index_id = 0;
bool is_patch_constant;
unsigned int i, count;
......@@ -5323,7 +5322,7 @@ static void spirv_compiler_emit_hull_shader_builtins(struct spirv_compiler *comp
static void spirv_compiler_emit_hull_shader_patch_constants(struct spirv_compiler *compiler)
{
const struct vkd3d_shader_signature *signature = compiler->patch_constant_signature;
const struct shader_signature *signature = compiler->patch_constant_signature;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t register_count = 0;
unsigned int signature_idx;
......@@ -6446,7 +6445,7 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile
static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler)
{
const struct vkd3d_shader_signature *signature = compiler->output_signature;
const struct shader_signature *signature = compiler->output_signature;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
struct vkd3d_symbol reg_symbol, *symbol;
struct vkd3d_shader_register reg;
......@@ -6485,7 +6484,7 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler)
for (i = 0; i < signature->element_count; ++i)
{
const struct vkd3d_shader_signature_element *e = &signature->elements[i];
const struct signature_element *e = &signature->elements[i];
reg.type = VKD3DSPR_OUTPUT;
reg.idx[0].offset = e->register_index;
......@@ -6548,8 +6547,8 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler,
static void spirv_compiler_emit_default_control_point_phase(struct spirv_compiler *compiler)
{
const struct vkd3d_shader_signature *output_signature = compiler->output_signature;
const struct vkd3d_shader_signature *input_signature = compiler->input_signature;
const struct shader_signature *output_signature = compiler->output_signature;
const struct shader_signature *input_signature = compiler->input_signature;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
enum vkd3d_shader_component_type component_type;
struct vkd3d_shader_src_param invocation;
......@@ -6580,8 +6579,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile
assert(input_signature->element_count == output_signature->element_count);
for (i = 0; i < output_signature->element_count; ++i)
{
const struct vkd3d_shader_signature_element *output = &output_signature->elements[i];
const struct vkd3d_shader_signature_element *input = &input_signature->elements[i];
const struct signature_element *output = &output_signature->elements[i];
const struct signature_element *input = &input_signature->elements[i];
assert(input->mask == output->mask);
assert(input->component_type == output->component_type);
......
......@@ -2060,7 +2060,7 @@ static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops =
};
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code,
size_t byte_code_size, const char *source_name, const struct vkd3d_shader_signature *output_signature,
size_t byte_code_size, const char *source_name, const struct shader_signature *output_signature,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_version version;
......@@ -2128,7 +2128,7 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
memset(sm4->output_map, 0xff, sizeof(sm4->output_map));
for (i = 0; i < output_signature->element_count; ++i)
{
struct vkd3d_shader_signature_element *e = &output_signature->elements[i];
struct signature_element *e = &output_signature->elements[i];
if (version.type == VKD3D_SHADER_TYPE_PIXEL
&& ascii_strcasecmp(e->semantic_name, "SV_Target"))
......@@ -2202,7 +2202,7 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
*parser = &sm4->p;
return VKD3D_OK;
return sm4->p.failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK;
}
static void write_sm4_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_block *block);
......
......@@ -1401,10 +1401,54 @@ void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signatu
desc->version = 0;
}
static bool vkd3d_shader_signature_from_shader_signature(struct vkd3d_shader_signature *signature,
const struct shader_signature *src)
{
unsigned int i;
signature->element_count = src->element_count;
if (!src->elements)
{
assert(!signature->element_count);
signature->elements = NULL;
return true;
}
if (!(signature->elements = vkd3d_calloc(signature->element_count, sizeof(*signature->elements))))
return false;
for (i = 0; i < signature->element_count; ++i)
{
struct vkd3d_shader_signature_element *d = &signature->elements[i];
struct signature_element *e = &src->elements[i];
d->semantic_name = e->semantic_name;
d->semantic_index = e->semantic_index;
d->stream_index = e->stream_index;
d->sysval_semantic = e->sysval_semantic;
d->component_type = e->component_type;
d->register_index = e->register_index;
if (e->register_count > 1)
FIXME("Arrayed elements are not supported yet.\n");
d->mask = e->mask;
d->used_mask = e->used_mask;
d->min_precision = e->min_precision;
}
return true;
}
void shader_signature_cleanup(struct shader_signature *signature)
{
vkd3d_free(signature->elements);
signature->elements = NULL;
}
int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_signature *signature, char **messages)
{
struct vkd3d_shader_message_context message_context;
struct shader_signature shader_signature;
int ret;
TRACE("dxbc {%p, %zu}, signature %p, messages %p.\n", dxbc->code, dxbc->size, signature, messages);
......@@ -1413,13 +1457,17 @@ int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
*messages = NULL;
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
ret = shader_parse_input_signature(dxbc, &message_context, signature);
ret = shader_parse_input_signature(dxbc, &message_context, &shader_signature);
vkd3d_shader_message_context_trace_messages(&message_context);
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages))
ret = VKD3D_ERROR_OUT_OF_MEMORY;
vkd3d_shader_message_context_cleanup(&message_context);
if (!vkd3d_shader_signature_from_shader_signature(signature, &shader_signature))
ret = VKD3D_ERROR_OUT_OF_MEMORY;
shader_signature_cleanup(&shader_signature);
return ret;
}
......
......@@ -775,13 +775,35 @@ enum vkd3d_shader_input_sysval_semantic
VKD3D_SIV_LINE_DENSITY_TESS_FACTOR = 22,
};
struct signature_element
{
const char *semantic_name;
unsigned int semantic_index;
unsigned int stream_index;
enum vkd3d_shader_sysval_semantic sysval_semantic;
enum vkd3d_shader_component_type component_type;
unsigned int register_index;
unsigned int register_count;
unsigned int mask;
unsigned int used_mask;
enum vkd3d_shader_minimum_precision min_precision;
};
struct shader_signature
{
struct signature_element *elements;
unsigned int element_count;
};
void shader_signature_cleanup(struct shader_signature *signature);
struct vkd3d_shader_desc
{
const uint32_t *byte_code;
size_t byte_code_size;
struct vkd3d_shader_signature input_signature;
struct vkd3d_shader_signature output_signature;
struct vkd3d_shader_signature patch_constant_signature;
struct shader_signature input_signature;
struct shader_signature output_signature;
struct shader_signature patch_constant_signature;
};
struct vkd3d_shader_register_semantic
......@@ -1136,7 +1158,7 @@ void free_shader_desc(struct vkd3d_shader_desc *desc);
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc);
int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature);
struct vkd3d_shader_message_context *message_context, struct shader_signature *signature);
struct vkd3d_glsl_generator;
......@@ -1350,7 +1372,7 @@ void shader_normaliser_init(struct vkd3d_shader_normaliser *normaliser,
struct vkd3d_shader_instruction_array *instructions);
enum vkd3d_result shader_normaliser_flatten_hull_shader_phases(struct vkd3d_shader_normaliser *normaliser);
enum vkd3d_result shader_normaliser_normalise_hull_shader_control_point_io(struct vkd3d_shader_normaliser *normaliser,
const struct vkd3d_shader_signature *input_signature);
const struct shader_signature *input_signature);
void shader_normaliser_destroy(struct vkd3d_shader_normaliser *normaliser);
#endif /* __VKD3D_SHADER_PRIVATE_H */
......@@ -36303,6 +36303,164 @@ static void test_readback_map_stability(void)
ID3D12Resource_Unmap(buffer, 0, NULL);
 
ID3D12Resource_Release(buffer);
}
static void test_vs_ps_relative_addressing(void)
{
D3D12_ROOT_SIGNATURE_DESC root_signature_desc;
D3D12_ROOT_PARAMETER root_parameters[1];
ID3D12GraphicsCommandList *command_list;
D3D12_INPUT_LAYOUT_DESC input_layout;
struct test_context_desc desc;
D3D12_VERTEX_BUFFER_VIEW vbv;
struct test_context context;
ID3D12CommandQueue *queue;
ID3D12Resource *vb;
HRESULT hr;
static const struct
{
struct vec4 position;
uint32_t color[3];
}
vertices[] =
{
{{-1.0f, -1.0f, 0.0f, 1.0f}, {0xffffff00, 0xff00, 0xff00ff00}},
{{-1.0f, 1.0f, 0.0f, 1.0f}, {0xffffff00, 0xff00, 0xff00ff00}},
{{ 1.0f, -1.0f, 0.0f, 1.0f}, {0xffffff00, 0xff00, 0xff00ff00}},
{{ 1.0f, 1.0f, 0.0f, 1.0f}, {0xffffff00, 0xff00, 0xff00ff00}},
};
static const D3D12_INPUT_ELEMENT_DESC layout_desc[] =
{
{"SV_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 20, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"COLOR", 2, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
};
static const DWORD vs_code[] =
{
#if 0
uint3 index;
struct vs_data
{
float4 pos : SV_Position;
float4 color[3] : COLOR;
};
void main(in struct vs_data vs_input, out struct vs_data vs_output)
{
vs_output.pos = vs_input.pos;
vs_output.color[0] = vs_input.color[index.x];
vs_output.color[1] = vs_input.color[index.y];
vs_output.color[2] = vs_input.color[index.z];
}
#endif
0x43425844, 0x313cf242, 0x30e9b93c, 0xf8d3ed69, 0x0feecdca, 0x00000001, 0x00000288, 0x00000003,
0x0000002c, 0x000000b0, 0x00000134, 0x4e475349, 0x0000007c, 0x00000004, 0x00000008, 0x00000068,
0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000074, 0x00000000, 0x00000000,
0x00000003, 0x00000001, 0x00000f0f, 0x00000074, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
0x00000f0f, 0x00000074, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000f0f, 0x505f5653,
0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000007c, 0x00000004, 0x00000008,
0x00000068, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000074, 0x00000000,
0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000074, 0x00000001, 0x00000000, 0x00000003,
0x00000002, 0x0000000f, 0x00000074, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x0000000f,
0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x58454853, 0x0000014c, 0x00010050,
0x00000053, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005f, 0x001010f2,
0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002, 0x0300005f,
0x001010f2, 0x00000003, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2,
0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000003, 0x02000068,
0x00000001, 0x0400005b, 0x001010f2, 0x00000001, 0x00000003, 0x05000036, 0x001020f2, 0x00000000,
0x00101e46, 0x00000000, 0x06000036, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000,
0x07000036, 0x001020f2, 0x00000001, 0x00d01e46, 0x00000001, 0x0010000a, 0x00000000, 0x06000036,
0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x07000036, 0x001020f2, 0x00000002,
0x00d01e46, 0x00000001, 0x0010000a, 0x00000000, 0x06000036, 0x00100012, 0x00000000, 0x0020802a,
0x00000000, 0x00000000, 0x07000036, 0x001020f2, 0x00000003, 0x00d01e46, 0x00000001, 0x0010000a,
0x00000000, 0x0100003e,
};
static const D3D12_SHADER_BYTECODE vs = {vs_code, sizeof(vs_code)};
static const DWORD ps_code[] =
{
#if 0
uint4 index;
struct ps_data
{
float4 pos : SV_Position;
float4 color[3] : COLOR;
};
float4 main(struct ps_data ps_input) : SV_Target
{
return ps_input.color[index.w];
}
#endif
0x43425844, 0x2b11c807, 0xf4f69d91, 0x983d18c9, 0x99ff2a5e, 0x00000001, 0x00000188, 0x00000003,
0x0000002c, 0x000000b0, 0x000000e4, 0x4e475349, 0x0000007c, 0x00000004, 0x00000008, 0x00000068,
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000,
0x00000003, 0x00000001, 0x00000f0f, 0x00000074, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
0x00000f0f, 0x00000074, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000f0f, 0x505f5653,
0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008,
0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261,
0xabab0074, 0x58454853, 0x0000009c, 0x00000050, 0x00000027, 0x0100086a, 0x04000059, 0x00208e46,
0x00000000, 0x00000001, 0x03001062, 0x001010f2, 0x00000001, 0x03001062, 0x001010f2, 0x00000002,
0x03001062, 0x001010f2, 0x00000003, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001,
0x0400005b, 0x001010f2, 0x00000001, 0x00000003, 0x06000036, 0x00100012, 0x00000000, 0x0020803a,
0x00000000, 0x00000000, 0x07000036, 0x001020f2, 0x00000000, 0x00d01e46, 0x00000001, 0x0010000a,
0x00000000, 0x0100003e,
};
static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)};
static const uint32_t indices[] = {1, 2, 0, 1};
static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f};
memset(&desc, 0, sizeof(desc));
desc.no_root_signature = true;
desc.no_pipeline = true;
if (!init_test_context(&context, &desc))
return;
command_list = context.list;
queue = context.queue;
root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
root_parameters[0].Constants.ShaderRegister = 0;
root_parameters[0].Constants.RegisterSpace = 0;
root_parameters[0].Constants.Num32BitValues = 4;
root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
memset(&root_signature_desc, 0, sizeof(root_signature_desc));
root_signature_desc.NumParameters = ARRAY_SIZE(root_parameters);
root_signature_desc.pParameters = root_parameters;
root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
hr = create_root_signature(context.device, &root_signature_desc, &context.root_signature);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
input_layout.pInputElementDescs = layout_desc;
input_layout.NumElements = ARRAY_SIZE(layout_desc);
context.pipeline_state = create_pipeline_state(context.device,
context.root_signature, context.render_target_desc.Format, &vs, &ps, &input_layout);
vb = create_upload_buffer(context.device, sizeof(vertices), vertices);
vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb);
vbv.StrideInBytes = sizeof(*vertices);
vbv.SizeInBytes = sizeof(vertices);
ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL);
ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature);
ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state);
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0, 4, &indices, 0);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv);
ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport);
ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect);
ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 1, 0, 0);
transition_resource_state(command_list, context.render_target,
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
todo
check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0);
ID3D12Resource_Release(vb);
destroy_test_context(&context);
}
 
......@@ -36484,4 +36642,5 @@ START_TEST(d3d12)
run_test(test_unbounded_samplers);
run_test(test_clock_calibration);
run_test(test_readback_map_stability);
run_test(test_vs_ps_relative_addressing);
}