Newer
Older
static void vkd3d_dxbc_compiler_emit_dcl_input_ps_siv(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t input_id;
input_id = vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg,
instruction->declaration.register_semantic.sysval_semantic);
if (!instruction->declaration.register_semantic.sysval_semantic)
vkd3d_dxbc_compiler_emit_interpolation_decorations(compiler, input_id, instruction->flags);
static void vkd3d_dxbc_compiler_emit_dcl_input_sgv(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg,
instruction->declaration.register_semantic.sysval_semantic);
}
static void vkd3d_dxbc_compiler_emit_dcl_output(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
vkd3d_dxbc_compiler_emit_output(compiler, &instruction->declaration.dst, VKD3D_SIV_NONE);
}
static void vkd3d_dxbc_compiler_emit_dcl_output_siv(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
vkd3d_dxbc_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg,
instruction->declaration.register_semantic.sysval_semantic);
}
static void vkd3d_dxbc_compiler_emit_dcl_thread_group(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
const struct vkd3d_shader_thread_group_size *group_size = &instruction->declaration.thread_group_size;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
vkd3d_spirv_set_local_size(builder, group_size->x, group_size->y, group_size->z);
}
static SpvOp vkd3d_dxbc_compiler_map_alu_instruction(const struct vkd3d_shader_instruction *instruction)
{
static const struct
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
SpvOp spirv_op;
}
alu_ops[] =
{
{VKD3DSIH_ADD, SpvOpFAdd},
{VKD3DSIH_AND, SpvOpBitwiseAnd},
{VKD3DSIH_BFREV, SpvOpBitReverse},
{VKD3DSIH_COUNTBITS, SpvOpBitCount},
{VKD3DSIH_DIV, SpvOpFDiv},
{VKD3DSIH_FTOI, SpvOpConvertFToS},
{VKD3DSIH_FTOU, SpvOpConvertFToU},
{VKD3DSIH_IADD, SpvOpIAdd},
{VKD3DSIH_ISHL, SpvOpShiftLeftLogical},
{VKD3DSIH_ISHR, SpvOpShiftRightArithmetic},
{VKD3DSIH_ITOF, SpvOpConvertSToF},
{VKD3DSIH_MUL, SpvOpFMul},
{VKD3DSIH_NOT, SpvOpNot},
{VKD3DSIH_OR, SpvOpBitwiseOr},
{VKD3DSIH_USHR, SpvOpShiftRightLogical},
{VKD3DSIH_UTOF, SpvOpConvertUToF},
{VKD3DSIH_XOR, SpvOpBitwiseXor},
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(alu_ops); ++i)
{
if (alu_ops[i].handler_idx == instruction->handler_idx)
return alu_ops[i].spirv_op;
}
return SpvOpMax;
}
static void vkd3d_dxbc_compiler_emit_alu_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t src_ids[VKD3D_DXBC_MAX_SOURCE_COUNT];
unsigned int component_count;
uint32_t type_id, val_id;
unsigned int i;
SpvOp op;
op = vkd3d_dxbc_compiler_map_alu_instruction(instruction);
if (op == SpvOpMax)
{
Józef Kucia
committed
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
return;
}
assert(instruction->dst_count == 1);
assert(instruction->src_count <= VKD3D_DXBC_MAX_SOURCE_COUNT);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst->reg.data_type), component_count);
for (i = 0; i < instruction->src_count; ++i)
src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
val_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, op, type_id,
src_ids, instruction->src_count);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
static enum GLSLstd450 vkd3d_dxbc_compiler_map_ext_glsl_instruction(
const struct vkd3d_shader_instruction *instruction)
{
static const struct
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
enum GLSLstd450 glsl_inst;
}
glsl_insts[] =
{
{VKD3DSIH_FIRSTBIT_HI, GLSLstd450FindUMsb},
{VKD3DSIH_FIRSTBIT_LO, GLSLstd450FindILsb},
{VKD3DSIH_FIRSTBIT_SHI, GLSLstd450FindSMsb},
{VKD3DSIH_MAD, GLSLstd450Fma},
{VKD3DSIH_MAX, GLSLstd450FMax},
{VKD3DSIH_MIN, GLSLstd450FMin},
{VKD3DSIH_RSQ, GLSLstd450InverseSqrt},
{VKD3DSIH_SQRT, GLSLstd450Sqrt},
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(glsl_insts); ++i)
{
if (glsl_insts[i].handler_idx == instruction->handler_idx)
return glsl_insts[i].glsl_inst;
}
return GLSLstd450Bad;
}
static void vkd3d_dxbc_compiler_emit_ext_glsl_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t src_id[VKD3D_DXBC_MAX_SOURCE_COUNT];
uint32_t instr_set_id, type_id, val_id;
unsigned int component_count;
enum GLSLstd450 glsl_inst;
unsigned int i;
glsl_inst = vkd3d_dxbc_compiler_map_ext_glsl_instruction(instruction);
if (glsl_inst == GLSLstd450Bad)
{
Józef Kucia
committed
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
return;
}
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
assert(instruction->dst_count == 1);
assert(instruction->src_count <= VKD3D_DXBC_MAX_SOURCE_COUNT);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst->reg.data_type), component_count);
for (i = 0; i < instruction->src_count; ++i)
src_id[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id,
instr_set_id, glsl_inst, src_id, instruction->src_count);
if (instruction->handler_idx == VKD3DSIH_FIRSTBIT_HI
|| instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI)
{
/* In D3D bits are numbered from the most significant bit. */
val_id = vkd3d_spirv_build_op_isub(builder, type_id,
vkd3d_dxbc_compiler_get_constant_uint(compiler, 31), val_id);
}
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
static void vkd3d_dxbc_compiler_emit_mov(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t val_id, dst_val_id, type_id, dst_id, src_id;
uint32_t components[VKD3D_VEC4_SIZE];
unsigned int i, component_count;
component_count = vkd3d_write_mask_component_count(dst->write_mask);
if (component_count == 1 || component_count == VKD3D_VEC4_SIZE
|| dst->modifiers || src->modifiers || src->reg.type == VKD3DSPR_IMMCONST)
{
val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
}
else
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
dst_id = vkd3d_dxbc_compiler_get_register_id(compiler, &dst->reg);
src_id = vkd3d_dxbc_compiler_get_register_id(compiler, &src->reg);
val_id = vkd3d_spirv_build_op_load(builder, type_id, src_id, SpvMemoryAccessMaskNone);
dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone);
for (i = 0; i < ARRAY_SIZE(components); ++i)
{
if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))
components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i);
else
components[i] = i;
}
val_id = vkd3d_spirv_build_op_vector_shuffle(builder,
type_id, dst_val_id, val_id, components, VKD3D_VEC4_SIZE);
vkd3d_spirv_build_op_store(builder, dst_id, val_id, SpvMemoryAccessMaskNone);
}
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
static uint32_t vkd3d_dxbc_compiler_emit_int_to_bool(struct vkd3d_dxbc_compiler *compiler,
enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id;
SpvOp op;
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_BOOL, component_count);
op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual;
return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
op, type_id, val_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 0));
}
static void vkd3d_dxbc_compiler_emit_movc(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t condition_id, src1_id, src2_id, type_id, val_id;
unsigned int component_count;
condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
src2_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[2], dst->write_mask);
component_count = vkd3d_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, component_count);
condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id);
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
static void vkd3d_dxbc_compiler_emit_dot(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t type_id, val_id, src_ids[2];
DWORD write_mask;
unsigned int i;
assert(vkd3d_write_mask_component_count(dst->write_mask) == 1);
if (instruction->handler_idx == VKD3DSIH_DP4)
write_mask = VKD3DSP_WRITEMASK_ALL;
else if (instruction->handler_idx == VKD3DSIH_DP3)
write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2;
else
write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1;
assert(instruction->src_count == ARRAY_SIZE(src_ids));
for (i = 0; i < instruction->src_count; ++i)
src_ids[i] = vkd3d_dxbc_compiler_emit_load_reg(compiler,
&src[i].reg, src[i].swizzle, write_mask);
type_id = vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(dst->reg.data_type), 1);
val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
SpvOpDot, type_id, src_ids[0], src_ids[1]);
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
static void vkd3d_dxbc_compiler_emit_bitfield_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t src_ids[4], result_id, type_id, mask_id;
unsigned int i, j, src_count;
DWORD write_mask;
SpvOp op;
src_count = instruction->src_count;
assert(2 <= src_count && src_count <= ARRAY_SIZE(src_ids));
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
mask_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0x1f);
switch (instruction->handler_idx)
{
case VKD3DSIH_BFI: op = SpvOpBitFieldInsert; break;
case VKD3DSIH_IBFE: op = SpvOpBitFieldSExtract; break;
case VKD3DSIH_UBFE: op = SpvOpBitFieldUExtract; break;
default:
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
return;
}
for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
{
if (!(write_mask = dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
for (j = 0; j < src_count; ++j)
src_ids[src_count - j - 1] = vkd3d_dxbc_compiler_emit_load_reg(compiler,
&src[j].reg, src[j].swizzle, write_mask);
for (j = src_count - 2; j < src_count; ++j)
{
Józef Kucia
committed
uint32_t int_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_INT, 1);
src_ids[j] = vkd3d_spirv_build_op_and(builder, int_type_id, src_ids[j], mask_id);
}
result_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream,
op, type_id, src_ids, src_count);
vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, write_mask, result_id);
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
static void vkd3d_dxbc_compiler_emit_f16tof32(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
static const uint32_t indexes[] = {0};
uint32_t instr_set_id, type_id, scalar_type_id, src_id, result_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;
DWORD write_mask;
unsigned int i;
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, 2);
scalar_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, 1);
/* FIXME: Consider a single UnpackHalf2x16 intruction per 2 components. */
for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
{
if (!(write_mask = dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, write_mask);
result_id = vkd3d_spirv_build_op_ext_inst(builder, type_id,
instr_set_id, GLSLstd450UnpackHalf2x16, &src_id, 1);
result_id = vkd3d_spirv_build_op_composite_extract(builder, scalar_type_id,
result_id, indexes, ARRAY_SIZE(indexes));
vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, write_mask, result_id);
}
}
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
static void vkd3d_dxbc_compiler_emit_f32tof16(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t instr_set_id, type_id, scalar_type_id, src_id, zero_id, constituents[2], result_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;
DWORD write_mask;
unsigned int i;
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, 2);
scalar_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
zero_id = vkd3d_dxbc_compiler_get_constant_float(compiler, 0.0f);
/* FIXME: Consider a single PackHalf2x16 intruction per 2 components. */
for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
{
if (!(write_mask = dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, write_mask);
constituents[0] = src_id;
constituents[1] = zero_id;
src_id = vkd3d_spirv_build_op_composite_construct(builder,
type_id, constituents, ARRAY_SIZE(constituents));
result_id = vkd3d_spirv_build_op_ext_inst(builder, scalar_type_id,
instr_set_id, GLSLstd450PackHalf2x16, &src_id, 1);
vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, write_mask, result_id);
}
}
static void vkd3d_dxbc_compiler_emit_comparison_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
static const uint32_t d3d_true[] = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
static const uint32_t d3d_false[] = {0, 0, 0, 0};
uint32_t src0_id, src1_id, type_id, result_id, true_id, false_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;
unsigned int component_count;
SpvOp op;
switch (instruction->handler_idx)
{
case VKD3DSIH_EQ: op = SpvOpFOrdEqual; break;
case VKD3DSIH_GE: op = SpvOpFOrdGreaterThanEqual; break;
case VKD3DSIH_IEQ: op = SpvOpIEqual; break;
case VKD3DSIH_LT: op = SpvOpFOrdLessThan; break;
case VKD3DSIH_NE: op = SpvOpFUnordNotEqual; break;
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
default:
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
return;
}
component_count = vkd3d_write_mask_component_count(dst->write_mask);
src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_BOOL, component_count);
result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
op, type_id, src0_id, src1_id);
true_id = vkd3d_dxbc_compiler_get_constant(compiler, VKD3D_TYPE_UINT, component_count, d3d_true);
false_id = vkd3d_dxbc_compiler_get_constant(compiler, VKD3D_TYPE_UINT, component_count, d3d_false);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, component_count);
result_id = vkd3d_spirv_build_op_select(builder, type_id, result_id, true_id, false_id);
vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id);
}
static void vkd3d_dxbc_compiler_emit_return(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
Józef Kucia
committed
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t void_id, function_id, arguments[MAX_REG_OUTPUT];
unsigned int i, count;;
if ((function_id = compiler->output_setup_function_id))
{
void_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_VOID, 1);
for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
{
if (compiler->private_output_variable[i])
arguments[count++] = compiler->private_output_variable[i];
}
vkd3d_spirv_build_op_function_call(builder, void_id, function_id, arguments, count);
}
vkd3d_spirv_build_op_return(builder);
static void vkd3d_dxbc_compiler_emit_control_flow_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_control_flow_info *cf_info = &compiler->control_flow_info;
uint32_t merge_block_id, val_id, condition_id, true_label, false_label;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_src_param *src = instruction->src;
switch (instruction->handler_idx)
{
case VKD3DSIH_IF:
if (cf_info->current_block != VKD3D_BLOCK_MAIN)
{
FIXME("Nested control flow not supported yet.\n");
return;
}
val_id = vkd3d_dxbc_compiler_emit_load_reg(compiler,
&src->reg, src->swizzle, 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->merge_block_id = merge_block_id;
cf_info->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:
if (cf_info->current_block == VKD3D_BLOCK_IF)
vkd3d_spirv_build_op_branch(builder, cf_info->merge_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->else_block_id);
cf_info->current_block = VKD3D_BLOCK_ELSE;
break;
case VKD3DSIH_ENDIF:
assert(cf_info->current_block != VKD3D_BLOCK_MAIN);
if (cf_info->current_block == VKD3D_BLOCK_IF)
{
vkd3d_spirv_build_op_branch(builder, cf_info->merge_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->else_block_id);
vkd3d_spirv_build_op_branch(builder, cf_info->merge_block_id);
}
else if (cf_info->current_block == VKD3D_BLOCK_ELSE)
{
vkd3d_spirv_build_op_branch(builder, cf_info->merge_block_id);
}
vkd3d_spirv_build_op_label(builder, cf_info->merge_block_id);
memset(cf_info, 0, sizeof(*cf_info));
break;
case VKD3DSIH_RET:
vkd3d_dxbc_compiler_emit_return(compiler, instruction);
if (cf_info->current_block == VKD3D_BLOCK_IF)
{
vkd3d_spirv_build_op_label(builder, cf_info->else_block_id);
cf_info->current_block = VKD3D_BLOCK_ELSE;
}
else
{
cf_info->current_block = VKD3D_BLOCK_NONE;
}
break;
default:
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
break;
}
}
void vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_TEMPS:
vkd3d_dxbc_compiler_emit_dcl_temps(compiler, instruction);
break;
case VKD3DSIH_DCL_CONSTANT_BUFFER:
vkd3d_dxbc_compiler_emit_dcl_constant_buffer(compiler, instruction);
break;
case VKD3DSIH_DCL_INPUT:
vkd3d_dxbc_compiler_emit_dcl_input(compiler, instruction);
break;
case VKD3DSIH_DCL_INPUT_PS:
vkd3d_dxbc_compiler_emit_dcl_input_ps(compiler, instruction);
break;
case VKD3DSIH_DCL_INPUT_PS_SIV:
vkd3d_dxbc_compiler_emit_dcl_input_ps_siv(compiler, instruction);
break;
case VKD3DSIH_DCL_INPUT_SGV:
vkd3d_dxbc_compiler_emit_dcl_input_sgv(compiler, instruction);
break;
case VKD3DSIH_DCL_OUTPUT:
vkd3d_dxbc_compiler_emit_dcl_output(compiler, instruction);
break;
case VKD3DSIH_DCL_OUTPUT_SIV:
vkd3d_dxbc_compiler_emit_dcl_output_siv(compiler, instruction);
break;
case VKD3DSIH_DCL_THREAD_GROUP:
vkd3d_dxbc_compiler_emit_dcl_thread_group(compiler, instruction);
break;
case VKD3DSIH_MOV:
vkd3d_dxbc_compiler_emit_mov(compiler, instruction);
break;
case VKD3DSIH_MOVC:
vkd3d_dxbc_compiler_emit_movc(compiler, instruction);
break;
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:
vkd3d_dxbc_compiler_emit_alu_instruction(compiler, instruction);
break;
case VKD3DSIH_FIRSTBIT_HI:
case VKD3DSIH_FIRSTBIT_LO:
case VKD3DSIH_FIRSTBIT_SHI:
case VKD3DSIH_MAD:
case VKD3DSIH_MAX:
case VKD3DSIH_MIN:
case VKD3DSIH_RSQ:
vkd3d_dxbc_compiler_emit_ext_glsl_instruction(compiler, instruction);
break;
case VKD3DSIH_DP4:
case VKD3DSIH_DP3:
case VKD3DSIH_DP2:
vkd3d_dxbc_compiler_emit_dot(compiler, instruction);
break;
case VKD3DSIH_EQ:
case VKD3DSIH_GE:
case VKD3DSIH_LT:
case VKD3DSIH_NE:
vkd3d_dxbc_compiler_emit_comparison_instruction(compiler, instruction);
break;
case VKD3DSIH_IBFE:
case VKD3DSIH_UBFE:
vkd3d_dxbc_compiler_emit_bitfield_instruction(compiler, instruction);
break;
case VKD3DSIH_F16TOF32:
vkd3d_dxbc_compiler_emit_f16tof32(compiler, instruction);
break;
case VKD3DSIH_F32TOF16:
vkd3d_dxbc_compiler_emit_f32tof16(compiler, instruction);
break;
case VKD3DSIH_IF:
case VKD3DSIH_ELSE:
case VKD3DSIH_ENDIF:
vkd3d_dxbc_compiler_emit_control_flow_instruction(compiler, instruction);
break;
default:
FIXME("Unhandled instruction %#x.\n", instruction->handler_idx);
}
Józef Kucia
committed
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
static void vkd3d_dxbc_compiler_emit_output_setup_function(struct vkd3d_dxbc_compiler *compiler)
{
uint32_t void_id, type_id, ptr_type_id, function_type_id, function_id, val_id;
const struct vkd3d_shader_signature *signature = compiler->output_signature;
uint32_t param_type_id[MAX_REG_OUTPUT], param_id[MAX_REG_OUTPUT] = {};
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
DWORD write_mask, reg_idx;
unsigned int i, count;
function_id = compiler->output_setup_function_id;
void_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_VOID, 1);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, 4);
ptr_type_id = vkd3d_dxbc_compiler_get_pointer_type(compiler, type_id, SpvStorageClassPrivate);
for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
{
if (compiler->private_output_variable[i])
param_type_id[count++] = ptr_type_id;
}
function_type_id = vkd3d_spirv_build_op_type_function(builder, void_id, param_type_id, count);
vkd3d_spirv_build_op_function(builder, void_id, function_id,
SpvFunctionControlMaskNone, function_type_id);
vkd3d_spirv_build_op_name(builder, function_id, "setup_output");
for (i = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
{
if (compiler->private_output_variable[i])
param_id[i] = vkd3d_spirv_build_op_function_parameter(builder, ptr_type_id);
}
vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
for (i = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
{
if (compiler->private_output_variable[i])
param_id[i] = vkd3d_spirv_build_op_load(builder, type_id, param_id[i], SpvMemoryAccessMaskNone);
}
for (i = 0; i < signature->element_count; ++i)
{
reg_idx = signature->elements[i].register_idx;
write_mask = signature->elements[i].mask & 0xff;
if (!param_id[reg_idx])
continue;
val_id = vkd3d_dxbc_compiler_emit_extract_components(compiler, param_id[reg_idx],
write_mask, VKD3D_TYPE_FLOAT);
if (compiler->output_info[i].component_type != VKD3D_TYPE_FLOAT)
{
type_id = vkd3d_spirv_get_type_id(builder, compiler->output_info[i].component_type,
vkd3d_write_mask_component_count(write_mask));
val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
}
vkd3d_spirv_build_op_store(builder, compiler->output_info[i].id, val_id, SpvMemoryAccessMaskNone);
}
vkd3d_spirv_build_op_return(&compiler->spirv_builder);
vkd3d_spirv_build_op_function_end(builder);
}
bool vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_shader_code *spirv)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
if (compiler->options & VKD3D_SHADER_STRIP_DEBUG)
vkd3d_spirv_stream_clear(&builder->debug_stream);
Józef Kucia
committed
vkd3d_spirv_build_op_function_end(builder);
if (compiler->output_setup_function_id)
vkd3d_dxbc_compiler_emit_output_setup_function(compiler);
if (!vkd3d_spirv_compile_module(builder, spirv))
return false;
if (TRACE_ON())
{
vkd3d_spirv_dump(spirv);
vkd3d_spirv_validate(spirv);
}
return true;
}
void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler)
{
Józef Kucia
committed
vkd3d_free(compiler->output_info);
vkd3d_spirv_builder_free(&compiler->spirv_builder);
rb_destroy(&compiler->symbol_table, vkd3d_symbol_free, NULL);
vkd3d_free(compiler);
}