vkd3d-shader/hlsl: Use hlsl_ir_index for array and record access.

From this point on, it is no longer true that only hlsl_ir_loads can
return objects, because an object can also come from chain of
hlsl_ir_indexes that ends in an hlsl_ir_load.

The lower_index_loads pass takes care of lowering all hlsl_ir_indexes
into hlsl_ir_loads.

For this reason, hlsl_resource_load_params now expects both the resource
as the sampler to be just an hlsl_ir_node pointer instead of a pointer
to a more specific hlsl_ir_load.
This commit is contained in:
Francisco Casas 2023-03-10 22:09:58 -03:00 committed by Alexandre Julliard
parent 741c9e5893
commit 5c285adc6b
Notes: Alexandre Julliard 2023-04-13 23:20:40 +02:00
Approved-by: Zebediah Figura (@zfigura)
Approved-by: Francisco Casas (@fcasas)
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/124
6 changed files with 205 additions and 99 deletions

View File

@ -438,6 +438,71 @@ static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hl
return true;
}
bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain)
{
struct hlsl_ir_index *index;
struct hlsl_ir_load *load;
unsigned int chain_len, i;
struct hlsl_ir_node *ptr;
deref->path = NULL;
deref->path_len = 0;
deref->offset.node = NULL;
assert(chain);
if (chain->type == HLSL_IR_INDEX)
assert(!hlsl_index_is_noncontiguous(hlsl_ir_index(chain)));
/* Find the length of the index chain */
chain_len = 0;
ptr = chain;
while (ptr->type == HLSL_IR_INDEX)
{
index = hlsl_ir_index(ptr);
chain_len++;
ptr = index->val.node;
}
if (ptr->type != HLSL_IR_LOAD)
{
hlsl_error(ctx, &chain->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_LVALUE, "Invalid l-value.");
return false;
}
load = hlsl_ir_load(ptr);
if (!init_deref(ctx, deref, load->src.var, load->src.path_len + chain_len))
return false;
for (i = 0; i < load->src.path_len; ++i)
hlsl_src_from_node(&deref->path[i], load->src.path[i].node);
chain_len = 0;
ptr = chain;
while (ptr->type == HLSL_IR_INDEX)
{
unsigned int p = deref->path_len - 1 - chain_len;
index = hlsl_ir_index(ptr);
if (hlsl_index_is_noncontiguous(index))
{
hlsl_src_from_node(&deref->path[p], deref->path[p + 1].node);
hlsl_src_remove(&deref->path[p + 1]);
hlsl_src_from_node(&deref->path[p + 1], index->idx.node);
}
else
{
hlsl_src_from_node(&deref->path[p], index->idx.node);
}
chain_len++;
ptr = index->val.node;
}
assert(deref->path_len == load->src.path_len + chain_len);
return true;
}
struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
{
struct hlsl_type *type;
@ -1232,17 +1297,23 @@ struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx,
return NULL;
init_node(&load->node, HLSL_IR_RESOURCE_LOAD, params->format, loc);
load->load_type = params->type;
if (!hlsl_copy_deref(ctx, &load->resource, &params->resource))
if (!hlsl_init_deref_from_index_chain(ctx, &load->resource, params->resource))
{
vkd3d_free(load);
return NULL;
}
if (!hlsl_copy_deref(ctx, &load->sampler, &params->sampler))
if (params->sampler)
{
hlsl_cleanup_deref(&load->resource);
vkd3d_free(load);
return NULL;
if (!hlsl_init_deref_from_index_chain(ctx, &load->sampler, params->sampler))
{
hlsl_cleanup_deref(&load->resource);
vkd3d_free(load);
return NULL;
}
}
hlsl_src_from_node(&load->coords, params->coords);
hlsl_src_from_node(&load->texel_offset, params->texel_offset);
hlsl_src_from_node(&load->lod, params->lod);
@ -1281,6 +1352,13 @@ struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned
return swizzle;
}
bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index)
{
struct hlsl_type *type = index->val.node->data_type;
return type->class == HLSL_CLASS_MATRIX && !hlsl_type_is_row_major(type);
}
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)
{

View File

@ -794,7 +794,7 @@ struct hlsl_resource_load_params
{
struct hlsl_type *format;
enum hlsl_resource_load_type type;
struct hlsl_deref resource, sampler;
struct hlsl_ir_node *resource, *sampler;
struct hlsl_ir_node *coords, *lod, *texel_offset;
};
@ -1021,6 +1021,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out);
bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain);
bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other);
void hlsl_cleanup_deref(struct hlsl_deref *deref);
@ -1085,6 +1086,8 @@ struct hlsl_ir_store *hlsl_new_store_index(struct hlsl_ctx *ctx, const struct hl
struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block,
const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs);
bool hlsl_index_is_noncontiguous(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);
struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc);

