Newer
Older
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
{-1.0 / 16.0, -3.0 / 16.0},
{-3.0 / 16.0, 2.0 / 16.0},
{ 4.0 / 16.0, -1.0 / 16.0},
{-5.0 / 16.0, -2.0 / 16.0},
{ 2.0 / 16.0, 5.0 / 16.0},
{ 5.0 / 16.0, 3.0 / 16.0},
{ 3.0 / 16.0, -5.0 / 16.0},
{-2.0 / 16.0, 6.0 / 16.0},
{ 0.0 / 16.0, -7.0 / 16.0},
{-4.0 / 16.0, -6.0 / 16.0},
{-6.0 / 16.0, 4.0 / 16.0},
{-8.0 / 16.0, 0.0 / 16.0},
{ 7.0 / 16.0, -4.0 / 16.0},
{ 6.0 / 16.0, 7.0 / 16.0},
{-7.0 / 16.0, -8.0 / 16.0},
};
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t constituents[ARRAY_SIZE(standard_sample_positions)];
const struct vkd3d_shader_dst_param *dst = instruction->dst;
uint32_t array_type_id, length_id, index_id, id;
uint32_t sample_count_id, sample_index_id;
uint32_t type_id, bool_id, ptr_type_id;
unsigned int i;
Elizabeth Figura
committed
sample_count_id = spirv_compiler_emit_query_sample_count(compiler, &instruction->src[0]);
sample_index_id = spirv_compiler_emit_load_src(compiler, &instruction->src[1], VKD3DSP_WRITEMASK_0);
Henri Verbeet
committed
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
index_id = vkd3d_spirv_build_op_iadd(builder, type_id, sample_count_id, sample_index_id);
index_id = vkd3d_spirv_build_op_isub(builder,
Elizabeth Figura
committed
type_id, index_id, spirv_compiler_get_constant_uint(compiler, 1));
/* Validate sample index. */
Henri Verbeet
committed
bool_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, 1);
id = vkd3d_spirv_build_op_logical_and(builder, bool_id,
vkd3d_spirv_build_op_uless_than(builder, bool_id, sample_index_id, sample_count_id),
vkd3d_spirv_build_op_uless_than_equal(builder,
Elizabeth Figura
committed
bool_id, sample_index_id, spirv_compiler_get_constant_uint(compiler, 16)));
index_id = vkd3d_spirv_build_op_select(builder, type_id,
Elizabeth Figura
committed
id, index_id, spirv_compiler_get_constant_uint(compiler, 0));
Henri Verbeet
committed
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2);
if (!(id = compiler->sample_positions_id))
{
Elizabeth Figura
committed
length_id = spirv_compiler_get_constant_uint(compiler, ARRAY_SIZE(standard_sample_positions));
array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
for (i = 0; i < ARRAY_SIZE(standard_sample_positions); ++ i)
{
Elizabeth Figura
committed
constituents[i] = spirv_compiler_get_constant(compiler,
Henri Verbeet
committed
VKD3D_SHADER_COMPONENT_FLOAT, 2, (const uint32_t *)standard_sample_positions[i]);
}
id = vkd3d_spirv_build_op_constant_composite(builder, array_type_id, constituents, ARRAY_SIZE(constituents));
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, array_type_id);
id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, SpvStorageClassPrivate, id);
vkd3d_spirv_build_op_name(builder, id, "sample_pos");
compiler->sample_positions_id = id;
}
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, id, index_id);
id = vkd3d_spirv_build_op_load(builder, type_id, id, SpvMemoryAccessMaskNone);
Elizabeth Figura
committed
id = spirv_compiler_emit_swizzle(compiler, id, VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1,
Henri Verbeet
committed
VKD3D_SHADER_COMPONENT_FLOAT, instruction->src[0].swizzle, dst->write_mask);
Elizabeth Figura
committed
spirv_compiler_emit_store_dst(compiler, dst, id);
Elizabeth Figura
committed
static void spirv_compiler_emit_eval_attrib(struct spirv_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;
const struct vkd3d_shader_register *input = &src[0].reg;
uint32_t instr_set_id, type_id, val_id, src_ids[2];
struct vkd3d_shader_register_info register_info;
unsigned int src_count = 0;
enum GLSLstd450 op;
Elizabeth Figura
committed
if (!spirv_compiler_get_register_info(compiler, input, ®ister_info))
return;
if (register_info.storage_class != SpvStorageClassInput)
{
FIXME("Not supported for storage class %#x.\n", register_info.storage_class);
return;
}
vkd3d_spirv_enable_capability(builder, SpvCapabilityInterpolationFunction);
src_ids[src_count++] = register_info.id;
if (instruction->handler_idx == VKD3DSIH_EVAL_CENTROID)
{
op = GLSLstd450InterpolateAtCentroid;
}
else
{
assert(instruction->handler_idx == VKD3DSIH_EVAL_SAMPLE_INDEX);
op = GLSLstd450InterpolateAtSample;
Elizabeth Figura
committed
src_ids[src_count++] = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0);
Henri Verbeet
committed
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT,
Henri Verbeet
committed
vsir_write_mask_component_count(register_info.write_mask));
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count);
Elizabeth Figura
committed
val_id = spirv_compiler_emit_swizzle(compiler, val_id, register_info.write_mask,
Henri Verbeet
committed
VKD3D_SHADER_COMPONENT_FLOAT, src[0].swizzle, dst->write_mask);
Elizabeth Figura
committed
spirv_compiler_emit_store_dst(compiler, dst, val_id);
/* From the Vulkan spec:
*
* "Scope for execution must be limited to: * Workgroup * Subgroup"
*
* "Scope for memory must be limited to: * Device * Workgroup * Invocation"
*/
Elizabeth Figura
committed
static void spirv_compiler_emit_sync(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
unsigned int memory_semantics = SpvMemorySemanticsAcquireReleaseMask;
SpvScope execution_scope = SpvScopeMax;
SpvScope memory_scope = SpvScopeDevice;
uint32_t flags = instruction->flags;
if (flags & VKD3DSSF_GROUP_SHARED_MEMORY)
{
memory_scope = SpvScopeWorkgroup;
memory_semantics |= SpvMemorySemanticsWorkgroupMemoryMask;
flags &= ~VKD3DSSF_GROUP_SHARED_MEMORY;
}
if (flags & VKD3DSSF_THREAD_GROUP)
{
execution_scope = SpvScopeWorkgroup;
flags &= ~VKD3DSSF_THREAD_GROUP;
}
if (flags & VKD3DSSF_GLOBAL_UAV)
{
memory_scope = SpvScopeDevice;
memory_semantics |= SpvMemorySemanticsImageMemoryMask;
flags &= ~VKD3DSSF_GLOBAL_UAV;
}
if (flags)
{
FIXME("Unhandled sync flags %#x.\n", flags);
memory_scope = SpvScopeDevice;
execution_scope = SpvScopeWorkgroup;
memory_semantics |= SpvMemorySemanticsUniformMemoryMask
| SpvMemorySemanticsSubgroupMemoryMask
| SpvMemorySemanticsWorkgroupMemoryMask
| SpvMemorySemanticsCrossWorkgroupMemoryMask
| SpvMemorySemanticsAtomicCounterMemoryMask
| SpvMemorySemanticsImageMemoryMask;
}
Elizabeth Figura
committed
spirv_compiler_emit_barrier(compiler, execution_scope, memory_scope, memory_semantics);
Elizabeth Figura
committed
static void spirv_compiler_emit_emit_stream(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
unsigned int stream_idx;
if (instruction->handler_idx == VKD3DSIH_EMIT_STREAM)
stream_idx = instruction->src[0].reg.idx[0].offset;
else
stream_idx = 0;
if (stream_idx)
{
FIXME("Multiple streams are not supported yet.\n");
return;
}
Elizabeth Figura
committed
spirv_compiler_emit_shader_epilogue_invocation(compiler);
vkd3d_spirv_build_op_emit_vertex(builder);
}
Elizabeth Figura
committed
static void spirv_compiler_emit_cut_stream(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
unsigned int stream_idx;
if (instruction->handler_idx == VKD3DSIH_CUT_STREAM)
stream_idx = instruction->src[0].reg.idx[0].offset;
else
stream_idx = 0;
if (stream_idx)
{
FIXME("Multiple streams are not supported yet.\n");
return;
}
vkd3d_spirv_build_op_end_primitive(builder);
}
/* This function is called after declarations are processed. */
Elizabeth Figura
committed
static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler)
Elizabeth Figura
committed
spirv_compiler_emit_push_constant_buffers(compiler);
if (compiler->xfb_info && compiler->xfb_info->element_count
&& compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY)
Elizabeth Figura
committed
spirv_compiler_emit_point_size(compiler);
Henri Verbeet
committed
static bool is_dcl_instruction(enum vkd3d_shader_opcode handler_idx)
return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT)
|| handler_idx == VKD3DSIH_HS_DECLS;
Conor McCarthy
committed
static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
Józef Kucia
committed
int ret = VKD3D_OK;
if (!is_dcl_instruction(instruction->handler_idx) && !compiler->after_declarations_section)
{
compiler->after_declarations_section = true;
Elizabeth Figura
committed
spirv_compiler_emit_main_prolog(compiler);
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_GLOBAL_FLAGS:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_global_flags(compiler, instruction);
case VKD3DSIH_DCL_INDEXABLE_TEMP:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_indexable_temp(compiler, instruction);
case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_immediate_constant_buffer(compiler, instruction);
case VKD3DSIH_DCL_TGSM_RAW:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_tgsm_raw(compiler, instruction);
case VKD3DSIH_DCL_TGSM_STRUCTURED:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_tgsm_structured(compiler, instruction);
case VKD3DSIH_DCL_INPUT_PS:
case VKD3DSIH_DCL_INPUT:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_input(compiler, instruction);
case VKD3DSIH_DCL_OUTPUT:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_output(compiler, instruction);
case VKD3DSIH_DCL_STREAM:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_stream(compiler, instruction);
case VKD3DSIH_DCL_VERTICES_OUT:
Elizabeth Figura
committed
spirv_compiler_emit_output_vertex_count(compiler, instruction);
case VKD3DSIH_DCL_INPUT_PRIMITIVE:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_input_primitive(compiler, instruction);
case VKD3DSIH_DCL_OUTPUT_TOPOLOGY:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_output_topology(compiler, instruction);
case VKD3DSIH_DCL_GS_INSTANCES:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_gs_instances(compiler, instruction);
case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT:
Elizabeth Figura
committed
spirv_compiler_emit_output_vertex_count(compiler, instruction);
case VKD3DSIH_DCL_TESSELLATOR_DOMAIN:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_tessellator_domain(compiler, instruction);
case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE:
Elizabeth Figura
committed
spirv_compiler_emit_tessellator_output_primitive(compiler,
instruction->declaration.tessellator_output_primitive);
break;
case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING:
Elizabeth Figura
committed
spirv_compiler_emit_tessellator_partitioning(compiler,
instruction->declaration.tessellator_partitioning);
break;
case VKD3DSIH_DCL_THREAD_GROUP:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_thread_group(compiler, instruction);
case VKD3DSIH_HS_CONTROL_POINT_PHASE:
case VKD3DSIH_HS_FORK_PHASE:
case VKD3DSIH_HS_JOIN_PHASE:
Elizabeth Figura
committed
spirv_compiler_enter_shader_phase(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_mov(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_movc(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_swapc(compiler, instruction);
case VKD3DSIH_ADD:
case VKD3DSIH_AND:
case VKD3DSIH_COUNTBITS:
case VKD3DSIH_FREM:
case VKD3DSIH_ITOF:
case VKD3DSIH_ITOI:
case VKD3DSIH_NOT:
case VKD3DSIH_OR:
case VKD3DSIH_UTOU:
case VKD3DSIH_XOR:
ret = spirv_compiler_emit_alu_instruction(compiler, instruction);
case VKD3DSIH_FIRSTBIT_HI:
case VKD3DSIH_FIRSTBIT_LO:
case VKD3DSIH_FIRSTBIT_SHI:
case VKD3DSIH_IMAX:
case VKD3DSIH_IMIN:
case VKD3DSIH_MAD:
case VKD3DSIH_MAX:
case VKD3DSIH_MIN:
case VKD3DSIH_ROUND_NE:
case VKD3DSIH_ROUND_NI:
case VKD3DSIH_ROUND_PI:
case VKD3DSIH_ROUND_Z:
case VKD3DSIH_RSQ:
case VKD3DSIH_UMAX:
case VKD3DSIH_UMIN:
Elizabeth Figura
committed
spirv_compiler_emit_ext_glsl_instruction(compiler, instruction);
break;
case VKD3DSIH_DP4:
case VKD3DSIH_DP3:
case VKD3DSIH_DP2:
Elizabeth Figura
committed
spirv_compiler_emit_dot(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_rcp(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_sincos(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_imul(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_imad(compiler, instruction);
case VKD3DSIH_IDIV:
spirv_compiler_emit_int_div(compiler, instruction);
case VKD3DSIH_DTOI:
case VKD3DSIH_FTOI:
spirv_compiler_emit_ftoi(compiler, instruction);
break;
case VKD3DSIH_DTOU:
case VKD3DSIH_FTOU:
spirv_compiler_emit_ftou(compiler, instruction);
break;
case VKD3DSIH_DEQO:
case VKD3DSIH_DGEO:
case VKD3DSIH_EQO:
case VKD3DSIH_EQU:
case VKD3DSIH_GEO:
case VKD3DSIH_GEU:
case VKD3DSIH_IGE:
case VKD3DSIH_ILT:
case VKD3DSIH_INE:
case VKD3DSIH_LTO:
case VKD3DSIH_LTU:
case VKD3DSIH_NEO:
case VKD3DSIH_NEU:
case VKD3DSIH_UGE:
case VKD3DSIH_ULT:
Elizabeth Figura
committed
spirv_compiler_emit_comparison_instruction(compiler, instruction);
break;
case VKD3DSIH_IBFE:
case VKD3DSIH_UBFE:
Elizabeth Figura
committed
spirv_compiler_emit_bitfield_instruction(compiler, instruction);
case VKD3DSIH_F16TOF32:
Elizabeth Figura
committed
spirv_compiler_emit_f16tof32(compiler, instruction);
case VKD3DSIH_F32TOF16:
Elizabeth Figura
committed
spirv_compiler_emit_f32tof16(compiler, instruction);
Conor McCarthy
committed
spirv_compiler_emit_return(compiler, instruction);
case VKD3DSIH_RETP:
spirv_compiler_emit_retc(compiler, instruction);
break;
Conor McCarthy
committed
case VKD3DSIH_DISCARD:
case VKD3DSIH_TEXKILL:
spirv_compiler_emit_kill(compiler, instruction);
break;
Conor McCarthy
committed
case VKD3DSIH_LABEL:
spirv_compiler_emit_label(compiler, instruction);
break;
case VKD3DSIH_BRANCH:
spirv_compiler_emit_branch(compiler, instruction);
break;
Conor McCarthy
committed
case VKD3DSIH_SWITCH_MONOLITHIC:
spirv_compiler_emit_switch(compiler, instruction);
break;
case VKD3DSIH_DSX:
case VKD3DSIH_DSX_COARSE:
case VKD3DSIH_DSX_FINE:
case VKD3DSIH_DSY:
case VKD3DSIH_DSY_COARSE:
case VKD3DSIH_DSY_FINE:
Elizabeth Figura
committed
spirv_compiler_emit_deriv_instruction(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_ld(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_lod(compiler, instruction);
case VKD3DSIH_SAMPLE_GRAD:
Elizabeth Figura
committed
spirv_compiler_emit_sample(compiler, instruction);
case VKD3DSIH_SAMPLE_C:
Elizabeth Figura
committed
spirv_compiler_emit_sample_c(compiler, instruction);
case VKD3DSIH_GATHER4:
case VKD3DSIH_GATHER4_PO:
case VKD3DSIH_GATHER4_PO_C:
Elizabeth Figura
committed
spirv_compiler_emit_gather4(compiler, instruction);
case VKD3DSIH_LD_STRUCTURED:
Elizabeth Figura
committed
spirv_compiler_emit_ld_raw_structured(compiler, instruction);
case VKD3DSIH_STORE_RAW:
case VKD3DSIH_STORE_STRUCTURED:
Elizabeth Figura
committed
spirv_compiler_emit_store_raw_structured(compiler, instruction);
break;
case VKD3DSIH_LD_UAV_TYPED:
Elizabeth Figura
committed
spirv_compiler_emit_ld_uav_typed(compiler, instruction);
case VKD3DSIH_STORE_UAV_TYPED:
Elizabeth Figura
committed
spirv_compiler_emit_store_uav_typed(compiler, instruction);
case VKD3DSIH_IMM_ATOMIC_ALLOC:
case VKD3DSIH_IMM_ATOMIC_CONSUME:
Elizabeth Figura
committed
spirv_compiler_emit_uav_counter_instruction(compiler, instruction);
case VKD3DSIH_ATOMIC_AND:
case VKD3DSIH_ATOMIC_CMP_STORE:
case VKD3DSIH_ATOMIC_IADD:
case VKD3DSIH_ATOMIC_IMAX:
case VKD3DSIH_ATOMIC_IMIN:
case VKD3DSIH_ATOMIC_OR:
case VKD3DSIH_ATOMIC_UMAX:
case VKD3DSIH_ATOMIC_UMIN:
case VKD3DSIH_ATOMIC_XOR:
case VKD3DSIH_IMM_ATOMIC_AND:
case VKD3DSIH_IMM_ATOMIC_CMP_EXCH:
case VKD3DSIH_IMM_ATOMIC_EXCH:
case VKD3DSIH_IMM_ATOMIC_IADD:
case VKD3DSIH_IMM_ATOMIC_IMAX:
case VKD3DSIH_IMM_ATOMIC_IMIN:
case VKD3DSIH_IMM_ATOMIC_OR:
case VKD3DSIH_IMM_ATOMIC_UMAX:
case VKD3DSIH_IMM_ATOMIC_UMIN:
case VKD3DSIH_IMM_ATOMIC_XOR:
Elizabeth Figura
committed
spirv_compiler_emit_atomic_instruction(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_bufinfo(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_resinfo(compiler, instruction);
case VKD3DSIH_SAMPLE_INFO:
Elizabeth Figura
committed
spirv_compiler_emit_sample_info(compiler, instruction);
case VKD3DSIH_SAMPLE_POS:
Elizabeth Figura
committed
spirv_compiler_emit_sample_position(compiler, instruction);
case VKD3DSIH_EVAL_CENTROID:
case VKD3DSIH_EVAL_SAMPLE_INDEX:
Elizabeth Figura
committed
spirv_compiler_emit_eval_attrib(compiler, instruction);
Elizabeth Figura
committed
spirv_compiler_emit_sync(compiler, instruction);
case VKD3DSIH_EMIT:
case VKD3DSIH_EMIT_STREAM:
Elizabeth Figura
committed
spirv_compiler_emit_emit_stream(compiler, instruction);
case VKD3DSIH_CUT:
case VKD3DSIH_CUT_STREAM:
Elizabeth Figura
committed
spirv_compiler_emit_cut_stream(compiler, instruction);
case VKD3DSIH_DCL:
case VKD3DSIH_DCL_CONSTANT_BUFFER:
case VKD3DSIH_DCL_HS_MAX_TESSFACTOR:
Elizabeth Figura
committed
case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
case VKD3DSIH_DCL_INPUT_SGV:
case VKD3DSIH_DCL_INPUT_SIV:
case VKD3DSIH_DCL_INPUT_PS_SGV:
case VKD3DSIH_DCL_INPUT_PS_SIV:
case VKD3DSIH_DCL_OUTPUT_SIV:
case VKD3DSIH_DCL_RESOURCE_RAW:
case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
case VKD3DSIH_DCL_SAMPLER:
case VKD3DSIH_DCL_TEMPS:
case VKD3DSIH_DCL_UAV_RAW:
case VKD3DSIH_DCL_UAV_STRUCTURED:
case VKD3DSIH_DCL_UAV_TYPED:
case VKD3DSIH_HS_DECLS:
/* nothing to do */
default:
FIXME("Unhandled instruction %#x.\n", instruction->handler_idx);
spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER,
"Encountered invalid/unhandled instruction handler %#x.", instruction->handler_idx);
break;
Józef Kucia
committed
return ret;
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler)
{
for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i)
spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i);
for (unsigned int i = 0; i < compiler->output_signature.element_count; ++i)
{
/* PS outputs other than TARGET have dedicated registers and therefore
* go through spirv_compiler_emit_dcl_output() for now. */
if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL
&& compiler->output_signature.elements[i].sysval_semantic != VKD3D_SHADER_SV_TARGET)
continue;
spirv_compiler_emit_output(compiler, VKD3DSPR_OUTPUT, i);
}
for (unsigned int i = 0; i < compiler->patch_constant_signature.element_count; ++i)
{
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_output(compiler, VKD3DSPR_PATCHCONST, i);
else
spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i);
}
}
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler)
{
unsigned int i;
for (i = 0; i < compiler->scan_descriptor_info->descriptor_count; ++i)
{
const struct vkd3d_shader_descriptor_info1 *descriptor = &compiler->scan_descriptor_info->descriptors[i];
struct vkd3d_shader_register_range range;
range.first = descriptor->register_index;
if (descriptor->count == ~0u)
range.last = ~0u;
else
range.last = descriptor->register_index + descriptor->count - 1;
range.space = descriptor->register_space;
switch (descriptor->type)
{
case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
spirv_compiler_emit_sampler_declaration(compiler, &range, descriptor->register_id);
break;
case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV:
spirv_compiler_emit_cbv_declaration(compiler, &range, descriptor->register_id, descriptor->buffer_size);
break;
case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV:
spirv_compiler_emit_resource_declaration(compiler, &range, descriptor->register_id,
descriptor->sample_count, false, descriptor->resource_type, descriptor->resource_data_type,
descriptor->structure_stride / 4, descriptor->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_RAW_BUFFER);
break;
case VKD3D_SHADER_DESCRIPTOR_TYPE_UAV:
spirv_compiler_emit_resource_declaration(compiler, &range, descriptor->register_id,
descriptor->sample_count, true, descriptor->resource_type, descriptor->resource_data_type,
descriptor->structure_stride / 4, descriptor->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_RAW_BUFFER);
break;
default:
vkd3d_unreachable();
}
}
}
static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
Conor McCarthy
committed
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_parser *parser,
struct vkd3d_shader_code *spirv)
const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
Henri Verbeet
committed
const struct vkd3d_shader_spirv_domain_shader_target_info *ds_info;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
struct vkd3d_shader_desc *shader_desc = &parser->shader_desc;
Conor McCarthy
committed
struct vkd3d_shader_instruction_array instructions;
Conor McCarthy
committed
enum vkd3d_result result = VKD3D_OK;
unsigned int i;
if (parser->shader_desc.temp_count)
spirv_compiler_emit_temps(compiler, parser->shader_desc.temp_count);
if (parser->shader_desc.ssa_count)
spirv_compiler_allocate_ssa_register_ids(compiler, parser->shader_desc.ssa_count);
spirv_compiler_emit_descriptor_declarations(compiler);
Henri Verbeet
committed
compiler->location.column = 0;
Conor McCarthy
committed
compiler->location.line = 1;
Elizabeth Figura
committed
if ((result = vkd3d_shader_normalise(parser, compile_info)) < 0)
return result;
if (parser->shader_desc.block_count && !spirv_compiler_init_blocks(compiler, parser->shader_desc.block_count))
return VKD3D_ERROR_OUT_OF_MEMORY;
Conor McCarthy
committed
instructions = parser->instructions;
memset(&parser->instructions, 0, sizeof(parser->instructions));
Conor McCarthy
committed
compiler->input_signature = shader_desc->input_signature;
compiler->output_signature = shader_desc->output_signature;
compiler->patch_constant_signature = shader_desc->patch_constant_signature;
memset(&shader_desc->input_signature, 0, sizeof(shader_desc->input_signature));
memset(&shader_desc->output_signature, 0, sizeof(shader_desc->output_signature));
memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature));
compiler->use_vocp = parser->shader_desc.use_vocp;
Conor McCarthy
committed
Elizabeth Figura
committed
compiler->input_control_point_count = shader_desc->input_control_point_count;
compiler->output_control_point_count = shader_desc->output_control_point_count;
Conor McCarthy
committed
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_shader_signature_outputs(compiler);
Conor McCarthy
committed
spirv_compiler_emit_io_declarations(compiler);
Conor McCarthy
committed
for (i = 0; i < instructions.count && result >= 0; ++i)
Conor McCarthy
committed
{
Henri Verbeet
committed
compiler->location.line = i + 1;
Conor McCarthy
committed
result = spirv_compiler_handle_instruction(compiler, &instructions.elements[i]);
Conor McCarthy
committed
}
Conor McCarthy
committed
shader_instruction_array_destroy(&instructions);
Conor McCarthy
committed
if (result < 0)
return result;
if (!is_in_default_phase(compiler))
spirv_compiler_leave_shader_phase(compiler);
Józef Kucia
committed
else
vkd3d_spirv_build_op_function_end(builder);
Józef Kucia
committed
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL)
Elizabeth Figura
committed
spirv_compiler_emit_hull_shader_main(compiler);
if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN)
{
if (info && (ds_info = vkd3d_find_struct(compile_info->next, SPIRV_DOMAIN_SHADER_TARGET_INFO)))
Elizabeth Figura
committed
spirv_compiler_emit_tessellator_output_primitive(compiler, ds_info->output_primitive);
spirv_compiler_emit_tessellator_partitioning(compiler, ds_info->partitioning);
Elizabeth Figura
committed
else if (spirv_compiler_is_opengl_target(compiler))
Henri Verbeet
committed
ERR("vkd3d_shader_spirv_domain_shader_target_info is required for "
"OpenGL tessellation evaluation shader.\n");
}
}
if (compiler->epilogue_function_id)
{
vkd3d_spirv_build_op_name(builder, compiler->epilogue_function_id, "epilogue");
Elizabeth Figura
committed
spirv_compiler_emit_shader_epilogue_function(compiler);
Józef Kucia
committed
if (compiler->strip_debug)
vkd3d_spirv_stream_clear(&builder->debug_stream);
Elizabeth Figura
committed
if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler)))
return VKD3D_ERROR;
Giovanni Mascellani
committed
if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)
Elizabeth Figura
committed
enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler);
Giovanni Mascellani
committed
struct vkd3d_string_buffer buffer;
if (TRACE_ON())
vkd3d_spirv_dump(spirv, environment);
vkd3d_string_buffer_init(&buffer);
if (!vkd3d_spirv_validate(&buffer, spirv, environment))
{
FIXME("Failed to validate SPIR-V binary.\n");
vkd3d_shader_trace_text(buffer.buffer, buffer.content_size);
if (compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)
{
spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER,
"Execution generated an invalid shader, failing compilation:\n%s",
buffer.buffer);
}
}
vkd3d_string_buffer_cleanup(&buffer);
Henri Verbeet
committed
if (compiler->failed)
return VKD3D_ERROR_INVALID_SHADER;
if (compile_info->target_type == VKD3D_SHADER_TARGET_SPIRV_TEXT)
{
struct vkd3d_shader_code text;
Elizabeth Figura
committed
enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler);
Henri Verbeet
committed
if (vkd3d_spirv_binary_to_text(spirv, environment, compiler->formatting, &text) != VKD3D_OK)
return VKD3D_ERROR;
*spirv = text;
}
return VKD3D_OK;
int spirv_compile(struct vkd3d_shader_parser *parser,
const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
{
struct spirv_compiler *spirv_compiler;
int ret;
if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc,
Giovanni Mascellani
committed
compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags)))
{
ERR("Failed to create SPIR-V compiler.\n");
return VKD3D_ERROR;
}
ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, parser, out);
spirv_compiler_destroy(spirv_compiler);
return ret;
}