Compare commits

...

6 Commits

Author SHA1 Message Date
Hans-Kristian Arntzen cfaf31019f tests: Add simple minprecision test.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
2022-05-30 12:13:52 +02:00
Hans-Kristian Arntzen e4261510af vkd3d-shader: Remove fixme warning for minimum precision.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
2022-05-30 12:13:52 +02:00
Hans-Kristian Arntzen 6224e1d9d4 vkd3d-shader: Emit RelaxedPrecision for saturation modifier.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
2022-05-30 12:13:52 +02:00
Hans-Kristian Arntzen 34d23c9cc7 vkd3d: Expose 16-bit min precision support.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
2022-05-30 12:13:52 +02:00
Hans-Kristian Arntzen 5273fbeacc vkd3d-shader: Emit RelaxedPrecision when appropriate.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
2022-05-30 12:13:49 +02:00
Hans-Kristian Arntzen fee77efca4 vkd3d-shader: Parse minprecision modifier.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
2022-05-30 11:24:53 +02:00
6 changed files with 367 additions and 25 deletions

View File

@ -1616,9 +1616,11 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr
}
if (m & 0x20000)
param->modifier = VKD3DSPRM_NONUNIFORM;
param->modifier |= VKD3DSPRM_NONUNIFORM;
if (m & 0x4000)
param->modifier |= VKD3DSPRM_RELAXED_PRECISION;
if ((m &= ~(0x200c1)))
if ((m &= ~(0x240c1)))
FIXME("Skipping modifier 0x%08x.\n", m);
}
else

View File

