vkd3d-shader/hlsl: Lower separated samplers for SM1.

The combined sampler is created as a SAMPLER instead of a TEXTURE
because that fits all our current infrastructure. The only problem is
that in the CTAB it must appear as a Texture, so the new field
hlsl_type.is_combined_sampler is added.

Co-authored-by: Elizabeth Figura <zfigura@codeweavers.com>
This commit is contained in:
Francisco Casas
2024-12-03 17:05:48 -03:00
committed by Henri Verbeet
parent 58d318719c
commit 3a6bf3be24
Notes: Henri Verbeet 2024-12-10 15:58:19 +01:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1303
9 changed files with 162 additions and 42 deletions

View File

@ -1570,9 +1570,14 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type)
vkd3d_unreachable(); vkd3d_unreachable();
} }
D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, bool is_combined_sampler)
{ {
switch (type->class) enum hlsl_type_class class = type->class;
if (is_combined_sampler)
class = HLSL_CLASS_TEXTURE;
switch (class)
{ {
case HLSL_CLASS_SCALAR: case HLSL_CLASS_SCALAR:
case HLSL_CLASS_VECTOR: case HLSL_CLASS_VECTOR:
@ -1639,7 +1644,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type)
break; break;
case HLSL_CLASS_ARRAY: case HLSL_CLASS_ARRAY:
return hlsl_sm1_base_type(type->e.array.type); return hlsl_sm1_base_type(type->e.array.type, is_combined_sampler);
case HLSL_CLASS_STRUCT: case HLSL_CLASS_STRUCT:
return D3DXPT_VOID; return D3DXPT_VOID;
@ -1677,7 +1682,8 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type)
vkd3d_unreachable(); vkd3d_unreachable();
} }
static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_type *type, unsigned int ctab_start) static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer,
struct hlsl_type *type, bool is_combined_sampler, unsigned int ctab_start)
{ {
const struct hlsl_type *array_type = hlsl_get_multiarray_element_type(type); const struct hlsl_type *array_type = hlsl_get_multiarray_element_type(type);
unsigned int array_size = hlsl_get_multiarray_size(type); unsigned int array_size = hlsl_get_multiarray_size(type);
@ -1697,7 +1703,7 @@ static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_typ
struct hlsl_struct_field *field = &array_type->e.record.fields[i]; struct hlsl_struct_field *field = &array_type->e.record.fields[i];
field->name_bytecode_offset = put_string(buffer, field->name); field->name_bytecode_offset = put_string(buffer, field->name);
write_sm1_type(buffer, field->type, ctab_start); write_sm1_type(buffer, field->type, false, ctab_start);
} }
fields_offset = bytecode_align(buffer) - ctab_start; fields_offset = bytecode_align(buffer) - ctab_start;
@ -1711,7 +1717,8 @@ static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_typ
} }
} }
type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(hlsl_sm1_class(type), hlsl_sm1_base_type(array_type))); type->bytecode_offset = put_u32(buffer,
vkd3d_make_u32(hlsl_sm1_class(type), hlsl_sm1_base_type(array_type, is_combined_sampler)));
put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx)); put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx));
put_u32(buffer, vkd3d_make_u32(array_size, field_count)); put_u32(buffer, vkd3d_make_u32(array_size, field_count));
put_u32(buffer, fields_offset); put_u32(buffer, fields_offset);
@ -1836,7 +1843,7 @@ void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buff
name_offset = put_string(buffer, var->name); name_offset = put_string(buffer, var->name);
set_u32(buffer, var_offset, name_offset - ctab_start); set_u32(buffer, var_offset, name_offset - ctab_start);
write_sm1_type(buffer, var->data_type, ctab_start); write_sm1_type(buffer, var->data_type, var->is_combined_sampler, ctab_start);
set_u32(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start); set_u32(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start);
if (var->default_values) if (var->default_values)

View File

