2015-02-06 01:11:18 +02:00
|
|
|
/* -*- c++ -*- */
|
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2010-2015 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef BRW_IR_FS_H
|
|
|
|
|
#define BRW_IR_FS_H
|
|
|
|
|
|
|
|
|
|
#include "brw_shader.h"
|
|
|
|
|
|
|
|
|
|
class fs_inst;
|
|
|
|
|
|
|
|
|
|
class fs_reg : public backend_reg {
|
|
|
|
|
public:
|
|
|
|
|
DECLARE_RALLOC_CXX_OPERATORS(fs_reg)
|
|
|
|
|
|
|
|
|
|
void init();
|
|
|
|
|
|
|
|
|
|
fs_reg();
|
|
|
|
|
explicit fs_reg(float f);
|
|
|
|
|
explicit fs_reg(int32_t i);
|
|
|
|
|
explicit fs_reg(uint32_t u);
|
|
|
|
|
explicit fs_reg(uint8_t vf[4]);
|
|
|
|
|
explicit fs_reg(uint8_t vf0, uint8_t vf1, uint8_t vf2, uint8_t vf3);
|
2015-10-24 15:29:03 -07:00
|
|
|
fs_reg(struct brw_reg reg);
|
2015-10-26 04:35:14 -07:00
|
|
|
fs_reg(enum register_file file, int nr);
|
|
|
|
|
fs_reg(enum register_file file, int nr, enum brw_reg_type type);
|
2015-02-06 01:11:18 +02:00
|
|
|
|
|
|
|
|
bool equals(const fs_reg &r) const;
|
|
|
|
|
bool is_contiguous() const;
|
|
|
|
|
|
2015-07-14 15:43:44 +03:00
|
|
|
/**
|
|
|
|
|
* Return the size in bytes of a single logical component of the
|
|
|
|
|
* register assuming the given execution width.
|
|
|
|
|
*/
|
|
|
|
|
unsigned component_size(unsigned width) const;
|
|
|
|
|
|
2015-02-06 01:11:18 +02:00
|
|
|
/** Smear a channel of the reg to all channels. */
|
|
|
|
|
fs_reg &set_smear(unsigned subreg);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Offset in bytes from the start of the register. Values up to a
|
|
|
|
|
* backend_reg::reg_offset unit are valid.
|
|
|
|
|
*/
|
|
|
|
|
int subreg_offset;
|
|
|
|
|
|
|
|
|
|
fs_reg *reladdr;
|
|
|
|
|
|
|
|
|
|
/** Register region horizontal stride */
|
|
|
|
|
uint8_t stride;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline fs_reg
|
|
|
|
|
negate(fs_reg reg)
|
|
|
|
|
{
|
2015-10-24 14:35:33 -07:00
|
|
|
assert(reg.file != IMM);
|
2015-02-06 01:11:18 +02:00
|
|
|
reg.negate = !reg.negate;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline fs_reg
|
|
|
|
|
retype(fs_reg reg, enum brw_reg_type type)
|
|
|
|
|
{
|
2015-10-24 15:29:03 -07:00
|
|
|
reg.type = type;
|
2015-02-06 01:11:18 +02:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline fs_reg
|
|
|
|
|
byte_offset(fs_reg reg, unsigned delta)
|
|
|
|
|
{
|
|
|
|
|
switch (reg.file) {
|
|
|
|
|
case BAD_FILE:
|
|
|
|
|
break;
|
2015-10-26 17:09:25 -07:00
|
|
|
case VGRF:
|
2015-02-06 01:11:18 +02:00
|
|
|
case ATTR:
|
|
|
|
|
reg.reg_offset += delta / 32;
|
|
|
|
|
break;
|
|
|
|
|
case MRF:
|
2015-10-26 04:35:14 -07:00
|
|
|
reg.nr += delta / 32;
|
2015-02-06 01:11:18 +02:00
|
|
|
break;
|
2015-10-26 06:58:56 -07:00
|
|
|
case IMM:
|
|
|
|
|
case HW_REG:
|
|
|
|
|
case UNIFORM:
|
2015-02-06 01:11:18 +02:00
|
|
|
assert(delta == 0);
|
|
|
|
|
}
|
|
|
|
|
reg.subreg_offset += delta % 32;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline fs_reg
|
|
|
|
|
horiz_offset(fs_reg reg, unsigned delta)
|
|
|
|
|
{
|
|
|
|
|
switch (reg.file) {
|
|
|
|
|
case BAD_FILE:
|
|
|
|
|
case UNIFORM:
|
|
|
|
|
case IMM:
|
|
|
|
|
/* These only have a single component that is implicitly splatted. A
|
|
|
|
|
* horizontal offset should be a harmless no-op.
|
|
|
|
|
*/
|
|
|
|
|
break;
|
2015-10-26 17:09:25 -07:00
|
|
|
case VGRF:
|
2015-02-06 01:11:18 +02:00
|
|
|
case MRF:
|
|
|
|
|
case ATTR:
|
|
|
|
|
return byte_offset(reg, delta * reg.stride * type_sz(reg.type));
|
2015-10-26 06:58:56 -07:00
|
|
|
case HW_REG:
|
2015-02-06 01:11:18 +02:00
|
|
|
assert(delta == 0);
|
|
|
|
|
}
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline fs_reg
|
|
|
|
|
component(fs_reg reg, unsigned idx)
|
|
|
|
|
{
|
|
|
|
|
assert(reg.subreg_offset == 0);
|
|
|
|
|
reg.subreg_offset = idx * type_sz(reg.type);
|
2015-04-30 19:29:54 +03:00
|
|
|
reg.stride = 0;
|
2015-02-06 01:11:18 +02:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-19 14:52:24 +02:00
|
|
|
static inline bool
|
|
|
|
|
is_uniform(const fs_reg ®)
|
|
|
|
|
{
|
2015-06-18 12:44:35 -07:00
|
|
|
return (reg.stride == 0 || reg.is_null()) &&
|
2015-02-19 14:52:24 +02:00
|
|
|
(!reg.reladdr || is_uniform(*reg.reladdr));
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 01:11:18 +02:00
|
|
|
/**
|
|
|
|
|
* Get either of the 8-component halves of a 16-component register.
|
|
|
|
|
*
|
|
|
|
|
* Note: this also works if \c reg represents a SIMD16 pair of registers.
|
|
|
|
|
*/
|
|
|
|
|
static inline fs_reg
|
|
|
|
|
half(fs_reg reg, unsigned idx)
|
|
|
|
|
{
|
|
|
|
|
assert(idx < 2);
|
|
|
|
|
|
2015-05-05 15:57:11 -07:00
|
|
|
switch (reg.file) {
|
|
|
|
|
case BAD_FILE:
|
|
|
|
|
case UNIFORM:
|
|
|
|
|
case IMM:
|
2015-02-06 01:11:18 +02:00
|
|
|
return reg;
|
|
|
|
|
|
2015-10-26 17:09:25 -07:00
|
|
|
case VGRF:
|
2015-05-05 15:57:11 -07:00
|
|
|
case MRF:
|
|
|
|
|
return horiz_offset(reg, 8 * idx);
|
|
|
|
|
|
|
|
|
|
case ATTR:
|
|
|
|
|
case HW_REG:
|
|
|
|
|
unreachable("Cannot take half of this register type");
|
|
|
|
|
}
|
|
|
|
|
return reg;
|
2015-02-06 01:11:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const fs_reg reg_undef;
|
|
|
|
|
|
|
|
|
|
class fs_inst : public backend_instruction {
|
|
|
|
|
fs_inst &operator=(const fs_inst &);
|
|
|
|
|
|
|
|
|
|
void init(enum opcode opcode, uint8_t exec_width, const fs_reg &dst,
|
2015-02-06 01:14:51 +02:00
|
|
|
const fs_reg *src, unsigned sources);
|
2015-02-06 01:11:18 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
DECLARE_RALLOC_CXX_OPERATORS(fs_inst)
|
|
|
|
|
|
|
|
|
|
fs_inst();
|
|
|
|
|
fs_inst(enum opcode opcode, uint8_t exec_size);
|
2015-06-18 12:30:43 -07:00
|
|
|
fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst);
|
2015-02-06 01:11:18 +02:00
|
|
|
fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
|
|
|
|
|
const fs_reg &src0);
|
|
|
|
|
fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
|
|
|
|
|
const fs_reg &src0, const fs_reg &src1);
|
|
|
|
|
fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
|
|
|
|
|
const fs_reg &src0, const fs_reg &src1, const fs_reg &src2);
|
|
|
|
|
fs_inst(enum opcode opcode, uint8_t exec_size, const fs_reg &dst,
|
2015-02-06 01:14:51 +02:00
|
|
|
const fs_reg src[], unsigned sources);
|
2015-02-06 01:11:18 +02:00
|
|
|
fs_inst(const fs_inst &that);
|
2015-02-06 01:14:51 +02:00
|
|
|
~fs_inst();
|
2015-02-06 01:11:18 +02:00
|
|
|
|
|
|
|
|
void resize_sources(uint8_t num_sources);
|
|
|
|
|
|
|
|
|
|
bool equals(fs_inst *inst) const;
|
|
|
|
|
bool overwrites_reg(const fs_reg ®) const;
|
|
|
|
|
bool is_send_from_grf() const;
|
|
|
|
|
bool is_partial_write() const;
|
2015-04-01 15:38:23 -07:00
|
|
|
bool is_copy_payload(const brw::simple_allocator &grf_alloc) const;
|
2015-07-21 17:28:39 +03:00
|
|
|
unsigned components_read(unsigned i) const;
|
2015-02-06 01:24:17 +02:00
|
|
|
int regs_read(int arg) const;
|
2015-04-15 18:00:05 -07:00
|
|
|
bool can_do_source_mods(const struct brw_device_info *devinfo);
|
2015-10-14 02:12:09 -07:00
|
|
|
bool can_change_types() const;
|
2015-03-31 15:49:42 -07:00
|
|
|
bool has_side_effects() const;
|
2015-02-06 01:11:18 +02:00
|
|
|
|
|
|
|
|
bool reads_flag() const;
|
|
|
|
|
bool writes_flag() const;
|
|
|
|
|
|
|
|
|
|
fs_reg dst;
|
|
|
|
|
fs_reg *src;
|
|
|
|
|
|
|
|
|
|
uint8_t sources; /**< Number of fs_reg sources. */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Execution size of the instruction. This is used by the generator to
|
|
|
|
|
* generate the correct binary for the given fs_inst. Current valid
|
|
|
|
|
* values are 1, 8, 16.
|
|
|
|
|
*/
|
|
|
|
|
uint8_t exec_size;
|
|
|
|
|
|
|
|
|
|
bool eot:1;
|
|
|
|
|
bool force_sechalf:1;
|
|
|
|
|
bool pi_noperspective:1; /**< Pixel interpolator noperspective flag */
|
|
|
|
|
};
|
|
|
|
|
|
2015-05-12 15:51:05 -07:00
|
|
|
/**
|
|
|
|
|
* Set second-half quarter control on \p inst.
|
|
|
|
|
*/
|
|
|
|
|
static inline fs_inst *
|
|
|
|
|
set_sechalf(fs_inst *inst)
|
|
|
|
|
{
|
|
|
|
|
inst->force_sechalf = true;
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-03 21:23:46 +03:00
|
|
|
/**
|
|
|
|
|
* Make the execution of \p inst dependent on the evaluation of a possibly
|
|
|
|
|
* inverted predicate.
|
|
|
|
|
*/
|
|
|
|
|
static inline fs_inst *
|
|
|
|
|
set_predicate_inv(enum brw_predicate pred, bool inverse,
|
|
|
|
|
fs_inst *inst)
|
|
|
|
|
{
|
|
|
|
|
inst->predicate = pred;
|
|
|
|
|
inst->predicate_inverse = inverse;
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Make the execution of \p inst dependent on the evaluation of a predicate.
|
|
|
|
|
*/
|
|
|
|
|
static inline fs_inst *
|
|
|
|
|
set_predicate(enum brw_predicate pred, fs_inst *inst)
|
|
|
|
|
{
|
|
|
|
|
return set_predicate_inv(pred, false, inst);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-03 21:24:18 +03:00
|
|
|
/**
|
|
|
|
|
* Write the result of evaluating the condition given by \p mod to a flag
|
|
|
|
|
* register.
|
|
|
|
|
*/
|
|
|
|
|
static inline fs_inst *
|
|
|
|
|
set_condmod(enum brw_conditional_mod mod, fs_inst *inst)
|
|
|
|
|
{
|
|
|
|
|
inst->conditional_mod = mod;
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-03 21:24:50 +03:00
|
|
|
/**
|
|
|
|
|
* Clamp the result of \p inst to the saturation range of its destination
|
|
|
|
|
* datatype.
|
|
|
|
|
*/
|
|
|
|
|
static inline fs_inst *
|
|
|
|
|
set_saturate(bool saturate, fs_inst *inst)
|
|
|
|
|
{
|
|
|
|
|
inst->saturate = saturate;
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 01:11:18 +02:00
|
|
|
#endif
|