X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fzink%2Fnir_to_spirv%2Fnir_to_spirv.c;h=09312dae406c2eb67a4135d91c7d737929713b20;hb=98885e9f6164e1c9b764c8e237ed6c996c2305cb;hp=c3d84ec8643384f60d6e78e9851226929daa1ca1;hpb=5f14168edf577fcaaf389a225a5648a2e725bcf1;p=mesa.git diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index c3d84ec8643..09312dae406 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -35,7 +35,6 @@ struct ntv_context { SpvId GLSL_std_450; gl_shader_stage stage; - int var_location; SpvId ubos[128]; size_t num_ubos; @@ -56,15 +55,21 @@ struct ntv_context { size_t num_blocks; bool block_started; SpvId loop_break, loop_cont; + + SpvId front_face_var; }; static SpvId -get_fvec_constant(struct ntv_context *ctx, int bit_size, int num_components, - const float values[]); +get_fvec_constant(struct ntv_context *ctx, unsigned bit_size, + unsigned num_components, float value); + +static SpvId +get_uvec_constant(struct ntv_context *ctx, unsigned bit_size, + unsigned num_components, uint32_t value); static SpvId -get_uvec_constant(struct ntv_context *ctx, int bit_size, int num_components, - const uint32_t values[]); +get_ivec_constant(struct ntv_context *ctx, unsigned bit_size, + unsigned num_components, int32_t value); static SpvId emit_unop(struct ntv_context *ctx, SpvOp op, SpvId type, SpvId src); @@ -96,6 +101,27 @@ block_label(struct ntv_context *ctx, nir_block *block) return ctx->block_ids[block->index]; } +static SpvId +emit_float_const(struct ntv_context *ctx, int bit_size, float value) +{ + assert(bit_size == 32); + return spirv_builder_const_float(&ctx->builder, bit_size, value); +} + +static SpvId +emit_uint_const(struct ntv_context *ctx, int bit_size, uint32_t value) +{ + assert(bit_size == 32); + return spirv_builder_const_uint(&ctx->builder, bit_size, value); +} + +static SpvId +emit_int_const(struct ntv_context *ctx, int bit_size, int32_t value) +{ + assert(bit_size == 32); + return spirv_builder_const_int(&ctx->builder, bit_size, value); +} + static SpvId get_fvec_type(struct ntv_context *ctx, unsigned bit_size, unsigned num_components) { @@ -113,9 +139,9 @@ get_fvec_type(struct ntv_context *ctx, unsigned bit_size, unsigned num_component static SpvId get_ivec_type(struct ntv_context *ctx, unsigned bit_size, unsigned num_components) { - assert(bit_size == 32); // only 32-bit ints supported so far + assert(bit_size == 1 || bit_size == 32); // only 32-bit ints supported so far - SpvId int_type = spirv_builder_type_int(&ctx->builder, bit_size); + SpvId int_type = spirv_builder_type_int(&ctx->builder, MAX2(bit_size, 32)); if (num_components > 1) return spirv_builder_type_vector(&ctx->builder, int_type, num_components); @@ -127,9 +153,9 @@ get_ivec_type(struct ntv_context *ctx, unsigned bit_size, unsigned num_component static SpvId get_uvec_type(struct ntv_context *ctx, unsigned bit_size, unsigned num_components) { - assert(bit_size == 32); // only 32-bit uints supported so far + assert(bit_size == 1 || bit_size == 32); // only 32-bit uints supported so far - SpvId uint_type = spirv_builder_type_uint(&ctx->builder, bit_size); + SpvId uint_type = spirv_builder_type_uint(&ctx->builder, MAX2(bit_size, 32)); if (num_components > 1) return spirv_builder_type_vector(&ctx->builder, uint_type, num_components); @@ -149,6 +175,9 @@ 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); @@ -179,7 +208,7 @@ get_glsl_type(struct ntv_context *ctx, const struct glsl_type *type) if (glsl_type_is_array(type)) { SpvId ret = spirv_builder_type_array(&ctx->builder, get_glsl_type(ctx, glsl_get_array_element(type)), - spirv_builder_const_uint(&ctx->builder, 32, glsl_get_length(type))); + emit_uint_const(ctx, 32, glsl_get_length(type))); uint32_t stride = glsl_get_explicit_stride(type); if (stride) spirv_builder_emit_array_stride(&ctx->builder, ret, stride); @@ -204,11 +233,17 @@ emit_input(struct ntv_context *ctx, struct nir_variable *var) 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, - 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: @@ -256,11 +291,17 @@ emit_output(struct ntv_context *ctx, struct nir_variable *var) 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, + 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: @@ -321,12 +362,16 @@ type_to_dim(enum glsl_sampler_dim gdim, bool *is_ms) 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; @@ -371,7 +416,7 @@ emit_ubo(struct ntv_context *ctx, struct nir_variable *var) { uint32_t size = glsl_count_attribute_slots(var->type, false); SpvId vec4_type = get_uvec_type(ctx, 32, 4); - SpvId array_length = spirv_builder_const_uint(&ctx->builder, 32, size); + SpvId array_length = emit_uint_const(ctx, 32, size); SpvId array_type = spirv_builder_type_array(&ctx->builder, vec4_type, array_length); spirv_builder_emit_array_stride(&ctx->builder, array_type, 16); @@ -484,8 +529,9 @@ get_alu_src_uint(struct ntv_context *ctx, nir_alu_instr *alu, unsigned src) return def; int bit_size = nir_src_bit_size(alu->src[src].src); + assert(bit_size == 1 || bit_size == 32); - SpvId uint_type = spirv_builder_type_uint(&ctx->builder, bit_size); + SpvId uint_type = spirv_builder_type_uint(&ctx->builder, MAX2(bit_size, 32)); if (used_channels == 1) { uint32_t indices[] = { alu->src[src].swizzle[0] }; return spirv_builder_emit_composite_extract(&ctx->builder, uint_type, @@ -528,34 +574,42 @@ store_ssa_def_uint(struct ntv_context *ctx, nir_ssa_def *ssa, SpvId result) ctx->defs[ssa->index] = result; } +static SpvId +emit_select(struct ntv_context *ctx, SpvId type, SpvId cond, + SpvId if_true, SpvId if_false) +{ + return emit_triop(ctx, SpvOpSelect, type, cond, if_true, if_false); +} + static SpvId bvec_to_uvec(struct ntv_context *ctx, SpvId value, unsigned num_components) { SpvId otype = get_uvec_type(ctx, 32, num_components); - uint32_t zeros[4] = { 0, 0, 0, 0 }; - uint32_t ones[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; - SpvId zero = get_uvec_constant(ctx, 32, num_components, zeros); - SpvId one = get_uvec_constant(ctx, 32, num_components, ones); - return emit_triop(ctx, SpvOpSelect, otype, value, one, zero); + SpvId zero = get_uvec_constant(ctx, 32, num_components, 0); + SpvId one = get_uvec_constant(ctx, 32, num_components, UINT32_MAX); + return emit_select(ctx, otype, value, one, zero); } static SpvId uvec_to_bvec(struct ntv_context *ctx, SpvId value, unsigned num_components) { SpvId type = get_bvec_type(ctx, num_components); - - uint32_t zeros[NIR_MAX_VEC_COMPONENTS] = { 0 }; - SpvId zero = get_uvec_constant(ctx, 32, num_components, zeros); - + SpvId zero = get_uvec_constant(ctx, 32, num_components, 0); return emit_binop(ctx, SpvOpINotEqual, type, value, zero); } +static SpvId +emit_bitcast(struct ntv_context *ctx, SpvId type, SpvId value) +{ + return emit_unop(ctx, SpvOpBitcast, type, value); +} + static SpvId bitcast_to_uvec(struct ntv_context *ctx, SpvId value, unsigned bit_size, unsigned num_components) { SpvId type = get_uvec_type(ctx, bit_size, num_components); - return emit_unop(ctx, SpvOpBitcast, type, value); + return emit_bitcast(ctx, type, value); } static SpvId @@ -563,7 +617,7 @@ bitcast_to_ivec(struct ntv_context *ctx, SpvId value, unsigned bit_size, unsigned num_components) { SpvId type = get_ivec_type(ctx, bit_size, num_components); - return emit_unop(ctx, SpvOpBitcast, type, value); + return emit_bitcast(ctx, type, value); } static SpvId @@ -571,7 +625,7 @@ bitcast_to_fvec(struct ntv_context *ctx, SpvId value, unsigned bit_size, unsigned num_components) { SpvId type = get_fvec_type(ctx, bit_size, num_components); - return emit_unop(ctx, SpvOpBitcast, type, value); + return emit_bitcast(ctx, type, value); } static void @@ -657,45 +711,72 @@ emit_builtin_binop(struct ntv_context *ctx, enum GLSLstd450 op, SpvId type, } static SpvId -get_fvec_constant(struct ntv_context *ctx, int bit_size, int num_components, - const float values[]) +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) { assert(bit_size == 32); - if (num_components > 1) { - SpvId components[num_components]; - for (int i = 0; i < num_components; i++) - components[i] = spirv_builder_const_float(&ctx->builder, bit_size, - values[i]); + SpvId result = emit_float_const(ctx, bit_size, value); + if (num_components == 1) + return result; - SpvId type = get_fvec_type(ctx, bit_size, num_components); - return spirv_builder_const_composite(&ctx->builder, type, components, - num_components); - } + assert(num_components > 1); + SpvId components[num_components]; + for (int i = 0; i < num_components; i++) + components[i] = result; - assert(num_components == 1); - return spirv_builder_const_float(&ctx->builder, bit_size, values[0]); + SpvId type = get_fvec_type(ctx, bit_size, num_components); + return spirv_builder_const_composite(&ctx->builder, type, components, + num_components); } static SpvId -get_uvec_constant(struct ntv_context *ctx, int bit_size, int num_components, - const uint32_t values[]) +get_uvec_constant(struct ntv_context *ctx, unsigned bit_size, + unsigned num_components, uint32_t value) { assert(bit_size == 32); - if (num_components > 1) { - SpvId components[num_components]; - for (int i = 0; i < num_components; i++) - components[i] = spirv_builder_const_uint(&ctx->builder, bit_size, - values[i]); + SpvId result = emit_uint_const(ctx, bit_size, value); + if (num_components == 1) + return result; - SpvId type = get_uvec_type(ctx, bit_size, num_components); - return spirv_builder_const_composite(&ctx->builder, type, components, - num_components); - } + assert(num_components > 1); + SpvId components[num_components]; + for (int i = 0; i < num_components; i++) + components[i] = result; - assert(num_components == 1); - return spirv_builder_const_uint(&ctx->builder, bit_size, values[0]); + SpvId type = get_uvec_type(ctx, bit_size, num_components); + return spirv_builder_const_composite(&ctx->builder, type, components, + num_components); +} + +static SpvId +get_ivec_constant(struct ntv_context *ctx, unsigned bit_size, + unsigned num_components, int32_t value) +{ + assert(bit_size == 32); + + SpvId result = emit_int_const(ctx, bit_size, value); + if (num_components == 1) + return result; + + assert(num_components > 1); + SpvId components[num_components]; + for (int i = 0; i < num_components; i++) + components[i] = result; + + SpvId type = get_ivec_type(ctx, bit_size, num_components); + return spirv_builder_const_composite(&ctx->builder, type, components, + num_components); } static inline unsigned @@ -802,14 +883,30 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) UNOP(nir_op_f2u32, SpvOpConvertFToU) UNOP(nir_op_i2f32, SpvOpConvertSToF) UNOP(nir_op_u2f32, SpvOpConvertUToF) + UNOP(nir_op_inot, SpvOpNot) #undef UNOP + case nir_op_b2i32: + assert(nir_op_infos[alu->op].num_inputs == 1); + result = emit_select(ctx, dest_type, src[0], + get_ivec_constant(ctx, 32, num_components, 1), + get_ivec_constant(ctx, 32, num_components, 0)); + break; + + case nir_op_b2f32: + assert(nir_op_infos[alu->op].num_inputs == 1); + result = emit_select(ctx, dest_type, src[0], + get_fvec_constant(ctx, 32, num_components, 1), + get_fvec_constant(ctx, 32, num_components, 0)); + break; + #define BUILTIN_UNOP(nir_op, spirv_op) \ case nir_op: \ assert(nir_op_infos[alu->op].num_inputs == 1); \ 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) @@ -825,15 +922,22 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) BUILTIN_UNOP(nir_op_fcos, GLSLstd450Cos) #undef BUILTIN_UNOP - case nir_op_frcp: { + case nir_op_frcp: assert(nir_op_infos[alu->op].num_inputs == 1); - float one[4] = { 1, 1, 1, 1 }; - src[1] = src[0]; - src[0] = get_fvec_constant(ctx, bit_size, num_components, one); - result = emit_binop(ctx, SpvOpFDiv, dest_type, src[0], src[1]); - } + result = emit_binop(ctx, SpvOpFDiv, dest_type, + get_fvec_constant(ctx, bit_size, num_components, 1), + src[0]); break; + case nir_op_f2b1: + assert(nir_op_infos[alu->op].num_inputs == 1); + result = emit_binop(ctx, SpvOpFOrdNotEqual, dest_type, src[0], + get_fvec_constant(ctx, + nir_src_bit_size(alu->src[0].src), + num_components, 0)); + break; + + #define BINOP(nir_op, spirv_op) \ case nir_op: \ assert(nir_op_infos[alu->op].num_inputs == 2); \ @@ -845,6 +949,7 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) 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) @@ -854,13 +959,16 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) BINOP(nir_op_ige, SpvOpSGreaterThanEqual) BINOP(nir_op_ieq, SpvOpIEqual) BINOP(nir_op_ine, SpvOpINotEqual) - BINOP(nir_op_flt, SpvOpFUnordLessThan) - BINOP(nir_op_fge, SpvOpFUnordGreaterThanEqual) + BINOP(nir_op_uge, SpvOpUGreaterThanEqual) + BINOP(nir_op_flt, SpvOpFOrdLessThan) + BINOP(nir_op_fge, SpvOpFOrdGreaterThanEqual) BINOP(nir_op_feq, SpvOpFOrdEqual) BINOP(nir_op_fne, SpvOpFOrdNotEqual) BINOP(nir_op_ishl, SpvOpShiftLeftLogical) BINOP(nir_op_ishr, SpvOpShiftRightArithmetic) BINOP(nir_op_ushr, SpvOpShiftRightLogical) + BINOP(nir_op_iand, SpvOpBitwiseAnd) + BINOP(nir_op_ior, SpvOpBitwiseOr) #undef BINOP #define BUILTIN_BINOP(nir_op, spirv_op) \ @@ -888,8 +996,8 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) int num_components = nir_dest_num_components(alu->dest.dest); SpvId bool_type = get_bvec_type(ctx, num_components); - SpvId zero = spirv_builder_const_float(&ctx->builder, 32, 0.0f); - SpvId one = spirv_builder_const_float(&ctx->builder, 32, 1.0f); + SpvId zero = emit_float_const(ctx, bit_size, 0.0f); + SpvId one = emit_float_const(ctx, bit_size, 1.0f); if (num_components > 1) { SpvId zero_comps[num_components], one_comps[num_components]; for (int i = 0; i < num_components; i++) { @@ -913,22 +1021,77 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) } result = emit_binop(ctx, op, bool_type, src[0], src[1]); - result = emit_triop(ctx, SpvOpSelect, dest_type, result, one, zero); + result = emit_select(ctx, dest_type, result, one, zero); } break; - case nir_op_fcsel: { + case nir_op_flrp: assert(nir_op_infos[alu->op].num_inputs == 3); - int num_components = nir_dest_num_components(alu->dest.dest); - SpvId bool_type = get_bvec_type(ctx, num_components); + result = emit_builtin_triop(ctx, GLSLstd450FMix, dest_type, + src[0], src[1], src[2]); + break; - float zero[4] = { 0, 0, 0, 0 }; - SpvId cmp = get_fvec_constant(ctx, nir_src_bit_size(alu->src[0].src), - num_components, zero); + case nir_op_fcsel: + result = emit_binop(ctx, SpvOpFOrdGreaterThan, + get_bvec_type(ctx, num_components), + src[0], + get_fvec_constant(ctx, + nir_src_bit_size(alu->src[0].src), + num_components, 0)); + result = emit_select(ctx, dest_type, result, src[1], src[2]); + break; - result = emit_binop(ctx, SpvOpFOrdGreaterThan, bool_type, src[0], cmp); - result = emit_triop(ctx, SpvOpSelect, dest_type, result, src[1], src[2]); - } + case nir_op_bcsel: + assert(nir_op_infos[alu->op].num_inputs == 3); + 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: @@ -955,13 +1118,40 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) 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]; + 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); + + 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); + 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); - SpvId constant = get_uvec_constant(ctx, load_const->def.bit_size, - load_const->def.num_components, - values); store_ssa_def_uint(ctx, &load_const->def, constant); } @@ -980,8 +1170,8 @@ emit_load_ubo(struct ntv_context *ctx, nir_intrinsic_instr *intr) uvec4_type); unsigned idx = const_offset->u32; - SpvId member = spirv_builder_const_uint(&ctx->builder, 32, 0); - SpvId offset = spirv_builder_const_uint(&ctx->builder, 32, idx); + SpvId member = emit_uint_const(ctx, 32, 0); + SpvId offset = emit_uint_const(ctx, 32, idx); SpvId offsets[] = { member, offset }; SpvId ptr = spirv_builder_emit_access_chain(&ctx->builder, pointer_type, ctx->ubos[0], offsets, @@ -1050,12 +1240,38 @@ emit_store_deref(struct ntv_context *ctx, nir_intrinsic_instr *intr) SpvId src = get_src_uint(ctx, &intr->src[1]); nir_variable *var = nir_intrinsic_get_var(intr, 0); - SpvId result = emit_unop(ctx, SpvOpBitcast, - get_glsl_type(ctx, glsl_without_array(var->type)), - src); + SpvId type = get_glsl_type(ctx, glsl_without_array(var->type)); + SpvId result = emit_bitcast(ctx, type, src); 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) { @@ -1076,6 +1292,10 @@ 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); @@ -1102,20 +1322,35 @@ get_src_float(struct ntv_context *ctx, nir_src *src) 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_txb || + 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; - 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; @@ -1133,10 +1368,29 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex) 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; + case nir_tex_src_comparator: + assert(nir_src_num_components(tex->src[i].src) == 1); + dref = get_src_float(ctx, &tex->src[i].src); + 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"); @@ -1144,7 +1398,7 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex) } if (lod == 0 && ctx->stage != MESA_SHADER_FRAGMENT) { - lod = spirv_builder_const_float(&ctx->builder, 32, 0); + lod = emit_float_const(ctx, 32, 0.0f); assert(lod != 0); } @@ -1165,12 +1419,17 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex) if (proj) { SpvId constituents[coord_components + 1]; - SpvId float_type = spirv_builder_type_float(&ctx->builder, 32); - for (uint32_t i = 0; i < coord_components; ++i) - constituents[i] = spirv_builder_emit_composite_extract(&ctx->builder, - float_type, - coord, - &i, 1); + if (coord_components == 1) + constituents[0] = coord; + else { + assert(coord_components > 1); + SpvId float_type = spirv_builder_type_float(&ctx->builder, 32); + for (uint32_t i = 0; i < coord_components; ++i) + constituents[i] = spirv_builder_emit_composite_extract(&ctx->builder, + float_type, + coord, + &i, 1); + } constituents[coord_components++] = proj; @@ -1181,14 +1440,34 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex) coord_components); } - SpvId result = spirv_builder_emit_image_sample(&ctx->builder, - dest_type, load, - coord, - proj != 0, - lod, bias); + SpvId actual_dest_type = dest_type; + if (dref) + actual_dest_type = float_type; + + 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); + if (dref) { + SpvId components[4] = { result, result, result, result }; + result = spirv_builder_emit_composite_construct(&ctx->builder, + dest_type, + components, + 4); + } + store_dest(ctx, &tex->dest, result, tex->dest_type); } @@ -1351,7 +1630,7 @@ static SpvId get_src_bool(struct ntv_context *ctx, nir_src *src) { SpvId def = get_src_uint(ctx, src); - assert(nir_src_bit_size(*src) == 32); + assert(nir_src_bit_size(*src) == 1); unsigned num_components = nir_src_num_components(*src); return uvec_to_bvec(ctx, def, num_components); } @@ -1524,9 +1803,6 @@ nir_to_spirv(struct nir_shader *s) 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); @@ -1584,6 +1860,10 @@ nir_to_spirv(struct nir_shader *s) 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);