@ -1021,8 +1021,8 @@ static uint32_t get_fx_2_type_class(const struct hlsl_type *type)
return hlsl_sm1_class(type); return hlsl_sm1_class(type);
} }
static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name,
struct fx_write_context *fx) const struct hlsl_semantic *semantic, bool is_combined_sampler, struct fx_write_context *fx)
{ {
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
uint32_t semantic_offset, offset, elements_count = 0, name_offset; uint32_t semantic_offset, offset, elements_count = 0, name_offset;
@ -1038,7 +1038,7 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n
name_offset = write_string(name, fx); name_offset = write_string(name, fx);
semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0; semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0;
offset = put_u32(buffer, hlsl_sm1_base_type(type)); offset = put_u32(buffer, hlsl_sm1_base_type(type, is_combined_sampler));
put_u32(buffer, get_fx_2_type_class(type)); put_u32(buffer, get_fx_2_type_class(type));
put_u32(buffer, name_offset); put_u32(buffer, name_offset);
put_u32(buffer, semantic_offset); put_u32(buffer, semantic_offset);
@ -1074,7 +1074,7 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n
/* Validated in check_invalid_object_fields(). */ /* Validated in check_invalid_object_fields(). */
VKD3D_ASSERT(hlsl_is_numeric_type(field->type)); VKD3D_ASSERT(hlsl_is_numeric_type(field->type));
write_fx_2_parameter(field->type, field->name, &field->semantic, fx); write_fx_2_parameter(field->type, field->name, &field->semantic, false, fx);
} }
} }
@ -1335,7 +1335,7 @@ static void write_fx_2_parameters(struct fx_write_context *fx)
if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc)) if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc))
continue; continue;
desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx); desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx);
value_offset = write_fx_2_initial_value(var, fx); value_offset = write_fx_2_initial_value(var, fx);
flags = 0; flags = 0;
@ -1358,7 +1358,7 @@ static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_conte
struct vkd3d_bytecode_buffer *buffer = &fx->structured; struct vkd3d_bytecode_buffer *buffer = &fx->structured;
uint32_t desc_offset, value_offset; uint32_t desc_offset, value_offset;
desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx); desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx);
value_offset = write_fx_2_initial_value(var, fx); value_offset = write_fx_2_initial_value(var, fx);
put_u32(buffer, desc_offset); put_u32(buffer, desc_offset);

View File

