static void
emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
{
- assert(tex->op == nir_texop_tex);
+ assert(tex->op == nir_texop_tex ||
+ tex->op == nir_texop_txb);
assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
assert(tex->texture_index == tex->sampler_index);
- bool has_proj = false, has_lod = false;
- SpvId coord = 0, proj, lod;
+ SpvId coord = 0, proj = 0, bias = 0, lod = 0;
unsigned coord_components;
for (unsigned i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
break;
case nir_tex_src_projector:
- has_proj = true;
- proj = get_src_float(ctx, &tex->src[i].src);
assert(nir_src_num_components(tex->src[i].src) == 1);
+ proj = get_src_float(ctx, &tex->src[i].src);
+ assert(proj != 0);
+ break;
+
+ case nir_tex_src_bias:
+ assert(tex->op == nir_texop_txb);
+ bias = get_src_float(ctx, &tex->src[i].src);
+ assert(bias != 0);
break;
case nir_tex_src_lod:
- has_lod = true;
- lod = get_src_float(ctx, &tex->src[i].src);
assert(nir_src_num_components(tex->src[i].src) == 1);
+ lod = get_src_float(ctx, &tex->src[i].src);
+ assert(lod != 0);
break;
default:
}
}
- if (!has_lod && ctx->stage != MESA_SHADER_FRAGMENT) {
- has_lod = true;
+ if (lod == 0 && ctx->stage != MESA_SHADER_FRAGMENT) {
lod = spirv_builder_const_float(&ctx->builder, 32, 0);
+ assert(lod != 0);
}
bool is_ms;
SpvId dest_type = get_dest_type(ctx, &tex->dest, tex->dest_type);
- SpvId result;
- if (has_proj) {
+ 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[coord_components++] = proj;
SpvId vec_type = get_fvec_type(ctx, 32, coord_components);
- SpvId merged = spirv_builder_emit_composite_construct(&ctx->builder,
+ coord = spirv_builder_emit_composite_construct(&ctx->builder,
vec_type,
constituents,
coord_components);
-
- if (has_lod)
- result = spirv_builder_emit_image_sample_proj_explicit_lod(&ctx->builder,
- dest_type,
- load,
- merged,
- lod);
- else
- result = spirv_builder_emit_image_sample_proj_implicit_lod(&ctx->builder,
- dest_type,
- load,
- merged);
- } else {
- if (has_lod)
- result = spirv_builder_emit_image_sample_explicit_lod(&ctx->builder,
- dest_type,
- load,
- coord, lod);
- else
- result = spirv_builder_emit_image_sample_implicit_lod(&ctx->builder,
- dest_type,
- load,
- coord);
}
+
+ SpvId result = spirv_builder_emit_image_sample(&ctx->builder,
+ dest_type, load,
+ coord,
+ proj != 0,
+ lod, bias);
spirv_builder_emit_decoration(&ctx->builder, result,
SpvDecorationRelaxedPrecision);
}
SpvId
-spirv_builder_emit_image_sample_implicit_lod(struct spirv_builder *b,
- SpvId result_type,
- SpvId sampled_image,
- SpvId coordinate)
+spirv_builder_emit_image_sample(struct spirv_builder *b,
+ SpvId result_type,
+ SpvId sampled_image,
+ SpvId coordinate,
+ bool proj,
+ SpvId lod,
+ SpvId bias)
{
SpvId result = spirv_builder_new_id(b);
- spirv_buffer_prepare(&b->instructions, 5);
- spirv_buffer_emit_word(&b->instructions, SpvOpImageSampleImplicitLod | (5 << 16));
- spirv_buffer_emit_word(&b->instructions, result_type);
- spirv_buffer_emit_word(&b->instructions, result);
- spirv_buffer_emit_word(&b->instructions, sampled_image);
- spirv_buffer_emit_word(&b->instructions, coordinate);
- return result;
-}
-SpvId
-spirv_builder_emit_image_sample_explicit_lod(struct spirv_builder *b,
- SpvId result_type,
- SpvId sampled_image,
- SpvId coordinate,
- SpvId lod)
-{
- SpvId result = spirv_builder_new_id(b);
- spirv_buffer_prepare(&b->instructions, 7);
- spirv_buffer_emit_word(&b->instructions, SpvOpImageSampleExplicitLod | (7 << 16));
- spirv_buffer_emit_word(&b->instructions, result_type);
- spirv_buffer_emit_word(&b->instructions, result);
- spirv_buffer_emit_word(&b->instructions, sampled_image);
- spirv_buffer_emit_word(&b->instructions, coordinate);
- spirv_buffer_emit_word(&b->instructions, SpvImageOperandsLodMask);
- spirv_buffer_emit_word(&b->instructions, lod);
- return result;
-}
+ int opcode = SpvOpImageSampleImplicitLod;
+ if (proj)
+ opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
+ if (lod)
+ opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
+
+ SpvImageOperandsMask operand_mask = 0;
+ SpvId extra_operands[3];
+ int num_extra_operands = SpvImageOperandsMaskNone;
+ if (bias) {
+ extra_operands[++num_extra_operands] = bias;
+ operand_mask |= SpvImageOperandsBiasMask;
+ }
+ if (lod) {
+ extra_operands[++num_extra_operands] = lod;
+ operand_mask |= SpvImageOperandsLodMask;
+ }
-SpvId
-spirv_builder_emit_image_sample_proj_implicit_lod(struct spirv_builder *b,
- SpvId result_type,
- SpvId sampled_image,
- SpvId coordinate)
-{
- SpvId result = spirv_builder_new_id(b);
- spirv_buffer_prepare(&b->instructions, 5);
- spirv_buffer_emit_word(&b->instructions, SpvOpImageSampleProjImplicitLod | (5 << 16));
- spirv_buffer_emit_word(&b->instructions, result_type);
- spirv_buffer_emit_word(&b->instructions, result);
- spirv_buffer_emit_word(&b->instructions, sampled_image);
- spirv_buffer_emit_word(&b->instructions, coordinate);
- return result;
-}
+ /* finalize num_extra_operands / extra_operands */
+ if (num_extra_operands > 0) {
+ extra_operands[0] = operand_mask;
+ num_extra_operands++;
+ }
-SpvId
-spirv_builder_emit_image_sample_proj_explicit_lod(struct spirv_builder *b,
- SpvId result_type,
- SpvId sampled_image,
- SpvId coordinate,
- SpvId lod)
-{
- SpvId result = spirv_builder_new_id(b);
- spirv_buffer_prepare(&b->instructions, 7);
- spirv_buffer_emit_word(&b->instructions, SpvOpImageSampleProjExplicitLod | (7 << 16));
+ spirv_buffer_prepare(&b->instructions, 5 + num_extra_operands);
+ spirv_buffer_emit_word(&b->instructions, opcode | ((5 + num_extra_operands) << 16));
spirv_buffer_emit_word(&b->instructions, result_type);
spirv_buffer_emit_word(&b->instructions, result);
spirv_buffer_emit_word(&b->instructions, sampled_image);
spirv_buffer_emit_word(&b->instructions, coordinate);
- spirv_buffer_emit_word(&b->instructions, SpvImageOperandsLodMask);
- spirv_buffer_emit_word(&b->instructions, lod);
+ for (int i = 0; i < num_extra_operands; ++i)
+ spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
return result;
}