#include "glsl/ir.h"
#include "glsl/ir_builder.h"
#include "program/prog_instruction.h"
+#include "brw_context.h"
using namespace ir_builder;
class lower_texture_grad_visitor : public ir_hierarchical_visitor {
public:
- lower_texture_grad_visitor()
+ lower_texture_grad_visitor(bool has_sample_d_c)
+ : has_sample_d_c(has_sample_d_c)
{
progress = false;
}
bool progress;
+ bool has_sample_d_c;
private:
void emit(ir_variable *, ir_rvalue *);
dims = 3;
break;
default:
- assert(!"Should not get here: invalid sampler dimensionality");
- dims = 2;
+ unreachable("Should not get here: invalid sampler dimensionality");
}
if (type->sampler_array)
ir_visitor_status
lower_texture_grad_visitor::visit_leave(ir_texture *ir)
{
- /* Only lower textureGrad with shadow samplers */
- if (ir->op != ir_txd || !ir->shadow_comparitor)
+ /* Only lower textureGrad with cube maps or shadow samplers */
+ if (ir->op != ir_txd ||
+ (ir->sampler->type->sampler_dimensionality != GLSL_SAMPLER_DIM_CUBE &&
+ !ir->shadow_comparitor))
+ return visit_continue;
+
+ /* Lower textureGrad() with samplerCube* even if we have the sample_d_c
+ * message. GLSL provides gradients for the 'r' coordinate. Unfortunately:
+ *
+ * From the Ivybridge PRM, Volume 4, Part 1, sample_d message description:
+ * "The r coordinate contains the faceid, and the r gradients are ignored
+ * by hardware."
+ */
+ bool need_lowering = !has_sample_d_c ||
+ ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE;
+
+ if (!need_lowering)
return visit_continue;
void *mem_ctx = ralloc_parent(ir);
new(mem_ctx) ir_variable(grad_type, "size", ir_var_temporary);
if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
base_ir->insert_before(size);
- base_ir->insert_before(assign(size, expr(ir_unop_i2f, txs), WRITEMASK_XY));
+ base_ir->insert_before(assign(size,
+ swizzle_for_size(expr(ir_unop_i2f, txs), 2),
+ WRITEMASK_XY));
base_ir->insert_before(assign(size, new(mem_ctx) ir_constant(1.0f), WRITEMASK_Z));
} else {
emit(size, expr(ir_unop_i2f,
expr(ir_unop_sqrt, dot(dPdy, dPdy)));
}
- /* lambda_base = log2(rho). We're ignoring GL state biases for now. */
+ /* lambda_base = log2(rho). We're ignoring GL state biases for now.
+ *
+ * For cube maps the result of these formulas is giving us a value of rho
+ * that is twice the value we should use, so divide it by 2 or,
+ * alternatively, remove one unit from the result of the log2 computation.
+ */
ir->op = ir_txl;
- ir->lod_info.lod = expr(ir_unop_log2, rho);
+ if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
+ ir->lod_info.lod = expr(ir_binop_add,
+ expr(ir_unop_log2, rho),
+ new(mem_ctx) ir_constant(-1.0f));
+ } else {
+ ir->lod_info.lod = expr(ir_unop_log2, rho);
+ }
progress = true;
return visit_continue;
extern "C" {
bool
-brw_lower_texture_gradients(struct exec_list *instructions)
+brw_lower_texture_gradients(struct brw_context *brw,
+ struct exec_list *instructions)
{
- lower_texture_grad_visitor v;
+ bool has_sample_d_c = brw->gen >= 8 || brw->is_haswell;
+ lower_texture_grad_visitor v(has_sample_d_c);
visit_list_elements(&v, instructions);