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
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
{-6.0 / 16.0, 2.0 / 16.0},
{ 2.0 / 16.0, 6.0 / 16.0},
/* 8 samples */
{ 1.0 / 16.0, -3.0 / 16.0},
{-1.0 / 16.0, 3.0 / 16.0},
{ 5.0 / 16.0, 1.0 / 16.0},
{-3.0 / 16.0, -5.0 / 16.0},
{-5.0 / 16.0, 5.0 / 16.0},
{-7.0 / 16.0, -1.0 / 16.0},
{ 3.0 / 16.0, 7.0 / 16.0},
{ 7.0 / 16.0, -7.0 / 16.0},
/* 16 samples */
{ 1.0 / 16.0, 1.0 / 16.0},
{-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->emit_point_size)
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;
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
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);
}
}
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
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;
compiler->block_names = parser->shader_desc.block_names;
compiler->block_name_count = parser->shader_desc.block_name_count;
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;
}