@ -535,6 +535,10 @@ struct hlsl_ir_var
* element of a struct, and thus needs to be aligned when packed in the signature. */ * element of a struct, and thus needs to be aligned when packed in the signature. */
bool force_align; bool force_align;
/* Whether this is a sampler that was created from the combination of a
* sampler and a texture for SM<4 backwards compatibility. */
bool is_combined_sampler;
uint32_t is_input_semantic : 1; uint32_t is_input_semantic : 1;
uint32_t is_output_semantic : 1; uint32_t is_output_semantic : 1;
uint32_t is_uniform : 1; uint32_t is_uniform : 1;
@ -1643,7 +1647,7 @@ bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx,
struct hlsl_block *block, void *context); struct hlsl_block *block, void *context);
D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type); D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type);
D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type); D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type, bool is_combined_sampler);
void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer); void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer);
int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, int d3dbc_compile(struct vsir_program *program, uint64_t config_flags,

View File

@ -2790,6 +2790,87 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n
return true; return true;
} }
/* Lower samples from separate texture and sampler variables to samples from
* synthetized combined samplers. That is, translate SM4-style samples in the
* source to SM1-style samples in the bytecode. */
static bool lower_separate_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_ir_var *var, *resource, *sampler;
struct hlsl_ir_resource_load *load;
struct vkd3d_string_buffer *name;
struct hlsl_type *sampler_type;
unsigned int sampler_dim;
if (instr->type != HLSL_IR_RESOURCE_LOAD)
return false;
load = hlsl_ir_resource_load(instr);
if (load->load_type != HLSL_RESOURCE_SAMPLE
&& load->load_type != HLSL_RESOURCE_SAMPLE_LOD
&& load->load_type != HLSL_RESOURCE_SAMPLE_LOD_BIAS)
return false;
if (!load->sampler.var)
return false;
resource = load->resource.var;
sampler = load->sampler.var;
VKD3D_ASSERT(hlsl_type_is_resource(resource->data_type));
VKD3D_ASSERT(hlsl_type_is_resource(sampler->data_type));
if (sampler->data_type->class == HLSL_CLASS_ARRAY)
{
/* Only supported by d3dcompiler if the sampler is the first component
* of the sampler array. */
hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NOT_IMPLEMENTED,
"Lower separated samples with sampler arrays.");
return false;
}
if (resource->data_type->class == HLSL_CLASS_ARRAY)
{
hlsl_fixme(ctx, &instr->loc, "Lower separated samples with resource arrays.");
return false;
}
if (!resource->is_uniform)
return false;
if(!sampler->is_uniform)
return false;
if (!(name = hlsl_get_string_buffer(ctx)))
return false;
vkd3d_string_buffer_printf(name, "%s+%s", sampler->name, resource->name);
sampler_dim = hlsl_get_multiarray_element_type(resource->data_type)->sampler_dim;
TRACE("Lowering to combined sampler %s.\n", debugstr_a(name->buffer));
if (!(var = hlsl_get_var(ctx->globals, name->buffer)))
{
sampler_type = ctx->builtin_types.sampler[sampler_dim];
if (!(var = hlsl_new_synthetic_var_named(ctx, name->buffer, sampler_type, &instr->loc, false)))
{
hlsl_release_string_buffer(ctx, name);
return false;
}
var->storage_modifiers |= HLSL_STORAGE_UNIFORM;
var->is_combined_sampler = true;
var->is_uniform = 1;
list_remove(&var->scope_entry);
list_add_after(&sampler->scope_entry, &var->scope_entry);
list_add_after(&sampler->extern_entry, &var->extern_entry);
}
hlsl_release_string_buffer(ctx, name);
/* Only change the deref's var, keep the path. */
load->resource.var = var;
hlsl_cleanup_deref(&load->sampler);
load->sampler.var = NULL;
return true;
}
/* Lower combined samples and sampler variables to synthesized separated textures and samplers. /* Lower combined samples and sampler variables to synthesized separated textures and samplers.
* That is, translate SM1-style samples in the source to SM4-style samples in the bytecode. */ * That is, translate SM1-style samples in the source to SM4-style samples in the bytecode. */
static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
@ -2901,6 +2982,27 @@ static void insert_ensuring_decreasing_bind_count(struct list *list, struct hlsl
list_add_tail(list, &to_add->extern_entry); list_add_tail(list, &to_add->extern_entry);
} }
static bool sort_synthetic_combined_samplers_first(struct hlsl_ctx *ctx)
{
struct list separated_resources;
struct hlsl_ir_var *var, *next;
list_init(&separated_resources);
LIST_FOR_EACH_ENTRY_SAFE(var, next, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (var->is_combined_sampler)
{
list_remove(&var->extern_entry);
insert_ensuring_decreasing_bind_count(&separated_resources, var, HLSL_REGSET_SAMPLERS);
}
}
list_move_head(&ctx->extern_vars, &separated_resources);
return false;
}
static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx) static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx)
{ {
struct list separated_resources; struct list separated_resources;
@ -10260,9 +10362,13 @@ static void process_entry_function(struct hlsl_ctx *ctx,
lower_ir(ctx, lower_casts_to_bool, body); lower_ir(ctx, lower_casts_to_bool, body);
lower_ir(ctx, lower_int_dot, body); lower_ir(ctx, lower_int_dot, body);
if (hlsl_version_lt(ctx, 4, 0))
hlsl_transform_ir(ctx, lower_separate_samples, body, NULL);
hlsl_transform_ir(ctx, validate_dereferences, body, NULL); hlsl_transform_ir(ctx, validate_dereferences, body, NULL);
hlsl_transform_ir(ctx, track_object_components_sampler_dim, body, NULL); hlsl_transform_ir(ctx, track_object_components_sampler_dim, body, NULL);
if (profile->major_version >= 4)
if (hlsl_version_ge(ctx, 4, 0))
hlsl_transform_ir(ctx, lower_combined_samples, body, NULL); hlsl_transform_ir(ctx, lower_combined_samples, body, NULL);
do do
@ -10270,7 +10376,10 @@ static void process_entry_function(struct hlsl_ctx *ctx,
while (hlsl_transform_ir(ctx, dce, body, NULL)); while (hlsl_transform_ir(ctx, dce, body, NULL));
hlsl_transform_ir(ctx, track_components_usage, body, NULL); hlsl_transform_ir(ctx, track_components_usage, body, NULL);
sort_synthetic_separated_samplers_first(ctx); if (hlsl_version_lt(ctx, 4, 0))
sort_synthetic_combined_samplers_first(ctx);
else
sort_synthetic_separated_samplers_first(ctx);
if (profile->major_version < 4) if (profile->major_version < 4)
{ {

View File

@ -95,8 +95,8 @@ float4 main() : sv_target
[test] [test]
todo(msl) draw quad todo(msl) draw quad
if(sm<4) todo probe (0, 0) rgba (1, 1, 1, 11) if(sm<4) probe (0, 0) rgba(1, 1, 1, 11)
if(sm>=4) probe (0, 0) rgba (10, 10, 10, 11) if(sm>=4) probe (0, 0) rgba(10, 10, 10, 11)
[pixel shader] [pixel shader]
@ -110,8 +110,8 @@ float4 main() : sv_target
[test] [test]
todo(msl) draw quad todo(msl) draw quad
if(sm<4) todo probe (0, 0) rgba (1, 1, 1, 11) if(sm<4) probe (0, 0) rgba(1, 1, 1, 11)
if(sm>=4) probe (0, 0) rgba (10, 10, 10, 11) if(sm>=4) probe (0, 0) rgba(10, 10, 10, 11)
[pixel shader todo(sm<4)] [pixel shader todo(sm<4)]
@ -202,7 +202,7 @@ float4 main() : sv_target
[test] [test]
todo(msl) draw quad todo(msl) draw quad
if(sm<4) todo probe (0, 0) rgba(453021, 453021, 453021, 111111) if(sm<4) probe (0, 0) rgba(453021, 453021, 453021, 111111)
if(sm>=4) probe (0, 0) rgba(12333, 12333, 12333, 111111) if(sm>=4) probe (0, 0) rgba(12333, 12333, 12333, 111111)

View File

@ -229,7 +229,7 @@ size (2d, 2, 2)
filter linear linear linear filter linear linear linear
address clamp clamp clamp address clamp clamp clamp
[pixel shader todo(sm<4)] [pixel shader]
Texture2D tex; Texture2D tex;
sampler sam; sampler sam;
float a; float a;
@ -243,14 +243,14 @@ float4 main() : sv_target
[test] [test]
uniform 0 float -2 uniform 0 float -2
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (0.0, 0.0, 0.0, 4.0) probe (0, 0) rgba (0.0, 0.0, 0.0, 4.0)
uniform 0 float 4 uniform 0 float 4
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0) probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader todo(sm<4)] [pixel shader]
Texture2D tex; Texture2D tex;
sampler sam; sampler sam;
float a; float a;
@ -267,11 +267,11 @@ float4 main() : sv_target
[test] [test]
uniform 0 float 2 uniform 0 float 2
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (0.0, 0.0, 0.0, 4.0) probe (0, 0) rgba (0.0, 0.0, 0.0, 4.0)
uniform 0 float 1 uniform 0 float 1
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (1.0, 0.0, 0.0, 4.0) probe (0, 0) rgba (1.0, 0.0, 0.0, 4.0)
uniform 0 float 0 uniform 0 float 0
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (1.0, 1.0, 0.0, 4.0) probe (0, 0) rgba (1.0, 1.0, 0.0, 4.0)

View File

@ -18,7 +18,7 @@ void main(float4 pos : position, out float2 tex : texcoord, out float4 out_pos :
out_pos = pos; out_pos = pos;
} }
[pixel shader todo(sm<4)] [pixel shader]
sampler s; sampler s;
Texture2D t; Texture2D t;
uniform float bias; uniform float bias;
@ -32,16 +32,16 @@ float4 main(float2 coord : texcoord) : sv_target
[test] [test]
uniform 0 float4 6.5 0.0 0.0 0.0 uniform 0 float4 6.5 0.0 0.0 0.0
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (10.0, 0.0, 10.0, 0.0) probe (0, 0) rgba (10.0, 0.0, 10.0, 0.0)
uniform 0 float4 7.5 0.0 0.0 0.0 uniform 0 float4 7.5 0.0 0.0 0.0
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (4.0, 0.0, 10.0, 0.0) todo(sm<4) probe (0, 0) rgba(4.0, 0.0, 10.0, 0.0)
uniform 0 float4 8.5 0.0 0.0 0.0 uniform 0 float4 8.5 0.0 0.0 0.0
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (0.0, 0.0, 10.0, 0.0) todo(sm<4) probe (0, 0) rgba(0.0, 0.0, 10.0, 0.0)
[require] [require]
shader model >= 3.0 shader model >= 3.0

View File

@ -7,7 +7,7 @@ size (2d, 2, 2)
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0
[pixel shader todo(sm<4)] [pixel shader]
sampler s; sampler s;
Texture2D t; Texture2D t;
@ -17,10 +17,10 @@ float4 main() : sv_target
} }
[test] [test]
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (0.25, 0, 0.25, 0) probe (0, 0) rgba (0.25, 0, 0.25, 0)
[pixel shader todo(sm<4)] [pixel shader]
SamplerState s; SamplerState s;
Texture2D t; Texture2D t;
@ -30,7 +30,7 @@ float4 main() : sv_target
} }
[test] [test]
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (0.25, 0, 0.25, 0) probe (0, 0) rgba (0.25, 0, 0.25, 0)
[pixel shader fail] [pixel shader fail]

View File

@ -136,7 +136,7 @@ float4 main(Texture2D tex2) : sv_target
} }
[pixel shader todo(sm<4)] [pixel shader]
Texture2D real_tex; Texture2D real_tex;
static Texture2D tex = real_tex; static Texture2D tex = real_tex;
sampler sam; sampler sam;
@ -147,11 +147,11 @@ float4 main() : sv_target
} }
[test] [test]
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (1, 2, 3, 4) probe (0, 0) rgba (1, 2, 3, 4)
[pixel shader todo(sm<4)] [pixel shader]
Texture2D real_tex; Texture2D real_tex;
static Texture2D tex; static Texture2D tex;
sampler sam; sampler sam;
@ -163,7 +163,7 @@ float4 main() : sv_target
} }
[test] [test]
todo(sm<4 | msl) draw quad todo(msl) draw quad
probe (0, 0) rgba (1, 2, 3, 4) probe (0, 0) rgba (1, 2, 3, 4)