Newer
Older
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
static uint32_t vkd3d_dxbc_compiler_emit_sat(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id)
{
static const float zero[] = {0.0f, 0.0f, 0.0f, 0.0f};
static const float one[] = {1.0f, 1.0f, 1.0f, 1.0f};
unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, zero_id, one_id;
zero_id = vkd3d_dxbc_compiler_get_constant(compiler,
VKD3D_TYPE_FLOAT, component_count, (const uint32_t *)zero);
one_id = vkd3d_dxbc_compiler_get_constant(compiler,
VKD3D_TYPE_FLOAT, component_count, (const uint32_t *)one);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(reg->data_type), component_count);
if (reg->data_type == VKD3D_DATA_FLOAT)
return vkd3d_spirv_build_op_glsl_std450_nclamp(builder, type_id, val_id, zero_id, one_id);
FIXME("Unhandled data type %#x.\n", reg->data_type);
return val_id;
}
static void vkd3d_dxbc_compiler_emit_store_dst(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_dst_param *dst, uint32_t val_id)
{
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_store_reg(compiler, &dst->reg, dst->write_mask, val_id);
}
/* The Vulkan spec says:
*
* "The variable decorated with GlobalInvocationId must be declared as a
* three-component vector of 32-bit integers."
*
* "The variable decorated with LocalInvocationId must be declared as a
* three-component vector of 32-bit integers."
*
* "The variable decorated with WorkgroupId must be declared as a
* three-component vector of 32-bit integers."
*
* "The variable decorated with FragCoord must be declared as a
* four-component vector of 32-bit floating-point values."
*
* "Any variable decorated with Position must be declared as a four-component
* vector of 32-bit floating-point values."
*
* "The variable decorated with VertexIndex must be declared as a scalar
* 32-bit integer."
*/
static const struct vkd3d_spirv_builtin
{
enum vkd3d_shader_input_sysval_semantic sysval;
enum vkd3d_shader_register_type reg_type;
enum vkd3d_component_type component_type;
unsigned int component_count;
SpvBuiltIn spirv_builtin;
}
vkd3d_spirv_builtin_table[] =
{
{VKD3D_SIV_NONE, VKD3DSPR_THREADID, VKD3D_TYPE_INT, 3, SpvBuiltInGlobalInvocationId},
{VKD3D_SIV_NONE, VKD3DSPR_LOCALTHREADID, VKD3D_TYPE_INT, 3, SpvBuiltInLocalInvocationId},
{VKD3D_SIV_NONE, VKD3DSPR_LOCALTHREADINDEX, VKD3D_TYPE_INT, 1, SpvBuiltInLocalInvocationIndex},
{VKD3D_SIV_NONE, VKD3DSPR_THREADGROUPID, VKD3D_TYPE_INT, 3, SpvBuiltInWorkgroupId},
{VKD3D_SIV_POSITION, ~0u, VKD3D_TYPE_FLOAT, 4, SpvBuiltInPosition},
{VKD3D_SIV_VERTEX_ID, ~0u, VKD3D_TYPE_INT, 1, SpvBuiltInVertexIndex},
};
static const struct vkd3d_spirv_builtin *vkd3d_get_spirv_builtin(enum vkd3d_shader_register_type reg_type,
enum vkd3d_shader_input_sysval_semantic sysval)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(vkd3d_spirv_builtin_table); ++i)
const struct vkd3d_spirv_builtin* current = &vkd3d_spirv_builtin_table[i];
if (current->sysval == VKD3D_SIV_NONE && current->reg_type == reg_type)
return current;
if (current->reg_type == ~0u && current->sysval == sysval)
return current;
if (sysval != VKD3D_SIV_NONE
|| (reg_type != VKD3DSPR_INPUT && reg_type != VKD3DSPR_OUTPUT && reg_type != VKD3DSPR_COLOROUT))
FIXME("Unhandled builtin (register type %#x, semantic %#x).\n", reg_type, sysval);
return NULL;
}
static void vkd3d_dxbc_compiler_decorate_builtin(struct vkd3d_dxbc_compiler *compiler,
uint32_t target_id, SpvBuiltIn builtin)
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && builtin == SpvBuiltInPosition)
builtin = SpvBuiltInFragCoord;
vkd3d_spirv_build_op_decorate1(builder, target_id, SpvDecorationBuiltIn, builtin);
}
Józef Kucia
committed
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
static const struct vkd3d_shader_signature_element *vkd3d_find_signature_element_for_reg(
const struct vkd3d_shader_signature *signature, unsigned int *signature_element_index,
const struct vkd3d_shader_register *reg, DWORD write_mask)
{
unsigned int signature_idx;
for (signature_idx = 0; signature_idx < signature->element_count; ++signature_idx)
{
if (signature->elements[signature_idx].register_idx == reg->idx[0].offset
&& (signature->elements[signature_idx].mask & 0xff) == write_mask)
{
if (signature_element_index)
*signature_element_index = signature_idx;
return &signature->elements[signature_idx];
}
}
FIXME("Could not find shader signature element (register %u, write mask %#x).\n",
reg->idx[0].offset, write_mask);
if (signature_element_index)
*signature_element_index = ~0u;
return NULL;
}
static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval)
{
unsigned int component_idx, component_count, input_component_count;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
const struct vkd3d_shader_signature_element *signature_element;
const struct vkd3d_shader_register *reg = &dst->reg;
const struct vkd3d_spirv_builtin *builtin;
enum vkd3d_component_type component_type;
uint32_t val_id = 0, input_id, var_id;
uint32_t type_id, float_type_id;
struct vkd3d_symbol reg_symbol;
SpvStorageClass storage_class;
Józef Kucia
committed
struct rb_entry *entry = NULL;
bool use_private_var = false;
DWORD write_mask;
/* vThreadIDInGroupFlattened is declared with no write mask in shader
* bytecode generated by fxc. */
write_mask = dst->write_mask;
Józef Kucia
committed
if (!write_mask && reg->type == VKD3DSPR_LOCALTHREADINDEX)
write_mask = VKD3DSP_WRITEMASK_0;
Józef Kucia
committed
signature_element = vkd3d_find_signature_element_for_reg(compiler->input_signature,
NULL, reg, write_mask);
builtin = vkd3d_get_spirv_builtin(reg->type, sysval);
component_idx = vkd3d_write_mask_get_component_idx(write_mask);
component_count = vkd3d_write_mask_component_count(write_mask);
if (builtin)
{
component_type = builtin->component_type;
input_component_count = builtin->component_count;
}
else
{
Józef Kucia
committed
component_type = signature_element ? signature_element->component_type : VKD3D_TYPE_FLOAT;
Józef Kucia
committed
input_component_count = component_count;
assert(component_count <= input_component_count);
Józef Kucia
committed
storage_class = SpvStorageClassInput;
input_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
Józef Kucia
committed
storage_class, component_type, input_component_count);
vkd3d_spirv_add_iface_variable(builder, input_id);
vkd3d_dxbc_compiler_decorate_builtin(compiler, input_id, builtin->spirv_builtin);
if (component_idx)
FIXME("Unhandled component index %u.\n", component_idx);
Józef Kucia
committed
vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationLocation, reg->idx[0].offset);
if (component_idx)
vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx);
}
if (component_type != VKD3D_TYPE_FLOAT || component_count != VKD3D_VEC4_SIZE)
type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count);
val_id = vkd3d_spirv_build_op_load(builder, type_id, input_id, SpvMemoryAccessMaskNone);
if (component_type != VKD3D_TYPE_FLOAT)
{
float_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, input_component_count);
val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id);
}
if (val_id && input_component_count != component_count)
val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, val_id, VKD3DSP_NOSWIZZLE, write_mask);
Józef Kucia
committed
vkd3d_symbol_make_register(®_symbol, reg);
Józef Kucia
committed
if (!use_private_var)
{
var_id = input_id;
}
else if (!(entry = rb_get(&compiler->symbol_table, ®_symbol)))
{
storage_class = SpvStorageClassPrivate;
var_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
storage_class, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
}
Józef Kucia
committed
if (!entry)
{
reg_symbol.id = var_id;
reg_symbol.info.storage_class = storage_class;
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
Józef Kucia
committed
}
if (use_private_var)
{
assert(val_id);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_store_reg(compiler, reg, write_mask, val_id);
return input_id;
static uint32_t vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval)
{
Józef Kucia
committed
unsigned int component_idx, component_count, output_component_count;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
const struct vkd3d_shader_signature_element *signature_element;
const struct vkd3d_shader_register *reg = &dst->reg;
const struct vkd3d_spirv_builtin *builtin;
Józef Kucia
committed
enum vkd3d_component_type component_type;
struct vkd3d_symbol reg_symbol;
SpvStorageClass storage_class;
Józef Kucia
committed
struct rb_entry *entry = NULL;
unsigned int signature_idx;
bool use_private_variable;
uint32_t id, var_id;
Józef Kucia
committed
signature_element = vkd3d_find_signature_element_for_reg(compiler->output_signature,
&signature_idx, reg, dst->write_mask);
Józef Kucia
committed
builtin = vkd3d_get_spirv_builtin(dst->reg.type, sysval);
component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
if (builtin)
{
component_type = builtin->component_type;
output_component_count = builtin->component_count;
}
else
{
component_type = signature_element ? signature_element->component_type : VKD3D_TYPE_FLOAT;
output_component_count = component_count;
}
assert(component_count <= output_component_count);
Józef Kucia
committed
storage_class = SpvStorageClassOutput;
id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
Józef Kucia
committed
storage_class, component_type, component_count);
vkd3d_spirv_add_iface_variable(builder, id);
Józef Kucia
committed
{
vkd3d_dxbc_compiler_decorate_builtin(compiler, id, builtin->spirv_builtin);
Józef Kucia
committed
if (component_idx)
FIXME("Unhandled component index %u.\n", component_idx);
}
Józef Kucia
committed
{
vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationLocation, reg->idx[0].offset);
Józef Kucia
committed
if (component_idx)
vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationComponent, component_idx);
}
if (signature_element)
{
compiler->output_info[signature_idx].id = id;
compiler->output_info[signature_idx].component_type = component_type;
}
Józef Kucia
committed
if ((use_private_variable = component_type != VKD3D_TYPE_FLOAT || component_count != VKD3D_VEC4_SIZE))
storage_class = SpvStorageClassPrivate;
Józef Kucia
committed
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
vkd3d_symbol_make_register(®_symbol, reg);
if (!use_private_variable)
var_id = id;
else if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
var_id = RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry)->id;
else
var_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
storage_class, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
if (!entry)
{
reg_symbol.id = var_id;
reg_symbol.info.storage_class = storage_class;
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
}
if (use_private_variable)
{
compiler->private_output_variable[reg->idx[0].offset] = var_id;
if (!compiler->output_setup_function_id)
compiler->output_setup_function_id = vkd3d_spirv_alloc_id(builder);
}
return id;
}
static void vkd3d_dxbc_compiler_emit_dcl_global_flags(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
if (instruction->flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS))
FIXME("Unrecognized global flags %#x.\n", instruction->flags);
else
WARN("Unhandled global flags %#x.\n", instruction->flags);
}
static void vkd3d_dxbc_compiler_emit_dcl_temps(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
unsigned int i;
Józef Kucia
committed
uint32_t id;
/* FIXME: Make sure that function variables are declared at the beginning
* of the first block in the function. Otherwise, we'll produce invalid
* SPIR-V code. */
assert(!compiler->temp_count);
compiler->temp_count = instruction->declaration.count;
for (i = 0; i < compiler->temp_count; ++i)
{
Józef Kucia
committed
id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->function_stream,
SpvStorageClassFunction, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
if (!i)
compiler->temp_id = id;
assert(id == compiler->temp_id + i);
vkd3d_spirv_build_op_name(builder, id, "r%u", i);
static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t vec4_id, array_type_id, length_id, struct_id, pointer_type_id, var_id;
Józef Kucia
committed
const struct vkd3d_shader_register *reg = &instruction->declaration.src.reg;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
struct vkd3d_symbol reg_symbol;
Józef Kucia
committed
unsigned int cb_size;
assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC));
if (instruction->flags & VKD3DSI_INDEXED_DYNAMIC)
vkd3d_spirv_enable_capability(builder, SpvCapabilityUniformBufferArrayDynamicIndexing);
Józef Kucia
committed
cb_size = reg->idx[1].offset;
vec4_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, cb_size);
array_type_id = vkd3d_spirv_build_op_type_array(builder, vec4_id, length_id);
vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 16);
struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0);
vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0);
vkd3d_spirv_build_op_name(builder, struct_id, "cb%u_struct", cb_size);
pointer_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, struct_id);
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
pointer_type_id, SpvStorageClassUniform, 0);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
Józef Kucia
committed
vkd3d_symbol_make_register(®_symbol, reg);
reg_symbol.id = var_id;
reg_symbol.info.storage_class = SpvStorageClassUniform;
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
}
static void vkd3d_dxbc_compiler_emit_dcl_immediate_constant_buffer(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb;
uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
struct vkd3d_shader_register reg;
struct vkd3d_symbol reg_symbol;
unsigned int i;
if (!(elements = vkd3d_calloc(icb->vec4_count, sizeof(*elements))))
return;
for (i = 0; i < icb->vec4_count; ++i)
elements[i] = vkd3d_dxbc_compiler_get_constant(compiler,
VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, icb->vec4_count);
type_id = vkd3d_spirv_build_op_type_array(builder, type_id, length_id);
const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->vec4_count);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, SpvStorageClassPrivate, const_id);
vkd3d_spirv_build_op_name(builder, icb_id, "icb");
vkd3d_free(elements);
memset(®, 0, sizeof(reg));
reg.type = VKD3DSPR_IMMCONSTBUFFER;
vkd3d_symbol_make_register(®_symbol, ®);
reg_symbol.id = icb_id;
reg_symbol.info.storage_class = SpvStorageClassPrivate;
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
}
static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
const struct vkd3d_shader_register *reg = &instruction->declaration.dst.reg;
const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, ptr_type_id, var_id;
struct vkd3d_symbol reg_symbol;
Józef Kucia
committed
type_id = vkd3d_spirv_get_op_type_sampler(builder);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, storage_class, 0);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
vkd3d_symbol_make_register(®_symbol, reg);
reg_symbol.id = var_id;
reg_symbol.info.storage_class = storage_class;
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
}
static const struct vkd3d_spirv_resource_type
enum vkd3d_shader_resource_type resource_type;
SpvDim dim;
uint32_t arrayed;
uint32_t ms;
unsigned int coordinate_component_count;
SpvCapability capability;
SpvCapability uav_capability;
}
vkd3d_spirv_resource_type_table[] =
{
{VKD3D_SHADER_RESOURCE_BUFFER, SpvDimBuffer, 0, 0, 1,
SpvCapabilitySampledBuffer, SpvCapabilityImageBuffer},
{VKD3D_SHADER_RESOURCE_TEXTURE_1D, SpvDim1D, 0, 0, 1,
SpvCapabilitySampled1D, SpvCapabilityImage1D},
{VKD3D_SHADER_RESOURCE_TEXTURE_2DMS, SpvDim2D, 0, 1, 2},
{VKD3D_SHADER_RESOURCE_TEXTURE_2D, SpvDim2D, 0, 0, 2},
{VKD3D_SHADER_RESOURCE_TEXTURE_3D, SpvDim3D, 0, 0, 3},
{VKD3D_SHADER_RESOURCE_TEXTURE_CUBE, SpvDimCube, 0, 0, 3},
{VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY, SpvDim1D, 1, 0, 2,
SpvCapabilitySampled1D, SpvCapabilityImage1D},
{VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY, SpvDim2D, 1, 0, 3},
{VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY, SpvDimCube, 1, 0, 3,
SpvCapabilitySampledCubeArray, SpvCapabilityImageCubeArray},
static const struct vkd3d_spirv_resource_type *vkd3d_get_spirv_resource_type(
enum vkd3d_shader_resource_type resource_type)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(vkd3d_spirv_resource_type_table); ++i)
const struct vkd3d_spirv_resource_type* current = &vkd3d_spirv_resource_type_table[i];
if (current->resource_type == resource_type)
return current;
FIXME("Unhandled resource type %#x.\n", resource_type);
return NULL;
}
static const struct vkd3d_spirv_resource_type *vkd3d_dxbc_compiler_enable_resource_type(
struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_resource_type resource_type, bool is_uav)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_spirv_resource_type *resource_type_info;
if (!(resource_type_info = vkd3d_get_spirv_resource_type(resource_type)))
return NULL;
if (resource_type_info->capability)
vkd3d_spirv_enable_capability(builder, resource_type_info->capability);
if (is_uav && resource_type_info->uav_capability)
vkd3d_spirv_enable_capability(builder, resource_type_info->uav_capability);
return resource_type_info;
static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_compiler *compiler,
Józef Kucia
committed
const struct vkd3d_shader_semantic *semantic)
{
const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
const struct vkd3d_shader_register *reg = &semantic->reg.reg;
const struct vkd3d_spirv_resource_type *resource_type_info;
uint32_t sampled_type_id, type_id, ptr_type_id, var_id;
enum vkd3d_component_type sampled_type;
struct vkd3d_symbol resource_symbol;
Józef Kucia
committed
bool is_uav;
Józef Kucia
committed
is_uav = reg->type == VKD3DSPR_UAV;
if (!(resource_type_info = vkd3d_dxbc_compiler_enable_resource_type(compiler,
semantic->resource_type, is_uav)))
{
FIXME("Failed to emit resource declaration.\n");
return;
}
sampled_type = vkd3d_component_type_from_data_type(semantic->resource_data_type);
sampled_type_id = vkd3d_spirv_get_type_id(builder, sampled_type, 1);
type_id = vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim,
0, resource_type_info->arrayed, resource_type_info->ms, is_uav ? 2 : 1, SpvImageFormatUnknown);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, storage_class, 0);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
Józef Kucia
committed
vkd3d_symbol_make_resource(&resource_symbol, reg);
resource_symbol.id = var_id;
resource_symbol.info.resource.sampled_type = sampled_type;
resource_symbol.info.resource.type_id = type_id;
resource_symbol.info.resource.coordinate_mask = (1u << resource_type_info->coordinate_component_count) - 1;
vkd3d_dxbc_compiler_put_symbol(compiler, &resource_symbol);
static void vkd3d_dxbc_compiler_emit_dcl_resource(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &instruction->declaration.semantic);
}
static void vkd3d_dxbc_compiler_emit_dcl_uav_typed(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
if (instruction->flags)
FIXME("Unhandled flags %#x.\n", instruction->flags);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &instruction->declaration.semantic);
static void vkd3d_dxbc_compiler_emit_dcl_input(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.dst, VKD3D_SIV_NONE);
}
static void vkd3d_dxbc_compiler_emit_interpolation_decorations(struct vkd3d_dxbc_compiler *compiler,
uint32_t id, enum vkd3d_shader_interpolation_mode mode)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
switch (mode)
{
case VKD3DSIM_CONSTANT:
vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0);
break;
case VKD3DSIM_LINEAR:
break;
default:
FIXME("Unhandled interpolation mode %#x.\n", mode);
break;
}
}
static void vkd3d_dxbc_compiler_emit_dcl_input_ps(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t input_id;
input_id = vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.dst, VKD3D_SIV_NONE);
vkd3d_dxbc_compiler_emit_interpolation_decorations(compiler, input_id, instruction->flags);
static void vkd3d_dxbc_compiler_emit_dcl_input_ps_siv(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t input_id;
input_id = vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg,
instruction->declaration.register_semantic.sysval_semantic);
if (!instruction->declaration.register_semantic.sysval_semantic)
vkd3d_dxbc_compiler_emit_interpolation_decorations(compiler, input_id, instruction->flags);
static void vkd3d_dxbc_compiler_emit_dcl_input_sgv(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg,
instruction->declaration.register_semantic.sysval_semantic);
}
static void vkd3d_dxbc_compiler_emit_dcl_output(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
vkd3d_dxbc_compiler_emit_output(compiler, &instruction->declaration.dst, VKD3D_SIV_NONE);
}
static void vkd3d_dxbc_compiler_emit_dcl_output_siv(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
vkd3d_dxbc_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg,
instruction->declaration.register_semantic.sysval_semantic);
}
static void vkd3d_dxbc_compiler_emit_dcl_thread_group(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
const struct vkd3d_shader_thread_group_size *group_size = &instruction->declaration.thread_group_size;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
vkd3d_spirv_set_local_size(builder, group_size->x, group_size->y, group_size->z);
}
static SpvOp vkd3d_dxbc_compiler_map_alu_instruction(const struct vkd3d_shader_instruction *instruction)
{
static const struct
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
SpvOp spirv_op;
}
alu_ops[] =
{
{VKD3DSIH_ADD, SpvOpFAdd},
{VKD3DSIH_AND, SpvOpBitwiseAnd},
{VKD3DSIH_BFREV, SpvOpBitReverse},
{VKD3DSIH_COUNTBITS, SpvOpBitCount},
{VKD3DSIH_DIV, SpvOpFDiv},
{VKD3DSIH_FTOI, SpvOpConvertFToS},
{VKD3DSIH_FTOU, SpvOpConvertFToU},
{VKD3DSIH_IADD, SpvOpIAdd},
{VKD3DSIH_ISHL, SpvOpShiftLeftLogical},
{VKD3DSIH_ISHR, SpvOpShiftRightArithmetic},
{VKD3DSIH_ITOF, SpvOpConvertSToF},
{VKD3DSIH_MUL, SpvOpFMul},
{VKD3DSIH_NOT, SpvOpNot},
{VKD3DSIH_OR, SpvOpBitwiseOr},
{VKD3DSIH_USHR, SpvOpShiftRightLogical},
{VKD3DSIH_UTOF, SpvOpConvertUToF},
{VKD3DSIH_XOR, SpvOpBitwiseXor},
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(alu_ops); ++i)
{
if (alu_ops[i].handler_idx == instruction->handler_idx)
return alu_ops[i].spirv_op;
}
return SpvOpMax;
}
static void vkd3d_dxbc_compiler_emit_alu_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t src_ids[VKD3D_DXBC_MAX_SOURCE_COUNT];
unsigned int component_count;
uint32_t type_id, val_id;
unsigned int i;
SpvOp op;
op = vkd3d_dxbc_compiler_map_alu_instruction(instruction);
if (op == SpvOpMax)
{
Józef Kucia
committed
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
return;
}
assert(instruction->dst_count == 1);
assert(instruction->src_count <= VKD3D_DXBC_MAX_SOURCE_COUNT);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst->reg.data_type), component_count);
for (i = 0; i < instruction->src_count; ++i)
src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
val_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, op, type_id,
src_ids, instruction->src_count);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
static enum GLSLstd450 vkd3d_dxbc_compiler_map_ext_glsl_instruction(
const struct vkd3d_shader_instruction *instruction)
{
static const struct
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
enum GLSLstd450 glsl_inst;
}
glsl_insts[] =
{
{VKD3DSIH_EXP, GLSLstd450Exp2},
{VKD3DSIH_FIRSTBIT_HI, GLSLstd450FindUMsb},
{VKD3DSIH_FIRSTBIT_LO, GLSLstd450FindILsb},
{VKD3DSIH_FIRSTBIT_SHI, GLSLstd450FindSMsb},
{VKD3DSIH_FRC, GLSLstd450Fract},
{VKD3DSIH_IMAX, GLSLstd450SMax},
{VKD3DSIH_IMIN, GLSLstd450SMin},
{VKD3DSIH_LOG, GLSLstd450Log2},
{VKD3DSIH_MAD, GLSLstd450Fma},
{VKD3DSIH_MAX, GLSLstd450FMax},
{VKD3DSIH_MIN, GLSLstd450FMin},
{VKD3DSIH_ROUND_NI, GLSLstd450Floor},
{VKD3DSIH_ROUND_PI, GLSLstd450Ceil},
{VKD3DSIH_RSQ, GLSLstd450InverseSqrt},
{VKD3DSIH_SQRT, GLSLstd450Sqrt},
{VKD3DSIH_UMAX, GLSLstd450UMax},
{VKD3DSIH_UMIN, GLSLstd450UMin},
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(glsl_insts); ++i)
{
if (glsl_insts[i].handler_idx == instruction->handler_idx)
return glsl_insts[i].glsl_inst;
}
return GLSLstd450Bad;
}
static void vkd3d_dxbc_compiler_emit_ext_glsl_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t src_id[VKD3D_DXBC_MAX_SOURCE_COUNT];
uint32_t instr_set_id, type_id, val_id;
unsigned int component_count;
enum GLSLstd450 glsl_inst;
unsigned int i;
glsl_inst = vkd3d_dxbc_compiler_map_ext_glsl_instruction(instruction);
if (glsl_inst == GLSLstd450Bad)
{
Józef Kucia
committed
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
return;
}
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
assert(instruction->dst_count == 1);
assert(instruction->src_count <= VKD3D_DXBC_MAX_SOURCE_COUNT);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst->reg.data_type), component_count);
for (i = 0; i < instruction->src_count; ++i)
src_id[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id,
instr_set_id, glsl_inst, src_id, instruction->src_count);
if (instruction->handler_idx == VKD3DSIH_FIRSTBIT_HI
|| instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI)
{
/* In D3D bits are numbered from the most significant bit. */
val_id = vkd3d_spirv_build_op_isub(builder, type_id,
vkd3d_dxbc_compiler_get_constant_uint(compiler, 31), val_id);
}
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
static void vkd3d_dxbc_compiler_emit_mov(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t val_id, dst_val_id, type_id, dst_id, src_id;
uint32_t components[VKD3D_VEC4_SIZE];
unsigned int i, component_count;
component_count = vkd3d_write_mask_component_count(dst->write_mask);
if (component_count == 1 || component_count == VKD3D_VEC4_SIZE
|| dst->modifiers || src->modifiers || src->reg.type == VKD3DSPR_IMMCONST)
{
val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
}
else
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
dst_id = vkd3d_dxbc_compiler_get_register_id(compiler, &dst->reg);
src_id = vkd3d_dxbc_compiler_get_register_id(compiler, &src->reg);
val_id = vkd3d_spirv_build_op_load(builder, type_id, src_id, SpvMemoryAccessMaskNone);
dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone);
for (i = 0; i < ARRAY_SIZE(components); ++i)
{
if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))
components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i);
else
components[i] = i;
}
val_id = vkd3d_spirv_build_op_vector_shuffle(builder,
type_id, dst_val_id, val_id, components, VKD3D_VEC4_SIZE);
vkd3d_spirv_build_op_store(builder, dst_id, val_id, SpvMemoryAccessMaskNone);
}
static uint32_t vkd3d_dxbc_compiler_emit_int_to_bool(struct vkd3d_dxbc_compiler *compiler,
enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
static const uint32_t zero[VKD3D_VEC4_SIZE];
uint32_t type_id;
SpvOp op;
assert(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z)));
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_BOOL, component_count);
op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual;
return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id,
vkd3d_dxbc_compiler_get_constant(compiler, VKD3D_TYPE_UINT, component_count, zero));
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
}
static void vkd3d_dxbc_compiler_emit_movc(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t condition_id, src1_id, src2_id, type_id, val_id;
unsigned int component_count;
condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
src2_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[2], dst->write_mask);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, component_count);
condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id);
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
static void vkd3d_dxbc_compiler_emit_swapc(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t condition_id, src1_id, src2_id, type_id, val_id;
unsigned int component_count;
assert(dst[0].write_mask == dst[1].write_mask);
condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
src2_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[2], dst->write_mask);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, component_count);
condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id);
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src2_id, src1_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[0], val_id);
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[1], val_id);
}
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
static void vkd3d_dxbc_compiler_emit_dot(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t type_id, val_id, src_ids[2];
DWORD write_mask;
unsigned int i;
assert(vkd3d_write_mask_component_count(dst->write_mask) == 1);
if (instruction->handler_idx == VKD3DSIH_DP4)
write_mask = VKD3DSP_WRITEMASK_ALL;
else if (instruction->handler_idx == VKD3DSIH_DP3)
write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2;
else
write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1;
assert(instruction->src_count == ARRAY_SIZE(src_ids));
for (i = 0; i < instruction->src_count; ++i)
Józef Kucia
committed
src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst->reg.data_type), 1);
val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
SpvOpDot, type_id, src_ids[0], src_ids[1]);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
static void vkd3d_dxbc_compiler_emit_rcp(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t type_id, src_id, val_id;
unsigned int component_count;
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst->reg.data_type), component_count);
src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask);
val_id = vkd3d_spirv_build_op_fdiv(builder, type_id,
vkd3d_dxbc_compiler_get_constant_float(compiler, 1.0f), src_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
static void vkd3d_dxbc_compiler_emit_imul(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t type_id, val_id, src0_id, src1_id;
unsigned int component_count;
if (dst[0].reg.type != VKD3DSPR_NULL)
FIXME("Extended multiplies not implemented.\n"); /* SpvOpSMulExtended */
if (dst[1].reg.type == VKD3DSPR_NULL)
return;
component_count = vkd3d_write_mask_component_count(dst[1].write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst[1].reg.data_type), component_count);
src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask);
src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask);
val_id = vkd3d_spirv_build_op_imul(builder, type_id, src0_id, src1_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[1], val_id);
}
static void vkd3d_dxbc_compiler_emit_imad(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t type_id, val_id, src_ids[3];