@ -853,6 +853,13 @@ static void vkd3d_spirv_build_op_decorate(struct vkd3d_spirv_builder *builder,
SpvOpDecorate, target_id, decoration, literals, literal_count);
}
static void vkd3d_dxbc_compiler_emit_relaxed_precision(struct vkd3d_spirv_builder *builder,
const struct vkd3d_shader_dst_param *dst, uint32_t val_id)
{
if (dst->reg.modifier & VKD3DSPRM_RELAXED_PRECISION)
vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationRelaxedPrecision, NULL, 0);
}
static void vkd3d_spirv_build_op_decorate1(struct vkd3d_spirv_builder *builder,
uint32_t target_id, SpvDecoration decoration, uint32_t operand0)
{
@ -3515,7 +3522,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_constant_buffer(struct vkd3d_dxbc_
ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id,
base_id, indexes, last_index + 1);
if (reg->modifier == VKD3DSPRM_NONUNIFORM)
if (reg->modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id);
component_ids[j++] = vkd3d_spirv_build_op_loadv(builder, type_id, ptr_id,
@ -3807,7 +3814,10 @@ static void vkd3d_dxbc_compiler_emit_store_dst(struct vkd3d_dxbc_compiler *compi
{
assert(!(dst->modifiers & ~VKD3DSPDM_SATURATE));
if (dst->modifiers & VKD3DSPDM_SATURATE)
{
val_id = vkd3d_dxbc_compiler_emit_sat(compiler, &dst->reg, dst->write_mask, val_id);
vkd3d_dxbc_compiler_emit_relaxed_precision(&compiler->spirv_builder, dst, val_id);
}
vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, val_id);
}
@ -4457,7 +4467,8 @@ static bool is_dual_source_blending(const struct vkd3d_dxbc_compiler *compiler)
static uint32_t vkd3d_dxbc_compiler_get_io_variable(struct vkd3d_dxbc_compiler *compiler,
SpvStorageClass storage_class, uint32_t reg_idx, uint32_t array_size,
enum vkd3d_shader_interpolation_mode interpolation_mode, bool is_patch_constant,
enum vkd3d_shader_interpolation_mode interpolation_mode,
bool is_patch_constant, bool relax_precision,
unsigned int *out_component_count, enum vkd3d_component_type *out_component_type)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
@ -4543,6 +4554,9 @@ static uint32_t vkd3d_dxbc_compiler_get_io_variable(struct vkd3d_dxbc_compiler *
if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && storage_class == SpvStorageClassInput)
vkd3d_dxbc_compiler_emit_interpolation_decorations(compiler, var_id, interpolation_mode);
if (relax_precision)
vkd3d_spirv_build_op_decorate(builder, var_id, SpvDecorationRelaxedPrecision, NULL, 0);
vkd3d_spirv_add_iface_variable(builder, var_id);
var_ids[reg_idx] = var_id;
return var_id;
@ -4567,6 +4581,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi
SpvStorageClass storage_class;
struct rb_entry *entry = NULL;
bool use_private_var = false;
bool is_relaxed_precision;
unsigned int write_mask;
unsigned int array_size;
bool is_patch_constant;
@ -4609,11 +4624,13 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi
{
component_type = builtin->component_type;
input_component_count = builtin->component_count;
is_relaxed_precision = false;
}
else
{
component_type = signature_element->component_type;
input_component_count = vkd3d_write_mask_component_count(signature_element->mask & 0xff);
is_relaxed_precision = signature_element->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE;
}
if ((use_private_var = builtin && builtin->fixup_pfn))
@ -4644,7 +4661,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi
if (use_private_var)
{
input_id = vkd3d_dxbc_compiler_get_io_variable(compiler, SpvStorageClassInput,
reg_idx, array_size, interpolation_mode, is_patch_constant,
reg_idx, array_size, interpolation_mode, is_patch_constant, is_relaxed_precision,
&input_component_count, &component_type);
apply_patch_decoration = false;
}
@ -4671,7 +4688,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi
if (!entry)
{
input_id = vkd3d_dxbc_compiler_get_io_variable(compiler, SpvStorageClassInput,
reg_idx, array_size, interpolation_mode, is_patch_constant,
reg_idx, array_size, interpolation_mode, is_patch_constant, is_relaxed_precision,
&input_component_count, &component_type);
apply_patch_decoration = false;
}
@ -5051,6 +5068,7 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
SpvStorageClass storage_class;
struct rb_entry *entry = NULL;
unsigned int signature_idx;
bool is_relaxed_precision;
bool use_private_variable;
unsigned int write_mask;
unsigned int array_size;
@ -5082,10 +5100,12 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
component_type = builtin->component_type;
if (!builtin->spirv_array_size)
output_component_count = builtin->component_count;
is_relaxed_precision = false;
}
else
{
component_type = signature_element->component_type;
is_relaxed_precision = signature_element->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE;
}
storage_class = SpvStorageClassOutput;
@ -5142,7 +5162,7 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
else
{
id = vkd3d_dxbc_compiler_get_io_variable(compiler, storage_class,
reg->idx[0].offset, array_size, VKD3DSIM_NONE, is_patch_constant,
reg->idx[0].offset, array_size, VKD3DSIM_NONE, is_patch_constant, is_relaxed_precision,
&output_component_count, &component_type);
apply_patch_decoration = false;
}
@ -5803,7 +5823,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_global_flags(struct vkd3d_dxbc_compiler
flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS);
}
if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS))
if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_MINIMUM_PRECISION | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS))
FIXME("Unhandled global flags %#x.\n", flags);
else
WARN("Unhandled global flags %#x.\n", flags);
@ -7424,6 +7444,7 @@ static void vkd3d_dxbc_compiler_emit_default_control_point_phase(struct vkd3d_dx
struct vkd3d_shader_register_info input_info;
struct vkd3d_shader_register input_reg;
uint32_t invocation_id, dst_write_mask;
bool is_relaxed_precision;
unsigned int i;
invocation_id = vkd3d_dxbc_compiler_emit_load_invocation_id(compiler);
@ -7463,17 +7484,19 @@ static void vkd3d_dxbc_compiler_emit_default_control_point_phase(struct vkd3d_dx
}
else
{
is_relaxed_precision = input->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE;
input_id = vkd3d_dxbc_compiler_get_io_variable(compiler, SpvStorageClassInput,
input->register_index, compiler->input_control_point_count, VKD3DSIM_NONE,
false, &input_component_count, &input_component_type);
false, is_relaxed_precision, &input_component_count, &input_component_type);
}
vkd3d_spirv_build_op_name(builder, input_id, "vicp%u", input->register_index);
}
is_relaxed_precision = output->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE;
output_id = vkd3d_dxbc_compiler_get_io_variable(compiler, SpvStorageClassOutput,
output->register_index, compiler->output_control_point_count, VKD3DSIM_NONE,
false, &output_component_count, &output_component_type);
false, is_relaxed_precision, &output_component_count, &output_component_type);
vkd3d_spirv_build_op_name(builder, output_id, "vocp%u", output->register_index);
src_id = vkd3d_dxbc_compiler_load_invocation_input(compiler, input_id, invocation_id,
@ -7609,6 +7632,49 @@ static SpvOp vkd3d_dxbc_compiler_map_alu_instruction(const struct vkd3d_shader_i
return SpvOpMax;
}
/* Only attempt to use relaxed precision for float ops.
* Relaxed precision on integers requires correct signage to be used on the type
* and we generally cannot handle that in any reasonable way with DXBC with the way
* we generate code. */
static bool vkd3d_glsl450_inst_can_relax_precision(enum GLSLstd450 inst)
{
switch (inst)
{
case GLSLstd450Fma:
case GLSLstd450NMax:
case GLSLstd450NMin:
case GLSLstd450NClamp:
case GLSLstd450RoundEven:
case GLSLstd450Floor:
case GLSLstd450Ceil:
case GLSLstd450Trunc:
case GLSLstd450Fract:
case GLSLstd450Exp2:
case GLSLstd450Log2:
case GLSLstd450InverseSqrt:
case GLSLstd450FAbs:
return true;
default:
return false;
}
}
static bool vkd3d_spirv_inst_can_relax_precision(SpvOp op)
{
switch (op)
{
case SpvOpFAdd:
case SpvOpFSub:
case SpvOpFMul:
case SpvOpFDiv:
return true;
default:
return false;
}
}
static void vkd3d_dxbc_compiler_emit_alu_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
@ -7640,6 +7706,9 @@ static void vkd3d_dxbc_compiler_emit_alu_instruction(struct vkd3d_dxbc_compiler
if (instruction->flags & VKD3DSI_PRECISE_XYZW)
vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0);
if (vkd3d_spirv_inst_can_relax_precision(op))
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, dst, val_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
@ -7769,6 +7838,9 @@ static void vkd3d_dxbc_compiler_emit_ext_glsl_instruction(struct vkd3d_dxbc_comp
if (glsl_inst == GLSLstd450Fma && (instruction->flags & VKD3DSI_PRECISE_XYZW))
vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0);
if (vkd3d_glsl450_inst_can_relax_precision(glsl_inst))
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, dst, val_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
@ -7883,6 +7955,7 @@ static void vkd3d_dxbc_compiler_emit_dot(struct vkd3d_dxbc_compiler *compiler,
if (instruction->flags & VKD3DSI_PRECISE_XYZW)
vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0);
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, dst, val_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
@ -7907,6 +7980,7 @@ static void vkd3d_dxbc_compiler_emit_rcp(struct vkd3d_dxbc_compiler *compiler,
src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask);
val_id = vkd3d_spirv_build_op_fdiv(builder, type_id, one_id, src_id);
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, dst, val_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
@ -7925,6 +7999,7 @@ static void vkd3d_dxbc_compiler_emit_sincos(struct vkd3d_dxbc_compiler *compiler
src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst_sin->write_mask);
sin_id = vkd3d_spirv_build_op_glsl_std450_sin(builder, type_id, src_id);
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, dst_sin, sin_id);
}
if (dst_cos->reg.type != VKD3DSPR_NULL)
@ -7936,6 +8011,7 @@ static void vkd3d_dxbc_compiler_emit_sincos(struct vkd3d_dxbc_compiler *compiler
}
cos_id = vkd3d_spirv_build_op_glsl_std450_cos(builder, type_id, src_id);
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, dst_cos, cos_id);
}
if (sin_id)
@ -8939,7 +9015,7 @@ static uint32_t vkd3d_dxbc_compiler_get_resource_index(struct vkd3d_dxbc_compile
#endif
/* AMD drivers rely on the index being marked as nonuniform */
if (reg->modifier == VKD3DSPRM_NONUNIFORM)
if (reg->modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, index_id);
return index_id;
@ -9027,7 +9103,7 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
image->image_id = 0;
}
if (image->image_id && resource_reg->modifier == VKD3DSPRM_NONUNIFORM)
if (image->image_id && (resource_reg->modifier & VKD3DSPRM_NONUNIFORM))
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image->image_id);
if (sampled)
@ -9043,12 +9119,12 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
image->sampled_image_id = vkd3d_spirv_build_op_sampled_image(builder,
sampled_image_type_id, image->image_id, sampler_id);
if (sampler_reg->modifier == VKD3DSPRM_NONUNIFORM)
if (sampler_reg->modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, sampler_id);
/* To be strict against Vulkan spec, the sampled image itself needs to be marked as NonUniform. */
if ((image->image_id && resource_reg->modifier == VKD3DSPRM_NONUNIFORM) ||
sampler_reg->modifier == VKD3DSPRM_NONUNIFORM)
if ((image->image_id && (resource_reg->modifier & VKD3DSPRM_NONUNIFORM)) ||
(sampler_reg->modifier & VKD3DSPRM_NONUNIFORM))
{
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image->sampled_image_id);
}
@ -9135,6 +9211,12 @@ static void vkd3d_dxbc_compiler_emit_ld(struct vkd3d_dxbc_compiler *compiler,
if (dst[0].reg.type != VKD3DSPR_NULL)
{
if (!is_sparse_op)
{
/* Sparse returns a struct and we'd have to OpMemberDecorate which is a mess. */
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, &dst[0], val_id);
}
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
&dst[0], val_id, image.sampled_type, src[1].swizzle);
}
@ -9293,6 +9375,12 @@ static void vkd3d_dxbc_compiler_emit_sample(struct vkd3d_dxbc_compiler *compiler
if (dst[0].reg.type != VKD3DSPR_NULL)
{
if (!is_sparse_op)
{
/* Sparse returns a struct and we'd have to OpMemberDecorate which is a mess. */
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, &dst[0], val_id);
}
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
&dst[0], val_id, image.sampled_type, resource->swizzle);
}
@ -9361,6 +9449,12 @@ static void vkd3d_dxbc_compiler_emit_sample_c(struct vkd3d_dxbc_compiler *compil
if (dst[0].reg.type != VKD3DSPR_NULL)
{
if (!is_sparse_op)
{
/* Sparse returns a struct and we'd have to OpMemberDecorate which is a mess. */
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, &dst[0], val_id);
}
vkd3d_dxbc_compiler_emit_store_dst_scalar(compiler,
&dst[0], val_id, image.sampled_type, src[1].swizzle);
}
@ -9454,6 +9548,12 @@ static void vkd3d_dxbc_compiler_emit_gather4(struct vkd3d_dxbc_compiler *compile
if (dst[0].reg.type != VKD3DSPR_NULL)
{
if (!is_sparse_op)
{
/* Sparse returns a struct and we'd have to OpMemberDecorate which is a mess. */
vkd3d_dxbc_compiler_emit_relaxed_precision(builder, &dst[0], val_id);
}
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
&dst[0], val_id, image.sampled_type, resource->swizzle);
}
@ -9681,7 +9781,7 @@ static void vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(struct vkd3d_dxbc
ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, image.id, indices, ARRAY_SIZE(indices));
constituents[j++] = vkd3d_spirv_build_op_loadv(builder, type_id, ptr_id, access_mask, &alignment, 1);
if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM)
if (resource->reg.modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id);
}
else
@ -9821,7 +9921,7 @@ static void vkd3d_dxbc_compiler_emit_store_uav_raw_structured(struct vkd3d_dxbc_
ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, image.id, indices, ARRAY_SIZE(indices));
vkd3d_spirv_build_op_storev(builder, ptr_id, texel_id, access_mask, &alignment, 1);
if (dst->reg.modifier == VKD3DSPRM_NONUNIFORM)
if (dst->reg.modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id);
}
else
@ -10032,7 +10132,7 @@ static void vkd3d_dxbc_compiler_emit_uav_counter_instruction(struct vkd3d_dxbc_c
ctr_ptr_type_id, image_ptr, zero_id, zero_id);
/* Need to mark the pointer argument itself as non-uniform. */
if (src->reg.modifier == VKD3DSPRM_NONUNIFORM)
if (src->reg.modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, pointer_id);
}
else
@ -10195,7 +10295,7 @@ static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compil
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, image.storage_class, type_id);
pointer_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, image.id, indices, ARRAY_SIZE(indices));
if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM)
if (resource->reg.modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, pointer_id);
}
else
@ -10207,7 +10307,7 @@ static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compil
pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder,
ptr_type_id, image.id, coordinate_id, sample_id);
if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM)
if (resource->reg.modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, pointer_id);
}
@ -10258,7 +10358,7 @@ static void vkd3d_dxbc_compiler_emit_bufinfo(struct vkd3d_dxbc_compiler *compile
}
else
{
if (src->reg.modifier == VKD3DSPRM_NONUNIFORM)
if (src->reg.modifier & VKD3DSPRM_NONUNIFORM)
vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image.id);
val_id = vkd3d_spirv_build_op_array_length(builder, type_id, image.id, 0);