View File

@ -685,9 +685,10 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list
return load;
}
static bool add_record_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *record,
static bool add_record_access(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *record,
unsigned int idx, const struct vkd3d_shader_location loc)
{
struct hlsl_ir_node *index;
struct hlsl_ir_constant *c;
assert(idx < record->data_type->e.record.field_count);
@ -696,60 +697,17 @@ static bool add_record_load(struct hlsl_ctx *ctx, struct list *instrs, struct hl
return false;
list_add_tail(instrs, &c->node.entry);
return !!add_load_index(ctx, instrs, record, &c->node, &loc);
if (!(index = hlsl_new_index(ctx, record, &c->node, &loc)))
return false;
list_add_tail(instrs, &index->entry);
return true;
}
static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, struct list *instrs,
enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2,
const struct vkd3d_shader_location *loc);
static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs,
struct hlsl_ir_node *matrix, struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc)
{
struct hlsl_type *mat_type = matrix->data_type, *ret_type;
struct hlsl_deref var_deref;
struct hlsl_ir_load *load;
struct hlsl_ir_var *var;
unsigned int i;
if (hlsl_type_is_row_major(mat_type))
return add_load_index(ctx, instrs, matrix, index, loc);
ret_type = hlsl_get_vector_type(ctx, mat_type->base_type, mat_type->dimx);
if (!(var = hlsl_new_synthetic_var(ctx, "index", ret_type, loc)))
return false;
hlsl_init_simple_deref_from_var(&var_deref, var);
for (i = 0; i < mat_type->dimx; ++i)
{
struct hlsl_ir_load *column, *value;
struct hlsl_ir_store *store;
struct hlsl_ir_constant *c;
struct hlsl_block block;
if (!(c = hlsl_new_uint_constant(ctx, i, loc)))
return false;
list_add_tail(instrs, &c->node.entry);
if (!(column = add_load_index(ctx, instrs, matrix, &c->node, loc)))
return false;
if (!(value = add_load_index(ctx, instrs, &column->node, index, loc)))
return false;
if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, i, &value->node)))
return false;
list_move_tail(instrs, &block.instrs);
}
if (!(load = hlsl_new_var_load(ctx, var, *loc)))
return false;
list_add_tail(instrs, &load->node.entry);
return true;
}
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)
{
@ -783,10 +741,11 @@ static struct hlsl_ir_node *add_zero_mipmap_level(struct hlsl_ctx *ctx, struct l
return &coords_load->node;
}
static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *array,
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)
{
const struct hlsl_type *expr_type = array->data_type, *index_type = index->data_type;
struct hlsl_ir_node *return_index;
struct hlsl_ir_expr *cast;
if (expr_type->class == HLSL_CLASS_OBJECT
@ -795,8 +754,6 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls
{
struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_LOAD};
unsigned int dim_count = hlsl_sampler_dim_count(expr_type->sampler_dim);
/* Only HLSL_IR_LOAD can return an object. */
struct hlsl_ir_load *object_load = hlsl_ir_load(array);
struct hlsl_ir_resource_load *resource_load;
if (index_type->class > HLSL_CLASS_VECTOR || index_type->dimx != dim_count)
@ -818,7 +775,7 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls
return false;
load_params.format = expr_type->e.resource_format;
load_params.resource = object_load->src;
load_params.resource = array;
load_params.coords = index;
if (!(resource_load = hlsl_new_resource_load(ctx, &load_params, loc)))
@ -838,10 +795,7 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls
list_add_tail(instrs, &cast->node.entry);
index = &cast->node;
if (expr_type->class == HLSL_CLASS_MATRIX)
return add_matrix_index(ctx, instrs, array, index, loc);
if (expr_type->class != HLSL_CLASS_ARRAY && expr_type->class != HLSL_CLASS_VECTOR)
if (expr_type->class != HLSL_CLASS_ARRAY && expr_type->class != HLSL_CLASS_VECTOR && expr_type->class != HLSL_CLASS_MATRIX)
{
if (expr_type->class == HLSL_CLASS_SCALAR)
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Scalar expressions cannot be array-indexed.");
@ -850,8 +804,9 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls
return false;
}
if (!add_load_index(ctx, instrs, array, index, loc))
if (!(return_index = hlsl_new_index(ctx, array, index, loc)))
return false;
list_add_tail(instrs, &return_index->entry);
return true;
}
@ -1784,7 +1739,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)
while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_RESOURCE_LOAD && lhs->type != HLSL_IR_INDEX)
{
if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST)
{
@ -1857,13 +1812,26 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in
return NULL;
list_add_tail(instrs, &store->node.entry);
}
else if (lhs->type == HLSL_IR_INDEX && hlsl_index_is_noncontiguous(hlsl_ir_index(lhs)))
{
hlsl_fixme(ctx, &lhs->loc, "Column-major matrix index store.");
return NULL;
}
else
{
struct hlsl_ir_store *store;
struct hlsl_deref deref;
if (!(store = hlsl_new_store_index(ctx, &hlsl_ir_load(lhs)->src, NULL, rhs, writemask, &rhs->loc)))
if (!hlsl_init_deref_from_index_chain(ctx, &deref, lhs))
return NULL;
if (!(store = hlsl_new_store_index(ctx, &deref, NULL, rhs, writemask, &rhs->loc)))
{
hlsl_cleanup_deref(&deref);
return NULL;
}
list_add_tail(instrs, &store->node.entry);
hlsl_cleanup_deref(&deref);
}
/* Don't use the instruction itself as a source, as this makes structure
@ -3205,7 +3173,6 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *
struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_SAMPLE};
const struct hlsl_type *sampler_type;
struct hlsl_ir_resource_load *load;
struct hlsl_ir_load *sampler_load;
struct hlsl_ir_node *coords;
if (params->args_count != 2 && params->args_count != 4)
@ -3234,10 +3201,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *
}
else
{
/* Only HLSL_IR_LOAD can return an object. */
sampler_load = hlsl_ir_load(params->args[0]);
load_params.resource = sampler_load->src;
load_params.resource = params->args[0];
}
if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1],
@ -3576,7 +3540,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
const struct hlsl_type *object_type = object->data_type;
struct hlsl_ir_load *object_load;
if (object_type->class != HLSL_CLASS_OBJECT || object_type->base_type != HLSL_TYPE_TEXTURE
|| object_type->sampler_dim == HLSL_SAMPLER_DIM_GENERIC)
@ -3590,9 +3553,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
return false;
}
/* Only HLSL_IR_LOAD can return an object. */
object_load = hlsl_ir_load(object);
if (!strcmp(name, "Load")
&& object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBE
&& object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY)
@ -3636,7 +3596,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
return false;
load_params.format = object_type->e.resource_format;
load_params.resource = object_load->src;
load_params.resource = object;
if (!(load = hlsl_new_resource_load(ctx, &load_params, loc)))
return false;
@ -3652,7 +3612,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_SAMPLE};
const struct hlsl_type *sampler_type;
struct hlsl_ir_resource_load *load;
struct hlsl_ir_load *sampler_load;
if (params->args_count < 2 || params->args_count > 4 + !!offset_dim)
{
@ -3675,9 +3634,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
return false;
}
/* Only HLSL_IR_LOAD can return an object. */
sampler_load = hlsl_ir_load(params->args[0]);
if (!(load_params.coords = add_implicit_conversion(ctx, instrs, params->args[1],
hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc)))
return false;
@ -3695,8 +3651,8 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
hlsl_fixme(ctx, loc, "Tiled resource status argument.");
load_params.format = object_type->e.resource_format;
load_params.resource = object_load->src;
load_params.sampler = sampler_load->src;
load_params.resource = object;
load_params.sampler = params->args[0];
if (!(load = hlsl_new_resource_load(ctx, &load_params, loc)))
return false;
@ -3716,7 +3672,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
struct hlsl_resource_load_params load_params = {0};
const struct hlsl_type *sampler_type;
struct hlsl_ir_resource_load *load;
struct hlsl_ir_load *sampler_load;
unsigned int read_channel;
if (!strcmp(name, "GatherGreen"))
@ -3792,16 +3747,13 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
return false;
}
/* Only HLSL_IR_LOAD can return an object. */
sampler_load = hlsl_ir_load(params->args[0]);
if (!(load_params.coords = add_implicit_conversion(ctx, instrs, params->args[1],
hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc)))
return false;
load_params.format = hlsl_get_vector_type(ctx, object_type->e.resource_format->base_type, 4);
load_params.resource = object_load->src;
load_params.sampler = sampler_load->src;
load_params.resource = object;
load_params.sampler = params->args[0];
if (!(load = hlsl_new_resource_load(ctx, &load_params, loc)))
return false;
@ -3817,7 +3769,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim);
const struct hlsl_type *sampler_type;
struct hlsl_ir_resource_load *load;
struct hlsl_ir_load *sampler_load;
if (params->args_count < 3 || params->args_count > 4 + !!offset_dim)
{
@ -3840,9 +3791,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
return false;
}
/* Only HLSL_IR_LOAD can return an object. */
sampler_load = hlsl_ir_load(params->args[0]);
if (!(load_params.coords = add_implicit_conversion(ctx, instrs, params->args[1],
hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc)))
load_params.coords = params->args[1];
@ -3862,8 +3810,8 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
hlsl_fixme(ctx, loc, "Tiled resource status argument.");
load_params.format = object_type->e.resource_format;
load_params.resource = object_load->src;
load_params.sampler = sampler_load->src;
load_params.resource = object;
load_params.sampler = params->args[0];
if (!(load = hlsl_new_resource_load(ctx, &load_params, loc)))
return false;
@ -5509,7 +5457,7 @@ postfix_expr:
}
field_idx = field - type->e.record.fields;
if (!add_record_load(ctx, $1, node, field_idx, @2))
if (!add_record_access(ctx, $1, node, field_idx, @2))
YYABORT;
$$ = $1;
}
@ -5538,7 +5486,7 @@ postfix_expr:
list_move_tail($1, $3);
vkd3d_free($3);
if (!add_array_load(ctx, $1, array, index, &@2))
if (!add_array_access(ctx, $1, array, index, &@2))
{
destroy_instr_list($1);
YYABORT;

View File

@ -731,6 +731,81 @@ static bool lower_calls(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *
return true;
}
/* 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. */
static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_deref var_deref;
struct hlsl_ir_index *index;
struct hlsl_ir_store *store;
struct hlsl_ir_load *load;
struct hlsl_ir_node *val;
struct hlsl_ir_var *var;
if (instr->type != HLSL_IR_INDEX)
return false;
index = hlsl_ir_index(instr);
val = index->val.node;
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);
if (!(store = hlsl_new_simple_store(ctx, var, val)))
return false;
list_add_before(&instr->entry, &store->node.entry);
if (hlsl_index_is_noncontiguous(index))
{
struct hlsl_ir_node *mat = index->val.node;
struct hlsl_deref row_deref;
unsigned int i;
assert(!hlsl_type_is_row_major(mat->data_type));
if (!(var = hlsl_new_synthetic_var(ctx, "row", instr->data_type, &instr->loc)))
return false;
hlsl_init_simple_deref_from_var(&row_deref, var);
for (i = 0; i < mat->data_type->dimx; ++i)
{
struct hlsl_ir_constant *c;
if (!(c = hlsl_new_uint_constant(ctx, i, &instr->loc)))
return false;
list_add_before(&instr->entry, &c->node.entry);
if (!(load = hlsl_new_load_index(ctx, &var_deref, &c->node, &instr->loc)))
return false;
list_add_before(&instr->entry, &load->node.entry);
if (!(load = hlsl_new_load_index(ctx, &load->src, index->idx.node, &instr->loc)))
return false;
list_add_before(&instr->entry, &load->node.entry);
if (!(store = hlsl_new_store_index(ctx, &row_deref, &c->node, &load->node, 0, &instr->loc)))
return false;
list_add_before(&instr->entry, &store->node.entry);
}
if (!(load = hlsl_new_var_load(ctx, var, instr->loc)))
return false;
list_add_before(&instr->entry, &load->node.entry);
hlsl_replace_node(instr, &load->node);
}
else
{
if (!(load = hlsl_new_load_index(ctx, &var_deref, index->idx.node, &instr->loc)))
return false;
list_add_before(&instr->entry, &load->node.entry);
hlsl_replace_node(instr, &load->node);
}
return true;
}
/* Lower casts from vec1 to vecN to swizzles. */
static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
@ -3375,6 +3450,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
while (transform_ir(ctx, lower_calls, body, NULL));
transform_ir(ctx, lower_index_loads, body, NULL);
LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
{
if (var->storage_modifiers & HLSL_STORAGE_UNIFORM)

View File

@ -78,7 +78,7 @@ draw quad
probe all rgba (1.0, 5.0, 7.0, 12.0)
[pixel shader]
[pixel shader todo]
float4 main() : SV_TARGET
{
float3x2 m = {1, 2, 3, 4, 5, 6};
@ -89,7 +89,7 @@ float4 main() : SV_TARGET
}
[test]
draw quad
todo draw quad
todo probe all rgba (30.0, 40.0, 5.0, 6.0)

View File

@ -24,7 +24,7 @@ float4 main() : sv_target
[test]
draw quad
todo probe all rgba (11.0, 11.0, 11.0, 11.0)
probe all rgba (11.0, 11.0, 11.0, 11.0)
[pixel shader]