Newer
Older
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_CONSTANT_BUFFER:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_constant_buffer(compiler, instruction);
case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_immediate_constant_buffer(compiler, instruction);
case VKD3DSIH_DCL_SAMPLER:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_sampler(compiler, instruction);
case VKD3DSIH_DCL:
case VKD3DSIH_DCL_UAV_TYPED:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_resource(compiler, instruction);
case VKD3DSIH_DCL_RESOURCE_RAW:
case VKD3DSIH_DCL_UAV_RAW:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_resource_raw(compiler, instruction);
case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
case VKD3DSIH_DCL_UAV_STRUCTURED:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_resource_structured(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:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_input(compiler, instruction);
break;
case VKD3DSIH_DCL_INPUT_PS:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_input_ps(compiler, instruction);
case VKD3DSIH_DCL_INPUT_PS_SGV:
case VKD3DSIH_DCL_INPUT_PS_SIV:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_input_ps_sysval(compiler, instruction);
case VKD3DSIH_DCL_INPUT_SGV:
case VKD3DSIH_DCL_INPUT_SIV:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_input_sysval(compiler, instruction);
case VKD3DSIH_DCL_OUTPUT:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_output(compiler, instruction);
case VKD3DSIH_DCL_OUTPUT_SIV:
Elizabeth Figura
committed
spirv_compiler_emit_dcl_output_siv(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_INPUT_CONTROL_POINT_COUNT:
compiler->input_control_point_count = instruction->declaration.count;
break;
case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT:
compiler->output_control_point_count = instruction->declaration.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_FTOI:
case VKD3DSIH_FTOU:
case VKD3DSIH_ITOF:
case VKD3DSIH_NOT:
case VKD3DSIH_OR:
case VKD3DSIH_XOR:
Elizabeth Figura
committed
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);
Elizabeth Figura
committed
spirv_compiler_emit_udiv(compiler, instruction);
case VKD3DSIH_EQ:
case VKD3DSIH_GE:
case VKD3DSIH_IGE:
case VKD3DSIH_ILT:
case VKD3DSIH_INE:
case VKD3DSIH_LT:
case VKD3DSIH_NE:
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);
case VKD3DSIH_BREAK:
case VKD3DSIH_CASE:
case VKD3DSIH_DEFAULT:
case VKD3DSIH_DISCARD:
case VKD3DSIH_ELSE:
case VKD3DSIH_ENDIF:
case VKD3DSIH_ENDSWITCH:
case VKD3DSIH_IF:
case VKD3DSIH_LOOP:
case VKD3DSIH_SWITCH:
case VKD3DSIH_TEXKILL:
Elizabeth Figura
committed
ret = spirv_compiler_emit_control_flow_instruction(compiler, instruction);
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_HS_MAX_TESSFACTOR:
case VKD3DSIH_DCL_TEMPS:
case VKD3DSIH_HS_DECLS:
/* nothing to do */
default:
FIXME("Unhandled instruction %#x.\n", instruction->handler_idx);
}
Józef Kucia
committed
return ret;
static void spirv_compiler_emit_sm1_constant_buffer(struct spirv_compiler *compiler,
const struct vkd3d_shader_desc *desc, enum vkd3d_shader_d3dbc_constant_register set,
enum vkd3d_data_type data_type)
{
struct vkd3d_shader_register_range range = {.space = 0, .first = set, .last = set};
uint32_t count = desc->flat_constant_count[set].external;
struct vkd3d_shader_register reg =
{
.type = VKD3DSPR_CONSTBUFFER,
.idx[0].offset = set, /* register ID */
.idx[1].offset = set, /* register index */
.idx[2].offset = count, /* size */
.idx_count = 3,
.data_type = data_type,
};
if (count)
spirv_compiler_emit_constant_buffer(compiler, count, &range, ®);
}
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);
spirv_compiler_emit_sm1_constant_buffer(compiler, &parser->shader_desc,
VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, VKD3D_DATA_FLOAT);
spirv_compiler_emit_sm1_constant_buffer(compiler, &parser->shader_desc,
VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER, VKD3D_DATA_INT);
spirv_compiler_emit_sm1_constant_buffer(compiler, &parser->shader_desc,
VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER, VKD3D_DATA_UINT);
Henri Verbeet
committed
compiler->location.column = 0;
Conor McCarthy
committed
compiler->location.line = 1;
if ((result = vkd3d_shader_normalise(parser)) < 0)
return result;
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));
Conor McCarthy
committed
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_shader_signature_outputs(compiler);
Conor McCarthy
committed
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 (compiler->main_block_open)
vkd3d_spirv_build_op_return(builder);
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;
if (TRACE_ON())
{
Elizabeth Figura
committed
enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler);
Henri Verbeet
committed
vkd3d_spirv_dump(spirv, environment);
vkd3d_spirv_validate(spirv, environment);
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_info *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,
compile_info, scan_descriptor_info, message_context, &parser->location)))
{
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;
}