Newer
Older
Józef Kucia
committed
vkd3d_spirv_build_op_return(builder);
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
static void vkd3d_dxbc_compiler_emit_kill(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t condition_id, target_block_id, merge_block_id;
condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
VKD3D_SHADER_CONDITIONAL_OP_NZ, 1, condition_id);
merge_block_id = vkd3d_spirv_alloc_id(builder);
target_block_id = vkd3d_spirv_alloc_id(builder);
vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone);
vkd3d_spirv_build_op_branch_conditional(builder, condition_id, target_block_id, merge_block_id);
vkd3d_spirv_build_op_label(builder, target_block_id);
vkd3d_spirv_build_op_kill(builder);
vkd3d_spirv_build_op_label(builder, merge_block_id);
}
Józef Kucia
committed
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
static struct vkd3d_control_flow_info *vkd3d_dxbc_compiler_push_control_flow_level(
struct vkd3d_dxbc_compiler *compiler)
{
if (!vkd3d_array_reserve((void **)&compiler->control_flow_info, &compiler->control_flow_info_size,
compiler->control_flow_depth + 1, sizeof(*compiler->control_flow_info)))
{
ERR("Failed to allocate control flow info structure.\n");
return NULL;
}
return &compiler->control_flow_info[compiler->control_flow_depth++];
}
static void vkd3d_dxbc_compiler_pop_control_flow_level(struct vkd3d_dxbc_compiler *compiler)
{
struct vkd3d_control_flow_info *cf_info;
assert(compiler->control_flow_depth);
cf_info = &compiler->control_flow_info[--compiler->control_flow_depth];
memset(cf_info, 0, sizeof(*cf_info));
}
Józef Kucia
committed
static struct vkd3d_control_flow_info *vkd3d_dxbc_compiler_find_innermost_breakable_cf_construct(
Józef Kucia
committed
struct vkd3d_dxbc_compiler *compiler)
{
int depth;
for (depth = compiler->control_flow_depth - 1; depth >= 0; --depth)
{
Józef Kucia
committed
if (compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP
|| compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_SWITCH)
Józef Kucia
committed
return &compiler->control_flow_info[depth];
}
return NULL;
}
static void vkd3d_dxbc_compiler_emit_control_flow_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t merge_block_id, val_id, condition_id, true_label, false_label;
uint32_t loop_header_block_id, loop_body_block_id, continue_block_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_src_param *src = instruction->src;
struct vkd3d_control_flow_info *cf_info;
cf_info = compiler->control_flow_depth
? &compiler->control_flow_info[compiler->control_flow_depth - 1] : NULL;
switch (instruction->handler_idx)
{
case VKD3DSIH_IF:
Józef Kucia
committed
if (!(cf_info = vkd3d_dxbc_compiler_push_control_flow_level(compiler)))
val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler, instruction->flags, 1, val_id);
true_label = vkd3d_spirv_alloc_id(builder);
false_label = vkd3d_spirv_alloc_id(builder);
merge_block_id = vkd3d_spirv_alloc_id(builder);
vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone);
vkd3d_spirv_build_op_branch_conditional(builder, condition_id, true_label, false_label);
vkd3d_spirv_build_op_label(builder, true_label);
cf_info->u.branch.merge_block_id = merge_block_id;
cf_info->u.branch.else_block_id = false_label;
cf_info->current_block = VKD3D_BLOCK_IF;
vkd3d_spirv_build_op_name(builder, merge_block_id, "branch%u_merge", compiler->branch_id);
vkd3d_spirv_build_op_name(builder, true_label, "branch%u_true", compiler->branch_id);
vkd3d_spirv_build_op_name(builder, false_label, "branch%u_false", compiler->branch_id);
++compiler->branch_id;
break;
case VKD3DSIH_ELSE:
assert(compiler->control_flow_depth);
assert(cf_info->current_block != VKD3D_BLOCK_LOOP);
if (cf_info->current_block == VKD3D_BLOCK_IF)
vkd3d_spirv_build_op_branch(builder, cf_info->u.branch.merge_block_id);
if (cf_info->current_block != VKD3D_BLOCK_ELSE)
vkd3d_spirv_build_op_label(builder, cf_info->u.branch.else_block_id);
cf_info->current_block = VKD3D_BLOCK_ELSE;
break;
case VKD3DSIH_ENDIF:
assert(compiler->control_flow_depth);
assert(cf_info->current_block != VKD3D_BLOCK_MAIN);
assert(cf_info->current_block != VKD3D_BLOCK_LOOP);
if (cf_info->current_block == VKD3D_BLOCK_IF)
{
vkd3d_spirv_build_op_branch(builder, cf_info->u.branch.merge_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->u.branch.else_block_id);
vkd3d_spirv_build_op_branch(builder, cf_info->u.branch.merge_block_id);
}
else if (cf_info->current_block == VKD3D_BLOCK_ELSE)
{
vkd3d_spirv_build_op_branch(builder, cf_info->u.branch.merge_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->u.branch.merge_block_id);
Józef Kucia
committed
vkd3d_dxbc_compiler_pop_control_flow_level(compiler);
Józef Kucia
committed
if (!(cf_info = vkd3d_dxbc_compiler_push_control_flow_level(compiler)))
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
return;
loop_header_block_id = vkd3d_spirv_alloc_id(builder);
loop_body_block_id = vkd3d_spirv_alloc_id(builder);
continue_block_id = vkd3d_spirv_alloc_id(builder);
merge_block_id = vkd3d_spirv_alloc_id(builder);
vkd3d_spirv_build_op_branch(builder, loop_header_block_id);
vkd3d_spirv_build_op_label(builder, loop_header_block_id);
vkd3d_spirv_build_op_loop_merge(builder, merge_block_id, continue_block_id, SpvLoopControlMaskNone);
vkd3d_spirv_build_op_branch(builder, loop_body_block_id);
vkd3d_spirv_build_op_label(builder, loop_body_block_id);
cf_info->u.loop.header_block_id = loop_header_block_id;
cf_info->u.loop.continue_block_id = continue_block_id;
cf_info->u.loop.merge_block_id = merge_block_id;
cf_info->current_block = VKD3D_BLOCK_LOOP;
vkd3d_spirv_build_op_name(builder, loop_header_block_id, "loop%u_header", compiler->loop_id);
vkd3d_spirv_build_op_name(builder, loop_body_block_id, "loop%u_body", compiler->loop_id);
vkd3d_spirv_build_op_name(builder, continue_block_id, "loop%u_continue", compiler->loop_id);
vkd3d_spirv_build_op_name(builder, merge_block_id, "loop%u_merge", compiler->loop_id);
++compiler->loop_id;
break;
case VKD3DSIH_ENDLOOP:
assert(compiler->control_flow_depth);
assert(cf_info->current_block == VKD3D_BLOCK_LOOP);
vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.continue_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->u.loop.continue_block_id);
vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.header_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->u.loop.merge_block_id);
Józef Kucia
committed
vkd3d_dxbc_compiler_pop_control_flow_level(compiler);
case VKD3DSIH_SWITCH:
if (!(cf_info = vkd3d_dxbc_compiler_push_control_flow_level(compiler)))
return;
merge_block_id = vkd3d_spirv_alloc_id(builder);
assert(src->reg.data_type == VKD3D_DATA_INT);
val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone);
cf_info->u.switch_.id = compiler->switch_id;
cf_info->u.switch_.merge_block_id = merge_block_id;
cf_info->u.switch_.stream_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
cf_info->u.switch_.selector_id = val_id;
cf_info->u.switch_.case_blocks = NULL;
cf_info->u.switch_.case_blocks_size = 0;
cf_info->u.switch_.case_block_count = 0;
vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size,
10, sizeof(*cf_info->u.switch_.case_blocks));
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
cf_info->u.switch_.default_block_id = 0;
cf_info->u.switch_.inside_block = false;
cf_info->current_block = VKD3D_BLOCK_SWITCH;
vkd3d_spirv_build_op_name(builder, merge_block_id, "switch%u_merge", compiler->switch_id);
++compiler->switch_id;
break;
case VKD3DSIH_ENDSWITCH:
assert(compiler->control_flow_depth);
assert(cf_info->current_block == VKD3D_BLOCK_SWITCH);
vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.merge_block_id);
/* The OpSwitch instruction is inserted when the endswitch
* instruction is processed because we do not know the number
* of case statments in advance.*/
vkd3d_spirv_begin_function_stream_insertion(builder, cf_info->u.switch_.stream_location);
vkd3d_spirv_build_op_switch(builder, cf_info->u.switch_.selector_id,
cf_info->u.switch_.default_block_id, cf_info->u.switch_.case_blocks,
cf_info->u.switch_.case_block_count);
vkd3d_spirv_end_function_stream_insertion(builder);
vkd3d_free(cf_info->u.switch_.case_blocks);
vkd3d_dxbc_compiler_pop_control_flow_level(compiler);
break;
case VKD3DSIH_CASE:
{
uint32_t label_id, value;
assert(compiler->control_flow_depth);
assert(cf_info->current_block == VKD3D_BLOCK_SWITCH);
assert(src->swizzle == VKD3DSP_NOSWIZZLE && src->reg.type == VKD3DSPR_IMMCONST);
value = *src->reg.u.immconst_data;
if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size,
2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks)))
return;
label_id = vkd3d_spirv_alloc_id(builder);
if (cf_info->u.switch_.inside_block) /* fall-through */
vkd3d_spirv_build_op_branch(builder, label_id);
cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 0] = value;
cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 1] = label_id;
++cf_info->u.switch_.case_block_count;
vkd3d_spirv_build_op_label(builder, label_id);
cf_info->u.switch_.inside_block = true;
vkd3d_spirv_build_op_name(builder, label_id, "switch%u_case%u", cf_info->u.switch_.id, value);
break;
}
case VKD3DSIH_DEFAULT:
assert(compiler->control_flow_depth);
assert(cf_info->current_block == VKD3D_BLOCK_SWITCH);
cf_info->u.switch_.default_block_id = vkd3d_spirv_alloc_id(builder);
if (cf_info->u.switch_.inside_block) /* fall-through */
vkd3d_spirv_build_op_branch(builder, cf_info->u.switch_.default_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.default_block_id);
cf_info->u.switch_.inside_block = true;
vkd3d_spirv_build_op_name(builder, cf_info->u.switch_.default_block_id,
"switch%u_default", cf_info->u.switch_.id);
break;
case VKD3DSIH_BREAK:
{
Józef Kucia
committed
struct vkd3d_control_flow_info *breakable_cf_info;
Józef Kucia
committed
if (!(breakable_cf_info = vkd3d_dxbc_compiler_find_innermost_breakable_cf_construct(compiler)))
{
FIXME("Unhandled break instruction.\n");
return;
}
Józef Kucia
committed
assert(compiler->control_flow_depth);
Józef Kucia
committed
if (breakable_cf_info->current_block == VKD3D_BLOCK_LOOP)
{
vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.loop.merge_block_id);
}
else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH)
{
if (breakable_cf_info->u.switch_.inside_block)
{
vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.switch_.merge_block_id);
if (breakable_cf_info == cf_info)
breakable_cf_info->u.switch_.inside_block = false;
}
}
if (cf_info->current_block == VKD3D_BLOCK_IF)
{
vkd3d_spirv_build_op_label(builder, cf_info->u.branch.else_block_id);
cf_info->current_block = VKD3D_BLOCK_ELSE;
}
Józef Kucia
committed
else if (cf_info->current_block != VKD3D_BLOCK_SWITCH)
{
cf_info->current_block = VKD3D_BLOCK_NONE;
}
break;
}
case VKD3DSIH_BREAKP:
assert(compiler->control_flow_depth);
assert(cf_info->current_block == VKD3D_BLOCK_LOOP);
vkd3d_dxbc_compiler_emit_breakc(compiler, instruction, cf_info->u.loop.merge_block_id);
break;
case VKD3DSIH_RET:
vkd3d_dxbc_compiler_emit_return(compiler, instruction);
if (cf_info && cf_info->current_block == VKD3D_BLOCK_IF)
vkd3d_spirv_build_op_label(builder, cf_info->u.branch.else_block_id);
cf_info->current_block = VKD3D_BLOCK_ELSE;
}
else if (cf_info && cf_info->current_block == VKD3D_BLOCK_SWITCH)
{
cf_info->u.switch_.inside_block = false;
}
else if (cf_info)
{
cf_info->current_block = VKD3D_BLOCK_NONE;
}
break;
case VKD3DSIH_TEXKILL:
vkd3d_dxbc_compiler_emit_kill(compiler, instruction);
break;
default:
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
break;
}
}
Józef Kucia
committed
struct vkd3d_shader_image
{
Józef Kucia
committed
uint32_t image_id;
uint32_t sampler_id;
uint32_t sampled_image_id;
enum vkd3d_component_type sampled_type;
uint32_t image_type_id;
const struct vkd3d_spirv_resource_type *resource_type_info;
unsigned int structure_stride;
bool raw;
Józef Kucia
committed
};
#define VKD3D_IMAGE_FLAG_NONE 0x0
#define VKD3D_IMAGE_FLAG_DEPTH 0x1
#define VKD3D_IMAGE_FLAG_NO_LOAD 0x2
static const struct vkd3d_symbol *vkd3d_dxbc_compiler_find_resource(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_register *resource_reg)
{
struct vkd3d_symbol resource_key;
struct rb_entry *entry;
vkd3d_symbol_make_resource(&resource_key, resource_reg);
entry = rb_get(&compiler->symbol_table, &resource_key);
assert(entry);
return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
}
Józef Kucia
committed
static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_shader_image *image, const struct vkd3d_shader_register *resource_reg,
unsigned int flags)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_symbol *resource_symbol;
bool load, depth_comparison;
load = !(flags & VKD3D_IMAGE_FLAG_NO_LOAD);
depth_comparison = flags & VKD3D_IMAGE_FLAG_DEPTH;
resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, resource_reg);
Józef Kucia
committed
image->sampled_type = resource_symbol->info.resource.sampled_type;
image->image_type_id = resource_symbol->info.resource.type_id;
image->resource_type_info = resource_symbol->info.resource.resource_type_info;
image->structure_stride = resource_symbol->info.resource.structure_stride;
image->raw = resource_symbol->info.resource.raw;
image->id = resource_symbol->id;
image->image_id = load ? vkd3d_spirv_build_op_load(builder,
image->image_type_id, image->id, SpvMemoryAccessMaskNone) : 0;
image->image_type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler,
resource_reg, image->resource_type_info, image->sampled_type,
image->structure_stride || image->raw, depth_comparison);
Józef Kucia
committed
image->sampler_id = 0;
image->sampled_image_id = 0;
Józef Kucia
committed
static void vkd3d_dxbc_compiler_prepare_sampled_image_for_sampler(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_shader_image *image, const struct vkd3d_shader_register *resource_reg,
uint32_t sampler_var_id, unsigned int flags)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
uint32_t sampled_image_type_id;
vkd3d_dxbc_compiler_prepare_image(compiler, image, resource_reg, flags);
Józef Kucia
committed
image->sampler_id = vkd3d_spirv_build_op_load(builder,
Józef Kucia
committed
vkd3d_spirv_get_op_type_sampler(builder), sampler_var_id, SpvMemoryAccessMaskNone);
Józef Kucia
committed
sampled_image_type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image->image_type_id);
image->sampled_image_id = vkd3d_spirv_build_op_sampled_image(builder,
sampled_image_type_id, image->image_id, image->sampler_id);
Józef Kucia
committed
static void vkd3d_dxbc_compiler_prepare_default_sampled_image(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_shader_image *image, const struct vkd3d_shader_register *resource_reg)
Józef Kucia
committed
vkd3d_dxbc_compiler_prepare_sampled_image_for_sampler(compiler, image, resource_reg,
vkd3d_dxbc_compiler_get_default_sampler_id(compiler), false);
Józef Kucia
committed
}
Józef Kucia
committed
static void vkd3d_dxbc_compiler_prepare_sampled_image(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_shader_image *image, const struct vkd3d_shader_register *resource_reg,
const struct vkd3d_shader_register *sampler_reg, bool depth_comparison)
Józef Kucia
committed
{
vkd3d_dxbc_compiler_prepare_sampled_image_for_sampler(compiler, image, resource_reg,
vkd3d_dxbc_compiler_get_register_id(compiler, sampler_reg), depth_comparison);
}
static void vkd3d_dxbc_compiler_emit_ld(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t image_id, type_id, coordinate_id, val_id;
SpvImageOperandsMask operands_mask = 0;
unsigned int image_operand_count = 0;
Józef Kucia
committed
struct vkd3d_shader_image image;
uint32_t image_operands[2];
DWORD coordinate_mask;
if (vkd3d_shader_instruction_has_texel_offset(instruction))
FIXME("Texel offset not supported.\n");
/* OpImageFetch must be used with a sampled image. */
Józef Kucia
committed
vkd3d_dxbc_compiler_prepare_default_sampled_image(compiler, &image, &src[1].reg);
image_id = vkd3d_spirv_build_op_image(builder, image.image_type_id, image.sampled_image_id);
Józef Kucia
committed
type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
Józef Kucia
committed
if (image.resource_type_info->resource_type != VKD3D_SHADER_RESOURCE_BUFFER)
{
operands_mask |= SpvImageOperandsLodMask;
image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
&src[0], VKD3DSP_WRITEMASK_3);
}
val_id = vkd3d_spirv_build_op_image_fetch(builder, type_id,
image_id, coordinate_id, operands_mask, image_operands, image_operand_count);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
dst, val_id, image.sampled_type, src[1].swizzle);
static void vkd3d_dxbc_compiler_emit_sample(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
Józef Kucia
committed
uint32_t sampled_type_id, coordinate_id, val_id;
SpvImageOperandsMask operands_mask = 0;
unsigned int image_operand_count = 0;
Józef Kucia
committed
struct vkd3d_shader_image image;
uint32_t image_operands[1];
SpvOp op;
switch (instruction->handler_idx)
{
case VKD3DSIH_SAMPLE:
op = SpvOpImageSampleImplicitLod;
break;
case VKD3DSIH_SAMPLE_LOD:
op = SpvOpImageSampleExplicitLod;
operands_mask |= SpvImageOperandsLodMask;
image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
&src[3], VKD3DSP_WRITEMASK_0);
break;
default:
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
return;
}
if (vkd3d_shader_instruction_has_texel_offset(instruction))
FIXME("Texel offset not supported.\n");
vkd3d_dxbc_compiler_prepare_sampled_image(compiler, &image,
&src[1].reg, &src[2].reg, VKD3D_IMAGE_FLAG_NONE);
Józef Kucia
committed
sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL);
val_id = vkd3d_spirv_build_op_image_sample(builder, op, sampled_type_id,
image.sampled_image_id, coordinate_id, operands_mask, image_operands, image_operand_count);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
dst, val_id, image.sampled_type, src[1].swizzle);
static void vkd3d_dxbc_compiler_emit_sample_c(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t sampled_type_id, coordinate_id, ref_id, val_id, type_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
SpvImageOperandsMask operands_mask = 0;
unsigned int image_operand_count = 0;
struct vkd3d_shader_image image;
uint32_t image_operands[1];
SpvOp op;
if (vkd3d_shader_instruction_has_texel_offset(instruction))
FIXME("Texel offset not supported.\n");
if (instruction->handler_idx == VKD3DSIH_SAMPLE_C_LZ)
{
op = SpvOpImageSampleDrefExplicitLod;
operands_mask |= SpvImageOperandsLodMask;
image_operands[image_operand_count++]
= vkd3d_dxbc_compiler_get_constant_float(compiler, 0.0f);
}
else
{
op = SpvOpImageSampleDrefImplicitLod;
}
vkd3d_dxbc_compiler_prepare_sampled_image(compiler,
&image, &src[1].reg, &src[2].reg, VKD3D_IMAGE_FLAG_DEPTH);
sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL);
ref_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[3], VKD3DSP_WRITEMASK_0);
/* XXX: Nvidia is broken and expects that the D_ref is packed together with coordinates. */
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
coordinate_id = vkd3d_spirv_build_op_composite_insert(builder,
type_id, ref_id, coordinate_id, &image.resource_type_info->coordinate_component_count, 1);
val_id = vkd3d_spirv_build_op_image_sample_dref(builder, op, sampled_type_id,
image.sampled_image_id, coordinate_id, ref_id, operands_mask,
image_operands, image_operand_count);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
dst, val_id, image.sampled_type, src[1].swizzle);
static uint32_t vkd3d_dxbc_compiler_emit_texel_offset(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction,
const struct vkd3d_spirv_resource_type *resource_type_info)
{
const struct vkd3d_shader_texel_offset *offset = &instruction->texel_offset;
unsigned int component_count = resource_type_info->offset_component_count;
int32_t data[4] = {offset->u, offset->v, offset->w, 0};
return vkd3d_dxbc_compiler_get_constant(compiler,
VKD3D_TYPE_INT, component_count, (const uint32_t *)data);
}
static void vkd3d_dxbc_compiler_emit_gather4(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t sampled_type_id, coordinate_id, component_id, val_id;
Józef Kucia
committed
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
const struct vkd3d_shader_src_param *resource, *sampler;
SpvImageOperandsMask operands_mask = 0;
unsigned int image_operand_count = 0;
struct vkd3d_shader_image image;
unsigned int component_idx;
uint32_t image_operands[1];
DWORD coordinate_mask;
resource = &src[1];
sampler = &src[2];
component_idx = vkd3d_swizzle_get_component(sampler->swizzle, 0);
/* Nvidia driver requires signed integer type. */
component_id = vkd3d_dxbc_compiler_get_constant(compiler, VKD3D_TYPE_INT, 1, &component_idx);
vkd3d_dxbc_compiler_prepare_sampled_image(compiler, &image,
&resource->reg, &sampler->reg, VKD3D_IMAGE_FLAG_NONE);
if (vkd3d_shader_instruction_has_texel_offset(instruction))
{
operands_mask |= SpvImageOperandsConstOffsetMask;
image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_texel_offset(compiler,
instruction, image.resource_type_info);
}
sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
val_id = vkd3d_spirv_build_op_image_gather(builder, sampled_type_id,
image.sampled_image_id, coordinate_id, component_id,
operands_mask, image_operands, image_operand_count);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
dst, val_id, image.sampled_type, resource->swizzle);
static uint32_t vkd3d_dxbc_compiler_emit_raw_structured_addressing(
struct vkd3d_dxbc_compiler *compiler, uint32_t type_id, unsigned int stride,
const struct vkd3d_shader_src_param *src0, DWORD src0_mask,
const struct vkd3d_shader_src_param *src1, DWORD src1_mask)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_src_param *offset;
uint32_t structure_id = 0, offset_id;
DWORD offset_write_mask;
if (stride)
structure_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src0, src0_mask);
structure_id = vkd3d_spirv_build_op_imul(builder, type_id,
structure_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, stride));
}
offset = stride ? src1 : src0;
offset_write_mask = stride ? src1_mask : src0_mask;
offset_id = vkd3d_dxbc_compiler_emit_load_src(compiler, offset, offset_write_mask);
offset_id = vkd3d_spirv_build_op_shift_right_logical(builder, type_id,
offset_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 2));
if (structure_id)
return vkd3d_spirv_build_op_iadd(builder, type_id, structure_id, offset_id);
else
return offset_id;
}
static void vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t coordinate_id, type_id, val_id, image_id, texel_type_id;
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_src_param *resource;
uint32_t base_coordinate_id, component_idx;
uint32_t constituents[VKD3D_VEC4_SIZE];
struct vkd3d_shader_image image;
resource = &src[instruction->src_count - 1];
if (resource->reg.type == VKD3DSPR_RESOURCE)
{
/* OpImageFetch must be used with a sampled image. */
op = SpvOpImageFetch;
vkd3d_dxbc_compiler_prepare_default_sampled_image(compiler, &image, &resource->reg);
image_id = vkd3d_spirv_build_op_image(builder, image.image_type_id, image.sampled_image_id);
}
else
{
op = SpvOpImageRead;
vkd3d_dxbc_compiler_prepare_image(compiler, &image, &resource->reg, VKD3D_IMAGE_FLAG_NONE);
image_id = image.image_id;
}
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
texel_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
coordinate_id = base_coordinate_id;
if (component_idx)
coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
op, texel_type_id, image_id, coordinate_id);
constituents[j++] = vkd3d_spirv_build_op_composite_extract1(builder,
type_id, val_id, 0);
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
assert(dst->reg.data_type == VKD3D_DATA_UINT);
vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, VKD3D_TYPE_UINT, constituents);
}
static void vkd3d_dxbc_compiler_emit_ld_tgsm(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 coordinate_id, type_id, ptr_type_id, ptr_id;
const struct vkd3d_shader_src_param *resource;
struct vkd3d_shader_register_info reg_info;
uint32_t base_coordinate_id, component_idx;
uint32_t constituents[VKD3D_VEC4_SIZE];
unsigned int i, j;
resource = &src[instruction->src_count - 1];
vkd3d_dxbc_compiler_get_register_info(compiler, &resource->reg, ®_info);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id);
base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
coordinate_id = base_coordinate_id;
if (component_idx)
coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id,
reg_info.id, &coordinate_id, 1);
constituents[j++] = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone);
}
assert(dst->reg.data_type == VKD3D_DATA_UINT);
vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, VKD3D_TYPE_UINT, constituents);
static void vkd3d_dxbc_compiler_emit_ld_raw_structured(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
enum vkd3d_shader_register_type reg_type = instruction->src[instruction->src_count - 1].reg.type;
switch (reg_type)
{
case VKD3DSPR_RESOURCE:
case VKD3DSPR_UAV:
vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(compiler, instruction);
break;
case VKD3DSPR_GROUPSHAREDMEM:
vkd3d_dxbc_compiler_emit_ld_tgsm(compiler, instruction);
break;
default:
ERR("Unexpected register type %#x.\n", reg_type);
static void vkd3d_dxbc_compiler_emit_store_uav(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t base_coordinate_id, component_idx, components[VKD3D_VEC4_SIZE];
Józef Kucia
committed
uint32_t coordinate_id, type_id, val_id, texel_type_id, texel_id;
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_src_param *texel;
Józef Kucia
committed
struct vkd3d_shader_image image;
unsigned int i, component_count;
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, VKD3D_IMAGE_FLAG_NONE);
assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !image.structure_stride);
base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
/* Mesa Vulkan drivers require the texel parameter to be a 4-component
* vector. */
texel = &src[instruction->src_count - 1];
assert(texel->reg.data_type == VKD3D_DATA_UINT);
val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, texel, dst->write_mask);
texel_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, VKD3D_VEC4_SIZE);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
for (component_idx = 0; component_idx < component_count; ++component_idx)
{
for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
components[i] = component_idx;
texel_id = vkd3d_spirv_build_op_vector_shuffle(builder,
texel_type_id, val_id, val_id, components, VKD3D_VEC4_SIZE);
coordinate_id = base_coordinate_id;
if (component_idx)
coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
Józef Kucia
committed
vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id,
texel_id, SpvImageOperandsMaskNone, NULL, 0);
}
}
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
static void vkd3d_dxbc_compiler_emit_store_tgsm(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t coordinate_id, type_id, val_id, ptr_type_id, ptr_id, data_id;
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 base_coordinate_id, component_idx;
const struct vkd3d_shader_src_param *data;
struct vkd3d_shader_register_info reg_info;
unsigned int component_count;
vkd3d_dxbc_compiler_get_register_info(compiler, &dst->reg, ®_info);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id);
assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !reg_info.structure_stride);
base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
data = &src[instruction->src_count - 1];
assert(data->reg.data_type == VKD3D_DATA_UINT);
val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, data, dst->write_mask);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
for (component_idx = 0; component_idx < component_count; ++component_idx)
{
data_id = component_count > 1 ?
vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx) : val_id;
coordinate_id = base_coordinate_id;
if (component_idx)
coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id,
reg_info.id, &coordinate_id, 1);
vkd3d_spirv_build_op_store(builder, ptr_id, data_id, SpvMemoryAccessMaskNone);
}
}
static void vkd3d_dxbc_compiler_emit_store_raw_structured(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
enum vkd3d_shader_register_type reg_type = instruction->dst[0].reg.type;
switch (reg_type)
{
case VKD3DSPR_UAV:
vkd3d_dxbc_compiler_emit_store_uav(compiler, instruction);
break;
case VKD3DSPR_GROUPSHAREDMEM:
vkd3d_dxbc_compiler_emit_store_tgsm(compiler, instruction);
break;
default:
ERR("Unexpected register type %#x.\n", reg_type);
}
}
static void vkd3d_dxbc_compiler_emit_ld_uav_typed(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
Józef Kucia
committed
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t coordinate_id, type_id, val_id;
struct vkd3d_shader_image image;
DWORD coordinate_mask;
vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src[1].reg, VKD3D_IMAGE_FLAG_NONE);
type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
val_id = vkd3d_spirv_build_op_image_read(builder, type_id,
image.image_id, coordinate_id, SpvImageOperandsMaskNone, NULL, 0);
Józef Kucia
committed
vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
dst, val_id, image.sampled_type, src[1].swizzle);
static void vkd3d_dxbc_compiler_emit_store_uav_typed(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;
struct vkd3d_shader_src_param texel_param = src[1];
Józef Kucia
committed
uint32_t coordinate_id, texel_id;
struct vkd3d_shader_image image;
DWORD coordinate_mask;
vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageWriteWithoutFormat);
vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, VKD3D_IMAGE_FLAG_NONE);
Józef Kucia
committed
coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
/* XXX: Fix the data type. */
Józef Kucia
committed
texel_param.reg.data_type = vkd3d_data_type_from_component_type(image.sampled_type);
texel_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &texel_param, dst->write_mask);
Józef Kucia
committed
vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id, texel_id,
SpvImageOperandsMaskNone, NULL, 0);
}
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
static void vkd3d_dxbc_compiler_emit_uav_counter_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 ptr_type_id, type_id, image_id, result_id;
uint32_t coordinate_id, sample_id, pointer_id;
const struct vkd3d_symbol *resource_symbol;
uint32_t operands[3];
SpvOp op;
op = instruction->handler_idx == VKD3DSIH_IMM_ATOMIC_ALLOC
? SpvOpAtomicIIncrement : SpvOpAtomicIDecrement;
resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &src->reg);
image_id = resource_symbol->info.resource.uav_counter_id;
assert(image_id);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id);
coordinate_id = sample_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder,
ptr_type_id, image_id, coordinate_id, sample_id);
operands[0] = pointer_id;
operands[1] = vkd3d_dxbc_compiler_get_constant_uint(compiler, SpvScopeDevice);
operands[2] = vkd3d_dxbc_compiler_get_constant_uint(compiler, SpvMemorySemanticsMaskNone);
result_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream,
op, type_id, operands, ARRAY_SIZE(operands));
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, result_id);
}
static SpvOp vkd3d_dxbc_compiler_map_atomic_instruction(const struct vkd3d_shader_instruction *instruction)
{
static const struct
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
SpvOp spirv_op;
}
atomic_ops[] =
{
{VKD3DSIH_ATOMIC_AND, SpvOpAtomicAnd},
{VKD3DSIH_ATOMIC_CMP_STORE, SpvOpAtomicCompareExchange},
{VKD3DSIH_ATOMIC_IADD, SpvOpAtomicIAdd},
{VKD3DSIH_ATOMIC_IMAX, SpvOpAtomicSMax},
{VKD3DSIH_ATOMIC_IMIN, SpvOpAtomicSMin},
{VKD3DSIH_ATOMIC_OR, SpvOpAtomicOr},
{VKD3DSIH_ATOMIC_UMAX, SpvOpAtomicUMax},
{VKD3DSIH_ATOMIC_UMIN, SpvOpAtomicUMin},
{VKD3DSIH_ATOMIC_XOR, SpvOpAtomicXor},
{VKD3DSIH_IMM_ATOMIC_AND, SpvOpAtomicAnd},
{VKD3DSIH_IMM_ATOMIC_CMP_EXCH, SpvOpAtomicCompareExchange},
{VKD3DSIH_IMM_ATOMIC_EXCH, SpvOpAtomicExchange},
{VKD3DSIH_IMM_ATOMIC_IADD, SpvOpAtomicIAdd},
{VKD3DSIH_IMM_ATOMIC_IMAX, SpvOpAtomicSMax},
{VKD3DSIH_IMM_ATOMIC_IMIN, SpvOpAtomicSMin},
{VKD3DSIH_IMM_ATOMIC_OR, SpvOpAtomicOr},
{VKD3DSIH_IMM_ATOMIC_UMAX, SpvOpAtomicUMax},
{VKD3DSIH_IMM_ATOMIC_UMIN, SpvOpAtomicUMin},
{VKD3DSIH_IMM_ATOMIC_XOR, SpvOpAtomicXor},
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(atomic_ops); ++i)
{
if (atomic_ops[i].handler_idx == instruction->handler_idx)
return atomic_ops[i].spirv_op;
}
return SpvOpMax;
}
static bool is_imm_atomic_instruction(enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx)
{
return VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR;
}
static void vkd3d_dxbc_compiler_emit_atomic_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 ptr_type_id, type_id, val_id, result_id;
const struct vkd3d_shader_dst_param *resource;
uint32_t coordinate_id, sample_id, pointer_id;
struct vkd3d_shader_register_info reg_info;
struct vkd3d_shader_image image;
unsigned int structure_stride;
DWORD coordinate_mask;
uint32_t operands[6];
unsigned int i = 0;
SpvScope scope;
bool raw;
resource = is_imm_atomic_instruction(instruction->handler_idx) ? &dst[1] : &dst[0];
op = vkd3d_dxbc_compiler_map_atomic_instruction(instruction);
if (op == SpvOpMax)
{
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);