View File

@ -386,7 +386,8 @@ enum vkd3d_immconst_type
enum vkd3d_shader_register_modifier
{
VKD3DSPRM_NONE = 0,
VKD3DSPRM_NONUNIFORM = 1,
VKD3DSPRM_NONUNIFORM = 0x1,
VKD3DSPRM_RELAXED_PRECISION = 0x2,
};
enum vkd3d_shader_src_modifier
@ -534,7 +535,7 @@ struct vkd3d_shader_register_index
struct vkd3d_shader_register
{
enum vkd3d_shader_register_type type;
enum vkd3d_shader_register_modifier modifier;
uint32_t modifier; /* enum vkd3d_shader_register_modifier */
enum vkd3d_data_type data_type;
struct vkd3d_shader_register_index idx[3];
enum vkd3d_immconst_type immconst_type;

View File

@ -5563,8 +5563,7 @@ static void d3d12_device_caps_init_feature_options(struct d3d12_device *device)
options->DoublePrecisionFloatShaderOps = features->shaderFloat64;
options->OutputMergerLogicOp = features->logicOp;
/* Currently not supported */
options->MinPrecisionSupport = D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE;
options->MinPrecisionSupport = D3D12_SHADER_MIN_PRECISION_SUPPORT_16_BIT;
options->TiledResourcesTier = d3d12_device_determine_tiled_resources_tier(device);
options->ResourceBindingTier = d3d12_device_determine_resource_binding_tier(device);
options->PSSpecifiedStencilRefSupported = vk_info->EXT_shader_stencil_export;

View File

@ -14253,3 +14253,242 @@ void test_constant_buffer_dxil(void)
test_constant_buffers(true);
}
void test_minprecision_dxbc(void)
{
static const D3D12_VIEWPORT vp = { 0.0f, 0.0f, 2.0f, 2.0f, 0.0f, 1.0f };
static const FLOAT white[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static const D3D12_RECT sci = { 0, 0, 2, 2 };
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc;
D3D12_STATIC_SAMPLER_DESC static_sampler;
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc;
D3D12_FEATURE_DATA_D3D12_OPTIONS options;
D3D12_DESCRIPTOR_RANGE descriptor_range;
D3D12_ROOT_PARAMETER root_parameter;
D3D12_ROOT_SIGNATURE_DESC rs_desc;
struct test_context_desc desc;
struct test_context context;
struct resource_readback rb;
D3D12_SUBRESOURCE_DATA data;
ID3D12DescriptorHeap *heap;
ID3D12Resource *texture;
unsigned int x, y;
static const uint8_t tex_data[] =
{
2, 4, 6, 8,
10, 12, 14, 16,
18, 20, 22, 24,
26, 28, 30, 32,
};
static const uint32_t expected_output[] =
{
0xbdbd1422, 0xfdfd0c22,
0xfdfd0c22, 0xbdbd1422,
};
static const DWORD vs_code[] =
{
#if 0
struct VSOut
{
float4 pos : SV_Position;
min16float2 uv : UV;
};
VSOut main(uint vid : SV_VertexID)
{
VSOut vout;
if (vid == 0)
vout.pos = float4(-1, -1, 0, 1);
else if (vid == 1)
vout.pos = float4(3, -1, 0, 1);
else
vout.pos = float4(-1, 3, 0, 1);
vout.uv = min16float2(vout.pos.xy * 0.5 + 0.5);
vout.uv.y = min16float(1.0) - vout.uv.y;
return vout;
}
#endif
0x43425844, 0xeb05c6ae, 0x0b887e52, 0xad169d77, 0x0a9ce882, 0x00000001, 0x00000240, 0x00000004,
0x00000030, 0x0000006c, 0x000000cc, 0x00000230, 0x31475349, 0x00000034, 0x00000001, 0x00000008,
0x00000000, 0x00000028, 0x00000000, 0x00000006, 0x00000001, 0x00000000, 0x00000101, 0x00000000,
0x565f5653, 0x65747265, 0x00444978, 0x3147534f, 0x00000058, 0x00000002, 0x00000008, 0x00000000,
0x00000048, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000000, 0x00000000,
0x00000054, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000c03, 0x00000001, 0x505f5653,
0x7469736f, 0x006e6f69, 0xab005655, 0x58454853, 0x0000015c, 0x00010050, 0x00000057, 0x0101086a,
0x04000060, 0x00101012, 0x00000000, 0x00000006, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
0x04000065, 0x80102032, 0x00004001, 0x00000001, 0x02000068, 0x00000001, 0x07000020, 0x00100012,
0x00000000, 0x0010100a, 0x00000000, 0x00004001, 0x00000001, 0x0f000037, 0x001000f2, 0x00000000,
0x00100006, 0x00000000, 0x00004002, 0x40400000, 0xbf800000, 0x00000000, 0x3f800000, 0x00004002,
0xbf800000, 0x40400000, 0x00000000, 0x3f800000, 0x0c000037, 0x001000f2, 0x00000000, 0x00101006,
0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0xbf800000, 0xbf800000, 0x00000000, 0x3f800000,
0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0f000032, 0x00100032, 0x00000000,
0x00100046, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00004002,
0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x09000000, 0x80102022, 0x00004001, 0x00000001,
0x8010001a, 0x00000041, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x80102012, 0x00004001,
0x00000001, 0x0010000a, 0x00000000, 0x0100003e, 0x30494653, 0x00000008, 0x00000010, 0x00000000,
};
static const DWORD ps_code[] =
{
#if 0
struct VSOut
{
float4 pos : SV_Position;
min16float2 uv : UV;
};
Texture2D<min16float3> T : register(t0);
SamplerState S : register(s0);
min16float4 ps_main(VSOut vout) : SV_Target
{
min16float3 s0 = round(min16float(255.0) * T.Sample(S, vout.uv));
min16float3 s1 = round(min16float(255.0) * T.Sample(S, min16float2(1.0, 1.0) - vout.uv));
min16float adds = dot(s0 + s1, min16float(1.0).xxx);
min16float subs = dot(abs(s0 - s1), min16float(1.0).xxx);
min16float muls = dot(s0 * s1, min16float(1.0).xxx);
return min16float4(adds / min16float(255.0), subs / min16float(255.0), muls / min16float(255.0), dot(s0, s1) / min16float(255.0));
}
#endif
0x43425844, 0xff40ae01, 0x7de33435, 0x621d36ba, 0x90f202fe, 0x00000001, 0x00000410, 0x00000004,
0x00000030, 0x00000090, 0x000000cc, 0x00000400, 0x31475349, 0x00000058, 0x00000002, 0x00000008,
0x00000000, 0x00000048, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000000,
0x00000000, 0x00000054, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000001,
0x505f5653, 0x7469736f, 0x006e6f69, 0xab005655, 0x3147534f, 0x00000034, 0x00000001, 0x00000008,
0x00000000, 0x00000028, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000001,
0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000032c, 0x00000050, 0x000000cb, 0x0101086a,
0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001062,
0x80101032, 0x00004001, 0x00000001, 0x04000065, 0x801020f2, 0x00004001, 0x00000000, 0x02000068,
0x00000003, 0x0c000000, 0x80100032, 0x00004001, 0x00000000, 0x80101046, 0x00004041, 0x00000001,
0x00004002, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x8d000045, 0x800000c2, 0x00155543,
0x80100072, 0x00004001, 0x00000000, 0x80100046, 0x00004001, 0x00000000, 0x00107e46, 0x00000000,
0x00106000, 0x00000000, 0x0c000038, 0x80100072, 0x00004001, 0x00000000, 0x80100246, 0x00004001,
0x00000000, 0x00004002, 0x437f0000, 0x437f0000, 0x437f0000, 0x00000000, 0x07000040, 0x80100072,
0x00004001, 0x00000000, 0x80100246, 0x00004001, 0x00000000, 0x8d000045, 0x800000c2, 0x00155543,
0x80100072, 0x00004001, 0x00000001, 0x80101046, 0x00004001, 0x00000001, 0x00107e46, 0x00000000,
0x00106000, 0x00000000, 0x0c000038, 0x80100072, 0x00004001, 0x00000001, 0x80100246, 0x00004001,
0x00000001, 0x00004002, 0x437f0000, 0x437f0000, 0x437f0000, 0x00000000, 0x07000040, 0x80100072,
0x00004001, 0x00000001, 0x80100246, 0x00004001, 0x00000001, 0x0a000000, 0x80100072, 0x00004001,
0x00000002, 0x80100246, 0x00004001, 0x00000000, 0x80100246, 0x00004001, 0x00000001, 0x0c000010,
0x80100082, 0x00004001, 0x00000000, 0x80100246, 0x00004001, 0x00000002, 0x00004002, 0x3f800000,
0x3f800000, 0x3f800000, 0x00000000, 0x09000038, 0x80102012, 0x00004001, 0x00000000, 0x8010003a,
0x00004001, 0x00000000, 0x00004001, 0x3b808081, 0x0a000000, 0x80100072, 0x00004001, 0x00000002,
0x80100246, 0x00004041, 0x00000000, 0x80100246, 0x00004001, 0x00000001, 0x0c000010, 0x80100082,
0x00004001, 0x00000000, 0x80100246, 0x00004081, 0x00000002, 0x00004002, 0x3f800000, 0x3f800000,
0x3f800000, 0x00000000, 0x0a000038, 0x80100072, 0x00004001, 0x00000002, 0x80100246, 0x00004001,
0x00000000, 0x80100246, 0x00004001, 0x00000001, 0x0a000010, 0x80100012, 0x00004001, 0x00000000,
0x80100246, 0x00004001, 0x00000001, 0x80100246, 0x00004001, 0x00000000, 0x0c000038, 0x801020a2,
0x00004001, 0x00000000, 0x801003f6, 0x00004001, 0x00000000, 0x00004002, 0x00000000, 0x3b808081,
0x00000000, 0x3b808081, 0x0c000010, 0x80100012, 0x00004001, 0x00000000, 0x80100246, 0x00004001,
0x00000002, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x09000038, 0x80102042,
0x00004001, 0x00000000, 0x8010000a, 0x00004001, 0x00000000, 0x00004001, 0x3b808081, 0x0100003e,
0x30494653, 0x00000008, 0x00000010, 0x00000000,
};
static const D3D12_SHADER_BYTECODE vs = SHADER_BYTECODE(vs_code);
static const D3D12_SHADER_BYTECODE ps = SHADER_BYTECODE(ps_code);
memset(&desc, 0, sizeof(desc));
desc.rt_format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.rt_width = 2;
desc.rt_height = 2;
desc.no_root_signature = true;
desc.no_pipeline = true;
if (!init_test_context(&context, &desc))
return;
if (FAILED(ID3D12Device_CheckFeatureSupport(context.device, D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options))) ||
!(options.MinPrecisionSupport & D3D12_SHADER_MIN_PRECISION_SUPPORT_16_BIT))
{
skip("Device does not support 16-bit min-precision, skipping.\n");
destroy_test_context(&context);
return;
}
heap = create_gpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1);
texture = create_default_texture2d(context.device, 4, 4, 1, 1, DXGI_FORMAT_R8_UNORM,
D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST);
memset(&srv_desc, 0, sizeof(srv_desc));
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srv_desc.Format = DXGI_FORMAT_R8_UNORM;
srv_desc.Texture2D.MipLevels = 1;
srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
ID3D12Device_CreateShaderResourceView(context.device, texture, &srv_desc,
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap));
data.pData = tex_data;
data.RowPitch = 4;
data.SlicePitch = 4 * 4;
upload_texture_data(texture, &data, 1, context.queue, context.list);
reset_command_list(context.list, context.allocator);
memset(&rs_desc, 0, sizeof(rs_desc));
memset(&static_sampler, 0, sizeof(static_sampler));
memset(&root_parameter, 0, sizeof(root_parameter));
memset(&descriptor_range, 0, sizeof(descriptor_range));
rs_desc.pParameters = &root_parameter;
rs_desc.pStaticSamplers = &static_sampler;
rs_desc.NumParameters = 1;
rs_desc.NumStaticSamplers = 1;
static_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
static_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
static_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
static_sampler.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
static_sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
root_parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
root_parameter.DescriptorTable.NumDescriptorRanges = 1;
root_parameter.DescriptorTable.pDescriptorRanges = &descriptor_range;
descriptor_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descriptor_range.NumDescriptors = 1;
create_root_signature(context.device, &rs_desc, &context.root_signature);
memset(&pso_desc, 0, sizeof(pso_desc));
init_pipeline_state_desc(&pso_desc, context.root_signature, DXGI_FORMAT_R8G8B8A8_UNORM, &vs, &ps, NULL);
pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void**)&context.pipeline_state);
ID3D12GraphicsCommandList_SetDescriptorHeaps(context.list, 1, &heap);
ID3D12GraphicsCommandList_OMSetRenderTargets(context.list, 1, &context.rtv, TRUE, NULL);
ID3D12GraphicsCommandList_ClearRenderTargetView(context.list, context.rtv, white, 0, NULL);
ID3D12GraphicsCommandList_SetGraphicsRootSignature(context.list, context.root_signature);
ID3D12GraphicsCommandList_SetPipelineState(context.list, context.pipeline_state);
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(context.list, 0,
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(heap));
ID3D12GraphicsCommandList_RSSetViewports(context.list, 1, &vp);
ID3D12GraphicsCommandList_RSSetScissorRects(context.list, 1, &sci);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(context.list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D12GraphicsCommandList_DrawInstanced(context.list, 3, 1, 0, 0);
transition_resource_state(context.list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
get_texture_readback_with_command_list(context.render_target, 0, &rb, context.queue, context.list);
for (y = 0; y < 2; y++)
{
for (x = 0; x < 2; x++)
{
uint32_t expected;
uint32_t value;
value = get_readback_uint(&rb, x, y, 0);
expected = expected_output[y * 2 + x];
ok(expected == value, "Pixel %u, %u mismatch, %x != %x.\n", x, y, value, expected);
}
}
release_resource_readback(&rb);
ID3D12DescriptorHeap_Release(heap);
ID3D12Resource_Release(texture);
destroy_test_context(&context);
}

View File

@ -304,3 +304,4 @@ decl_test(test_mesh_shader_execute_indirect);
decl_test(test_amplification_shader);
decl_test(test_advanced_cbv_layout);
decl_test(test_shader_waveop_maximal_convergence);
decl_test(test_minprecision_dxbc);