SpvId GLSL_std_450;
gl_shader_stage stage;
- int var_location;
SpvId ubos[128];
size_t num_ubos;
size_t num_blocks;
bool block_started;
SpvId loop_break, loop_cont;
+
+ SpvId front_face_var;
};
static SpvId
get_glsl_basetype(struct ntv_context *ctx, enum glsl_base_type type)
{
switch (type) {
+ case GLSL_TYPE_BOOL:
+ return spirv_builder_type_bool(&ctx->builder);
+
case GLSL_TYPE_FLOAT:
return spirv_builder_type_float(&ctx->builder, 32);
spirv_builder_emit_name(&ctx->builder, var_id, var->name);
if (ctx->stage == MESA_SHADER_FRAGMENT) {
- if (var->data.location >= VARYING_SLOT_VAR0 ||
- (var->data.location >= VARYING_SLOT_COL0 &&
- var->data.location <= VARYING_SLOT_TEX7)) {
+ if (var->data.location >= VARYING_SLOT_VAR0)
+ spirv_builder_emit_location(&ctx->builder, var_id,
+ var->data.location -
+ VARYING_SLOT_VAR0 +
+ VARYING_SLOT_TEX0);
+ else if ((var->data.location >= VARYING_SLOT_COL0 &&
+ var->data.location <= VARYING_SLOT_TEX7) ||
+ var->data.location == VARYING_SLOT_BFC0 ||
+ var->data.location == VARYING_SLOT_BFC1) {
spirv_builder_emit_location(&ctx->builder, var_id,
- ctx->var_location++);
+ var->data.location);
} else {
switch (var->data.location) {
case VARYING_SLOT_POS:
if (ctx->stage == MESA_SHADER_VERTEX) {
- if (var->data.location >= VARYING_SLOT_VAR0 ||
- (var->data.location >= VARYING_SLOT_COL0 &&
- var->data.location <= VARYING_SLOT_TEX7)) {
+ if (var->data.location >= VARYING_SLOT_VAR0)
spirv_builder_emit_location(&ctx->builder, var_id,
- ctx->var_location++);
+ var->data.location -
+ VARYING_SLOT_VAR0 +
+ VARYING_SLOT_TEX0);
+ else if ((var->data.location >= VARYING_SLOT_COL0 &&
+ var->data.location <= VARYING_SLOT_TEX7) ||
+ var->data.location == VARYING_SLOT_BFC0 ||
+ var->data.location == VARYING_SLOT_BFC1) {
+ spirv_builder_emit_location(&ctx->builder, var_id,
+ var->data.location);
} else {
switch (var->data.location) {
case VARYING_SLOT_POS:
return SpvDim1D;
case GLSL_SAMPLER_DIM_2D:
return SpvDim2D;
- case GLSL_SAMPLER_DIM_RECT:
- return SpvDimRect;
- case GLSL_SAMPLER_DIM_CUBE:
- return SpvDimCube;
case GLSL_SAMPLER_DIM_3D:
return SpvDim3D;
+ case GLSL_SAMPLER_DIM_CUBE:
+ return SpvDimCube;
+ case GLSL_SAMPLER_DIM_RECT:
+ return SpvDimRect;
+ case GLSL_SAMPLER_DIM_BUF:
+ return SpvDimBuffer;
+ case GLSL_SAMPLER_DIM_EXTERNAL:
+ return SpvDim2D; /* seems dodgy... */
case GLSL_SAMPLER_DIM_MS:
*is_ms = true;
return SpvDim2D;
op, args, ARRAY_SIZE(args));
}
+static SpvId
+emit_builtin_triop(struct ntv_context *ctx, enum GLSLstd450 op, SpvId type,
+ SpvId src0, SpvId src1, SpvId src2)
+{
+ SpvId args[] = { src0, src1, src2 };
+ return spirv_builder_emit_ext_inst(&ctx->builder, type, ctx->GLSL_std_450,
+ op, args, ARRAY_SIZE(args));
+}
+
static SpvId
get_fvec_constant(struct ntv_context *ctx, unsigned bit_size,
unsigned num_components, float value)
result = emit_builtin_unop(ctx, spirv_op, dest_type, src[0]); \
break;
+ BUILTIN_UNOP(nir_op_iabs, GLSLstd450SAbs)
BUILTIN_UNOP(nir_op_fabs, GLSLstd450FAbs)
BUILTIN_UNOP(nir_op_fsqrt, GLSLstd450Sqrt)
BUILTIN_UNOP(nir_op_frsq, GLSLstd450InverseSqrt)
BINOP(nir_op_imul, SpvOpIMul)
BINOP(nir_op_idiv, SpvOpSDiv)
BINOP(nir_op_udiv, SpvOpUDiv)
+ BINOP(nir_op_umod, SpvOpUMod)
BINOP(nir_op_fadd, SpvOpFAdd)
BINOP(nir_op_fsub, SpvOpFSub)
BINOP(nir_op_fmul, SpvOpFMul)
BINOP(nir_op_ige, SpvOpSGreaterThanEqual)
BINOP(nir_op_ieq, SpvOpIEqual)
BINOP(nir_op_ine, SpvOpINotEqual)
+ BINOP(nir_op_uge, SpvOpUGreaterThanEqual)
BINOP(nir_op_flt, SpvOpFOrdLessThan)
BINOP(nir_op_fge, SpvOpFOrdGreaterThanEqual)
BINOP(nir_op_feq, SpvOpFOrdEqual)
}
break;
+ case nir_op_flrp:
+ assert(nir_op_infos[alu->op].num_inputs == 3);
+ result = emit_builtin_triop(ctx, GLSLstd450FMix, dest_type,
+ src[0], src[1], src[2]);
+ break;
+
case nir_op_fcsel:
result = emit_binop(ctx, SpvOpFOrdGreaterThan,
get_bvec_type(ctx, num_components),
result = emit_select(ctx, dest_type, src[0], src[1], src[2]);
break;
+ case nir_op_bany_fnequal2:
+ case nir_op_bany_fnequal3:
+ case nir_op_bany_fnequal4:
+ assert(nir_op_infos[alu->op].num_inputs == 2);
+ assert(alu_instr_src_components(alu, 0) ==
+ alu_instr_src_components(alu, 1));
+ result = emit_binop(ctx, SpvOpFOrdNotEqual,
+ get_bvec_type(ctx, alu_instr_src_components(alu, 0)),
+ src[0], src[1]);
+ result = emit_unop(ctx, SpvOpAny, dest_type, result);
+ break;
+
+ case nir_op_ball_fequal2:
+ case nir_op_ball_fequal3:
+ case nir_op_ball_fequal4:
+ assert(nir_op_infos[alu->op].num_inputs == 2);
+ assert(alu_instr_src_components(alu, 0) ==
+ alu_instr_src_components(alu, 1));
+ result = emit_binop(ctx, SpvOpFOrdEqual,
+ get_bvec_type(ctx, alu_instr_src_components(alu, 0)),
+ src[0], src[1]);
+ result = emit_unop(ctx, SpvOpAll, dest_type, result);
+ break;
+
+ case nir_op_bany_inequal2:
+ case nir_op_bany_inequal3:
+ case nir_op_bany_inequal4:
+ assert(nir_op_infos[alu->op].num_inputs == 2);
+ assert(alu_instr_src_components(alu, 0) ==
+ alu_instr_src_components(alu, 1));
+ result = emit_binop(ctx, SpvOpINotEqual,
+ get_bvec_type(ctx, alu_instr_src_components(alu, 0)),
+ src[0], src[1]);
+ result = emit_unop(ctx, SpvOpAny, dest_type, result);
+ break;
+
+ case nir_op_ball_iequal2:
+ case nir_op_ball_iequal3:
+ case nir_op_ball_iequal4:
+ assert(nir_op_infos[alu->op].num_inputs == 2);
+ assert(alu_instr_src_components(alu, 0) ==
+ alu_instr_src_components(alu, 1));
+ result = emit_binop(ctx, SpvOpIEqual,
+ get_bvec_type(ctx, alu_instr_src_components(alu, 0)),
+ src[0], src[1]);
+ result = emit_unop(ctx, SpvOpAll, dest_type, result);
+ break;
+
case nir_op_vec2:
case nir_op_vec3:
case nir_op_vec4: {
static void
emit_load_const(struct ntv_context *ctx, nir_load_const_instr *load_const)
{
- uint32_t values[NIR_MAX_VEC_COMPONENTS];
- for (int i = 0; i < load_const->def.num_components; ++i)
- values[i] = load_const->value[i].u32;
-
unsigned bit_size = load_const->def.bit_size;
unsigned num_components = load_const->def.num_components;
SpvId constant;
if (num_components > 1) {
SpvId components[num_components];
- for (int i = 0; i < num_components; i++)
- components[i] = emit_uint_const(ctx, bit_size, values[i]);
+ SpvId type;
+ if (bit_size == 1) {
+ for (int i = 0; i < num_components; i++)
+ components[i] = spirv_builder_const_bool(&ctx->builder,
+ load_const->value[i].b);
- SpvId type = get_uvec_type(ctx, bit_size, num_components);
+ type = get_bvec_type(ctx, num_components);
+ } else {
+ for (int i = 0; i < num_components; i++)
+ components[i] = emit_uint_const(ctx, bit_size,
+ load_const->value[i].u32);
+
+ type = get_uvec_type(ctx, bit_size, num_components);
+ }
constant = spirv_builder_const_composite(&ctx->builder, type,
components, num_components);
} else {
assert(num_components == 1);
- constant = emit_uint_const(ctx, bit_size, values[0]);
+ if (bit_size == 1)
+ constant = spirv_builder_const_bool(&ctx->builder,
+ load_const->value[0].b);
+ else
+ constant = emit_uint_const(ctx, bit_size, load_const->value[0].u32);
}
+ if (bit_size == 1)
+ constant = bvec_to_uvec(ctx, constant, num_components);
+
store_ssa_def_uint(ctx, &load_const->def, constant);
}
spirv_builder_emit_store(&ctx->builder, ptr, result);
}
+static void
+emit_load_front_face(struct ntv_context *ctx, nir_intrinsic_instr *intr)
+{
+ SpvId var_type = get_glsl_type(ctx, glsl_bool_type());
+ if (!ctx->front_face_var) {
+ SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
+ SpvStorageClassInput,
+ var_type);
+ ctx->front_face_var = spirv_builder_emit_var(&ctx->builder,
+ pointer_type,
+ SpvStorageClassInput);
+ spirv_builder_emit_name(&ctx->builder, ctx->front_face_var,
+ "gl_FrontFacing");
+ spirv_builder_emit_builtin(&ctx->builder, ctx->front_face_var,
+ SpvBuiltInFrontFacing);
+
+ assert(ctx->num_entry_ifaces < ARRAY_SIZE(ctx->entry_ifaces));
+ ctx->entry_ifaces[ctx->num_entry_ifaces++] = ctx->front_face_var;
+ }
+
+ SpvId result = spirv_builder_emit_load(&ctx->builder, var_type,
+ ctx->front_face_var);
+ assert(1 == nir_dest_num_components(intr->dest));
+ result = bvec_to_uvec(ctx, result, 1);
+ store_dest_uint(ctx, &intr->dest, result);
+}
+
static void
emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
{
emit_store_deref(ctx, intr);
break;
+ case nir_intrinsic_load_front_face:
+ emit_load_front_face(ctx, intr);
+ break;
+
default:
fprintf(stderr, "emit_intrinsic: not implemented (%s)\n",
nir_intrinsic_infos[intr->intrinsic].name);
return bitcast_to_fvec(ctx, def, bit_size, num_components);
}
+static SpvId
+get_src_int(struct ntv_context *ctx, nir_src *src)
+{
+ SpvId def = get_src_uint(ctx, src);
+ unsigned num_components = nir_src_num_components(*src);
+ unsigned bit_size = nir_src_bit_size(*src);
+ return bitcast_to_ivec(ctx, def, bit_size, num_components);
+}
+
static void
emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
{
assert(tex->op == nir_texop_tex ||
tex->op == nir_texop_txb ||
- tex->op == nir_texop_txl);
+ tex->op == nir_texop_txl ||
+ tex->op == nir_texop_txd ||
+ tex->op == nir_texop_txf);
assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
assert(tex->texture_index == tex->sampler_index);
- SpvId coord = 0, proj = 0, bias = 0, lod = 0, dref = 0;
- unsigned coord_components;
+ SpvId coord = 0, proj = 0, bias = 0, lod = 0, dref = 0, dx = 0, dy = 0;
+ unsigned coord_components = 0;
for (unsigned i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
case nir_tex_src_coord:
- coord = get_src_float(ctx, &tex->src[i].src);
+ if (tex->op == nir_texop_txf)
+ coord = get_src_int(ctx, &tex->src[i].src);
+ else
+ coord = get_src_float(ctx, &tex->src[i].src);
coord_components = nir_src_num_components(tex->src[i].src);
break;
case nir_tex_src_lod:
assert(nir_src_num_components(tex->src[i].src) == 1);
- lod = get_src_float(ctx, &tex->src[i].src);
+ if (tex->op == nir_texop_txf)
+ lod = get_src_int(ctx, &tex->src[i].src);
+ else
+ lod = get_src_float(ctx, &tex->src[i].src);
assert(lod != 0);
break;
assert(dref != 0);
break;
+ case nir_tex_src_ddx:
+ dx = get_src_float(ctx, &tex->src[i].src);
+ assert(dx != 0);
+ break;
+
+ case nir_tex_src_ddy:
+ dy = get_src_float(ctx, &tex->src[i].src);
+ assert(dy != 0);
+ break;
+
default:
fprintf(stderr, "texture source: %d\n", tex->src[i].src_type);
unreachable("unknown texture source");
if (dref)
actual_dest_type = float_type;
- SpvId result = spirv_builder_emit_image_sample(&ctx->builder,
- actual_dest_type, load,
- coord,
- proj != 0,
- lod, bias, dref);
+ SpvId result;
+ if (tex->op == nir_texop_txf) {
+ SpvId image = spirv_builder_emit_image(&ctx->builder, image_type, load);
+ result = spirv_builder_emit_image_fetch(&ctx->builder, dest_type,
+ image, coord, lod);
+ } else {
+ result = spirv_builder_emit_image_sample(&ctx->builder,
+ actual_dest_type, load,
+ coord,
+ proj != 0,
+ lod, bias, dref, dx, dy);
+ }
+
spirv_builder_emit_decoration(&ctx->builder, result,
SpvDecorationRelaxedPrecision);
nir_foreach_variable(var, &s->uniforms)
emit_uniform(&ctx, var);
- spirv_builder_emit_entry_point(&ctx.builder, exec_model, entry_point,
- "main", ctx.entry_ifaces,
- ctx.num_entry_ifaces);
if (s->info.stage == MESA_SHADER_FRAGMENT) {
spirv_builder_emit_exec_mode(&ctx.builder, entry_point,
SpvExecutionModeOriginUpperLeft);
spirv_builder_return(&ctx.builder); // doesn't belong here, but whatevz
spirv_builder_function_end(&ctx.builder);
+ spirv_builder_emit_entry_point(&ctx.builder, exec_model, entry_point,
+ "main", ctx.entry_ifaces,
+ ctx.num_entry_ifaces);
+
size_t num_words = spirv_builder_get_num_words(&ctx.builder);
ret = CALLOC_STRUCT(spirv_shader);