[Mesa-dev] [PATCH 2/6] i965/vec4/generator: use 1-Oword Block Read/Write messages for DF scratch writes/reads
Francisco Jerez
currojerez at riseup.net
Mon Jun 26 17:38:46 UTC 2017
Samuel Iglesias Gonsálvez <siglesias at igalia.com> writes:
> On Fri, 2017-06-23 at 11:06 -0700, Francisco Jerez wrote:
>> Samuel Iglesias Gonsálvez <siglesias at igalia.com> writes:
>>
>> > On Thu, 2017-06-22 at 16:25 -0700, Francisco Jerez wrote:
>> > > Samuel Iglesias Gonsálvez <siglesias at igalia.com> writes:
>> > >
>> > > > Signed-off-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
>> > > > ---
>> > > > src/intel/compiler/brw_eu_defines.h | 2 +
>> > > > src/intel/compiler/brw_shader.cpp | 5 +
>> > > > src/intel/compiler/brw_vec4.cpp | 7 ++
>> > > > src/intel/compiler/brw_vec4.h | 8 ++
>> > > > src/intel/compiler/brw_vec4_generator.cpp | 136
>> > > > +++++++++++++++++++++++++++
>> > > > src/intel/compiler/brw_vec4_reg_allocate.cpp | 6 +-
>> > > > src/intel/compiler/brw_vec4_visitor.cpp | 49 ++++++++++
>> > > > 7 files changed, 212 insertions(+), 1 deletion(-)
>> > > >
>> > > > diff --git a/src/intel/compiler/brw_eu_defines.h
>> > > > b/src/intel/compiler/brw_eu_defines.h
>> > > > index 1af835d47e..3c148de0fa 100644
>> > > > --- a/src/intel/compiler/brw_eu_defines.h
>> > > > +++ b/src/intel/compiler/brw_eu_defines.h
>> > > > @@ -436,6 +436,8 @@ enum opcode {
>> > > > VEC4_OPCODE_PICK_HIGH_32BIT,
>> > > > VEC4_OPCODE_SET_LOW_32BIT,
>> > > > VEC4_OPCODE_SET_HIGH_32BIT,
>> > > > + VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW,
>> > > > + VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH,
>> > > >
>> > >
>> > > What's the point of introducing two different opcodes with
>> > > essentially
>> > > the same semantics (read 32B worth of data) as the current
>> > > SHADER_OPCODE_GEN4_SCRATCH_READ?
>> >
>> > Originally I had only SHADER_OPCODE_GEN4_SCRATCH_READ but I changed
>> > it
>> > to don't allocate more registers than needed when doing scratch
>> > write
>> > of a partial DF write. Let me explain it:
>> >
>> > When doing spilling, as DF instructions are both split and
>> > scalarized,
>> > we read the existing contents in scratch memory, overwrite them
>> > with
>> > the destination of the instruction, then emit scratch write.
>> > Together
>> > with the fact that I am not shuffling DF data, we only need to
>> > allocate
>> > 1 GRF to do so, instead of 2 (if I had emitted
>> > SHADER_OPCODE_GEN4_SCRATCH_READ), when doing spilling on partial DF
>> > writes.
>> >
>>
>> Why would you need to allocate more GRFs for
>> SHADER_OPCODE_GEN4_SCRATCH_READ? It also only reads one register,
>> which
>> should be sufficient for a single scalarized instruction as long as
>> you
>> don't shuffle data around -- Have a look at how the FS back-end
>> addresses this problem.
>>
>
> OK
>
>> > > Is there any downside from using the
>> > > current opcode with force_writemask_all? If anything it would
>> > > give
>> > > you
>> > > better performance because you'd only have to set up one header
>> > > (which
>> > > stalls the EU pipeline twice), send down one message to the
>> > > dataport,
>> > > and avoid stalling to shuffle the data around in the return
>> > > payload
>> > > (which prevents your two 1OWORD messages from being pipelined at
>> > > all).
>> > >
>> >
>> > Sorry, I am confused here. Do you mean using
>> > SHADER_OPCODE_GEN4_SCRATCH_READ as-is, which emits a "OWord Dual
>> > Block
>> > Read" message (so only one message)?
>> >
>> > If that's the case, then I should shuffle the destination data of
>> > the
>> > partial DF write, change the 1-Oword block write offsets and so
>> > on...
>>
>> Why would you need to shuffle any spilled data? I don't think
>> there's
>> much of a benefit from shuffling since scratch overwrites need read
>> the
>> original data for the most part anyway because of writemasking. In
>> fact
>> shuffling DF data is probably the reason things blow up right now
>> whenever you have mixed DF and single-precision reads or writes to
>> the
>> same spilled variable, which I guess is the reason you need to look
>> for
>> those cases and mark them as no_spill...
>>
>
> Right, I don't need to shuffle data for the scratch write.
>
>> > in order to save it inside scratch memory in the proper place to
>> > make
>> > OWord Dual Block Read work. That would require to some extra
>> > instructions, but I don't know if this would give better
>> > performance
>> > against current implementation or not.
>> >
>>
>> I expect the most serious performance issue with the approach of this
>> patch will be the sequence of non-pipelined single-oword reads, which
>> means you get to pay for the EU-dataport roundtrip latency twice
>> instead
>> of once.
>>
>> > Then, why do I need force_writemask=true when emitting
>> > SHADER_OPCODE_GEN4_SCRATCH_READ?
>> >
>>
>> Because you probably don't want to shuffle data in your scratch
>> buffer,
>> and you don't want the dataport to apply bogus 16B channel enables to
>> your reads and writes.
>>
>
> If we save the dvec4 data of a vertex altogether in consecutive 32
> bytes in scratch memory (i.e. no need of shuffling and we use
> force_writemask_all as you said), then we need to create a special case
> for IVB and partial DFs reads on HSW+ when unspilling the data.
>
> What I am thinking now is if the scratch write is done wisely, we can
> write the data in the proper places for the two
> SHADER_OPCODE_GEN4_SCRATCH_READ we use for unspill DF data: write each
> XY components with the respective 1-OWord scratch write message and ZW
> components with other 1-OWord scratch write messages with an offset of
> 32 bytes. Thanks to this, we don't need to touch the current code for
> unspilling (which does data shuffling) and it allows us to do
> unspilling on IVB and partial DF reads on HSW+ without any special
> case.
>
> If we choose the no-shuffling-at-all solution, this is an improvement
> to what I have sent in this v1, but I am leaning toward the solution in
> last paragraph because it re-uses existing code and simplifies the
> changes, although we have some data shuffling overhead.
>
> What do you think?
>
Cannot we just drop the shuffling on HSW+ too? AFAIA it has the same
drawbacks on HSW+ as it has on IVB, so I don't see any reason for
supporting both codepaths.
> Sam
>
>
>> > I can try this alternative solution if this is what you meant. It
>> > has
>> > the advantage of simplifying the changes a lot, which is always
>> > great.
>> >
>> > Sam
>> >
>> > > > FS_OPCODE_DDX_COARSE,
>> > > > FS_OPCODE_DDX_FINE,
>> > > > diff --git a/src/intel/compiler/brw_shader.cpp
>> > > > b/src/intel/compiler/brw_shader.cpp
>> > > > index 53d0742d2e..248feacbd2 100644
>> > > > --- a/src/intel/compiler/brw_shader.cpp
>> > > > +++ b/src/intel/compiler/brw_shader.cpp
>> > > > @@ -296,6 +296,11 @@ brw_instruction_name(const struct
>> > > > gen_device_info *devinfo, enum opcode op)
>> > > > case FS_OPCODE_PACK:
>> > > > return "pack";
>> > > >
>> > > > +
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW:
>> > > > + return "gen4_scratch_read_1word_low";
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH:
>> > > > + return "gen4_scratch_read_1word_high";
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_READ:
>> > > > return "gen4_scratch_read";
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
>> > > > diff --git a/src/intel/compiler/brw_vec4.cpp
>> > > > b/src/intel/compiler/brw_vec4.cpp
>> > > > index b443effca9..b6d409eea2 100644
>> > > > --- a/src/intel/compiler/brw_vec4.cpp
>> > > > +++ b/src/intel/compiler/brw_vec4.cpp
>> > > > @@ -259,6 +259,8 @@ bool
>> > > > vec4_instruction::can_do_writemask(const struct
>> > > > gen_device_info
>> > > > *devinfo)
>> > > > {
>> > > > switch (opcode) {
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW:
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH:
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_READ:
>> > > > case VEC4_OPCODE_DOUBLE_TO_F32:
>> > > > case VEC4_OPCODE_DOUBLE_TO_D32:
>> > > > @@ -335,6 +337,9 @@
>> > > > vec4_visitor::implied_mrf_writes(vec4_instruction *inst)
>> > > > return 1;
>> > > > case VS_OPCODE_PULL_CONSTANT_LOAD:
>> > > > return 2;
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW:
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH:
>> > > > + return 1;
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_READ:
>> > > > return 2;
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
>> > > > @@ -2091,6 +2096,8 @@ get_lowered_simd_width(const struct
>> > > > gen_device_info *devinfo,
>> > > > {
>> > > > /* Do not split some instructions that require special
>> > > > handling
>> > > > */
>> > > > switch (inst->opcode) {
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW:
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH:
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_READ:
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
>> > > > return inst->exec_size;
>> > > > diff --git a/src/intel/compiler/brw_vec4.h
>> > > > b/src/intel/compiler/brw_vec4.h
>> > > > index d828da02ea..a5b45aca21 100644
>> > > > --- a/src/intel/compiler/brw_vec4.h
>> > > > +++ b/src/intel/compiler/brw_vec4.h
>> > > > @@ -214,6 +214,9 @@ public:
>> > > > enum brw_conditional_mod condition);
>> > > > vec4_instruction *IF(enum brw_predicate predicate);
>> > > > EMIT1(SCRATCH_READ)
>> > > > + vec4_instruction *DF_IVB_SCRATCH_READ(const dst_reg &dst,
>> > > > const
>> > > > src_reg &src0,
>> > > > + bool low);
>> > > > +
>> > > > EMIT2(SCRATCH_WRITE)
>> > > > EMIT3(LRP)
>> > > > EMIT1(BFREV)
>> > > > @@ -294,6 +297,11 @@ public:
>> > > > dst_reg dst,
>> > > > src_reg orig_src,
>> > > > int base_offset);
>> > > > + void emit_1grf_df_ivb_scratch_read(bblock_t *block,
>> > > > + vec4_instruction *inst,
>> > > > + dst_reg temp, src_reg
>> > > > orig_src,
>> > > > + int base_offset, bool
>> > > > first_grf);
>> > > > +
>> > > > void emit_scratch_write(bblock_t *block, vec4_instruction
>> > > > *inst,
>> > > > int base_offset);
>> > > > void emit_pull_constant_load(bblock_t *block,
>> > > > vec4_instruction
>> > > > *inst,
>> > > > diff --git a/src/intel/compiler/brw_vec4_generator.cpp
>> > > > b/src/intel/compiler/brw_vec4_generator.cpp
>> > > > index 334933d15a..3bb931385a 100644
>> > > > --- a/src/intel/compiler/brw_vec4_generator.cpp
>> > > > +++ b/src/intel/compiler/brw_vec4_generator.cpp
>> > > > @@ -1133,6 +1133,73 @@ generate_unpack_flags(struct brw_codegen
>> > > > *p,
>> > > > }
>> > > >
>> > > > static void
>> > > > +generate_scratch_read_1oword(struct brw_codegen *p,
>> > > > + vec4_instruction *inst,
>> > > > + struct brw_reg dst,
>> > > > + struct brw_reg index,
>> > > > + bool low)
>> > > > +{
>> > > > + const struct gen_device_info *devinfo = p->devinfo;
>> > > > +
>> > > > + assert(devinfo->gen >= 7 && inst->exec_size == 4 &&
>> > > > + type_sz(dst.type) == 8);
>> > > > + brw_set_default_access_mode(p, BRW_ALIGN_1);
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_8);
>> > > > +
>> > > > + if (!low) {
>> > > > + /* Read second GRF (offset in OWORDs) */
>> > > > + for (int i = 0; i < 2; i++) {
>> > > > + brw_oword_block_read_scratch(p,
>> > > > + dst,
>> > > > + brw_message_reg(inst-
>> > > > > base_mrf),
>> > > >
>> > > > + 1, 32*inst->offset +
>> > > > 16*i +
>> > > > 32, false, true);
>> > > > + if (i == 0) {
>> > > > + /* The scratch read message writes the 128 MSB
>> > > > (OWORD1
>> > > > HIGH) of
>> > > > + * the destination. We need to move them to dst.0
>> > > > so
>> > > > we can
>> > > > + * read the pending 128 bits without using a
>> > > > temporary
>> > > > register.
>> > > > + */
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_4);
>> > > > + struct brw_reg tmp =
>> > > > + stride(suboffset(dst, 16 / type_sz(dst.type)),
>> > > > + 4, 4, 1);
>> > > > +
>> > > > + brw_set_default_mask_control(p, true);
>> > > > + brw_MOV(p, dst, tmp);
>> > > > + brw_set_default_mask_control(p, inst-
>> > > > > force_writemask_all);
>> > > >
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_8);
>> > > > + }
>> > > > + }
>> > > > + } else {
>> > > > + /* Read first GRF (offset in OWORDs) */
>> > > > + for (int i = 1; i >= 0; i--) {
>> > > > + brw_oword_block_read_scratch(p,
>> > > > + dst,
>> > > > + brw_message_reg(inst-
>> > > > > base_mrf),
>> > > >
>> > > > + 1, 32*inst->offset +
>> > > > 16*i,
>> > > > true, false);
>> > > > +
>> > > > + if (i == 1) {
>> > > > + /* The scratch read message writes the 128 LSB
>> > > > (OWORD1
>> > > > LOW) of
>> > > > + * the destination. We need to move them to dst.4
>> > > > so
>> > > > we can
>> > > > + * read the pending 128 bits without using a
>> > > > temporary
>> > > > register.
>> > > > + */
>> > > > + struct brw_reg tmp = stride(dst, 4, 4, 1);
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_4);
>> > > > + brw_set_default_mask_control(p, true);
>> > > > + brw_MOV(p,
>> > > > + suboffset(dst, 16 / type_sz(dst.type)),
>> > > > + tmp);
>> > > > + brw_set_default_mask_control(p, inst-
>> > > > > force_writemask_all);
>> > > >
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_8);
>> > > > + }
>> > > > + }
>> > > > + }
>> > > > +
>> > > > + brw_set_default_exec_size(p, cvt(inst->exec_size) - 1);
>> > > > + brw_set_default_access_mode(p, BRW_ALIGN_16);
>> > > > + return;
>> > > > +}
>> > > > +
>> > > > +static void
>> > > > generate_scratch_read(struct brw_codegen *p,
>> > > > vec4_instruction *inst,
>> > > > struct brw_reg dst,
>> > > > @@ -1143,6 +1210,16 @@ generate_scratch_read(struct brw_codegen
>> > > > *p,
>> > > >
>> > > > gen6_resolve_implied_move(p, &header, inst->base_mrf);
>> > > >
>> > > > + if (devinfo->gen >= 7 && inst->exec_size == 4 &&
>> > > > + type_sz(dst.type) == 8) {
>> > > > + /* First read second GRF (offset in OWORDs) */
>> > > > + struct brw_reg dst_high = suboffset(dst, 32 /
>> > > > type_sz(dst.type));
>> > > > + generate_scratch_read_1oword(p, inst, dst_high, index,
>> > > > false);
>> > > > + /* Now read first GRF (data from first vertex) */
>> > > > + generate_scratch_read_1oword(p, inst, dst, index, true);
>> > > > + return;
>> > > > + }
>> > > > +
>> > > > generate_oword_dual_block_offsets(p, brw_message_reg(inst-
>> > > > > base_mrf + 1),
>> > > >
>> > > > index);
>> > > >
>> > > > @@ -1192,6 +1269,57 @@ generate_scratch_write(struct
>> > > > brw_codegen
>> > > > *p,
>> > > > struct brw_reg header = brw_vec8_grf(0, 0);
>> > > > bool write_commit;
>> > > >
>> > > > + if (devinfo->gen >= 7 && inst->exec_size == 4 &&
>> > > > + type_sz(src.type) == 8) {
>> > > > + brw_set_default_access_mode(p, BRW_ALIGN_1);
>> > > > +
>> > > > + /* The messages only works with group == 0, we use the
>> > > > group
>> > > > to know which
>> > > > + * message emit (1-OWORD LOW or 1-OWORD HIGH).
>> > > > + */
>> > > > + brw_set_default_group(p, 0);
>> > > > +
>> > > > + if (inst->group == 0) {
>> > > > + for (int i = 0; i < 2; i++) {
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_4);
>> > > > + brw_set_default_mask_control(p, true);
>> > > > + struct brw_reg temp =
>> > > > + retype(suboffset(src, i * 16 /
>> > > > type_sz(src.type)),
>> > > > BRW_REGISTER_TYPE_UD);
>> > > > + temp = stride(temp, 4, 4, 1);
>> > > > +
>> > > > + brw_MOV(p, brw_uvec_mrf(4, inst->base_mrf + 1, 0),
>> > > > + temp);
>> > > > + brw_set_default_mask_control(p, inst-
>> > > > > force_writemask_all);
>> > > >
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_8);
>> > > > +
>> > > > + /* Offset in OWORDs */
>> > > > + brw_oword_block_write_scratch(p,
>> > > > brw_message_reg(inst-
>> > > > > base_mrf),
>> > > >
>> > > > + 1, 32*inst->offset +
>> > > > 16*i, true, false);
>> > > > + }
>> > > > + } else {
>> > > > + for (int i = 0; i < 2; i++) {
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_4);
>> > > > +
>> > > > + brw_set_default_mask_control(p, true);
>> > > > + struct brw_reg temp =
>> > > > + retype(suboffset(src, i * 16 /
>> > > > type_sz(src.type)),
>> > > > BRW_REGISTER_TYPE_UD);
>> > > > + temp = stride(temp, 4, 4, 1);
>> > > > +
>> > > > + brw_MOV(p, brw_uvec_mrf(4, inst->base_mrf + 1, 4),
>> > > > + temp);
>> > > > +
>> > > > + brw_set_default_mask_control(p, inst-
>> > > > > force_writemask_all);
>> > > >
>> > > > + brw_set_default_exec_size(p, BRW_EXECUTE_8);
>> > > > +
>> > > > + /* Offset in OWORDs */
>> > > > + brw_oword_block_write_scratch(p,
>> > > > brw_message_reg(inst-
>> > > > > base_mrf),
>> > > >
>> > > > + 1, 32*inst->offset +
>> > > > 16*i + 32, false, true);
>> > > > + }
>> > > > + }
>> > > > + brw_set_default_exec_size(p, cvt(inst->exec_size) - 1);
>> > > > + brw_set_default_access_mode(p, BRW_ALIGN_16);
>> > > > + return;
>> > > > + }
>> > > > +
>> > > > /* If the instruction is predicated, we'll predicate the
>> > > > send,
>> > > > not
>> > > > * the header setup.
>> > > > */
>> > > > @@ -1780,6 +1908,14 @@ generate_code(struct brw_codegen *p,
>> > > > generate_vs_urb_write(p, inst);
>> > > > break;
>> > > >
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW:
>> > > > + generate_scratch_read_1oword(p, inst, dst, src[0],
>> > > > true);
>> > > > + fill_count++;
>> > > > + break;
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH:
>> > > > + generate_scratch_read_1oword(p, inst, dst, src[0],
>> > > > false);
>> > > > + fill_count++;
>> > > > + break;
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_READ:
>> > > > generate_scratch_read(p, inst, dst, src[0]);
>> > > > fill_count++;
>> > > > diff --git a/src/intel/compiler/brw_vec4_reg_allocate.cpp
>> > > > b/src/intel/compiler/brw_vec4_reg_allocate.cpp
>> > > > index a0ba77b867..ec5ba10e86 100644
>> > > > --- a/src/intel/compiler/brw_vec4_reg_allocate.cpp
>> > > > +++ b/src/intel/compiler/brw_vec4_reg_allocate.cpp
>> > > > @@ -332,7 +332,9 @@ can_use_scratch_for_source(const
>> > > > vec4_instruction *inst, unsigned i,
>> > > > * reusing scratch_reg for this instruction.
>> > > > */
>> > > > if (prev_inst->opcode ==
>> > > > SHADER_OPCODE_GEN4_SCRATCH_WRITE ||
>> > > > - prev_inst->opcode ==
>> > > > SHADER_OPCODE_GEN4_SCRATCH_READ)
>> > > > + prev_inst->opcode == SHADER_OPCODE_GEN4_SCRATCH_READ
>> > > > ||
>> > > > + prev_inst->opcode ==
>> > > > VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW ||
>> > > > + prev_inst->opcode ==
>> > > > VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH)
>> > > > continue;
>> > > >
>> > > > /* If the previous instruction does not write to
>> > > > scratch_reg, then check
>> > > > @@ -467,6 +469,8 @@ vec4_visitor::evaluate_spill_costs(float
>> > > > *spill_costs, bool *no_spill)
>> > > > loop_scale /= 10;
>> > > > break;
>> > > >
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW:
>> > > > + case VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH:
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_READ:
>> > > > case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
>> > > > for (int i = 0; i < 3; i++) {
>> > > > diff --git a/src/intel/compiler/brw_vec4_visitor.cpp
>> > > > b/src/intel/compiler/brw_vec4_visitor.cpp
>> > > > index 22ee4dd1c4..37ae31c0d5 100644
>> > > > --- a/src/intel/compiler/brw_vec4_visitor.cpp
>> > > > +++ b/src/intel/compiler/brw_vec4_visitor.cpp
>> > > > @@ -264,6 +264,24 @@ vec4_visitor::SCRATCH_READ(const dst_reg
>> > > > &dst,
>> > > > const src_reg &index)
>> > > > }
>> > > >
>> > > > vec4_instruction *
>> > > > +vec4_visitor::DF_IVB_SCRATCH_READ(const dst_reg &dst,
>> > > > + const src_reg &index,
>> > > > + bool first_grf)
>> > > > +{
>> > > > + vec4_instruction *inst;
>> > > > + enum opcode op = first_grf ?
>> > > > + VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_LOW :
>> > > > + VEC4_OPCODE_GEN4_SCRATCH_READ_1OWORD_HIGH;
>> > > > +
>> > > > + inst = new(mem_ctx) vec4_instruction(op,
>> > > > + dst, index);
>> > > > + inst->base_mrf = FIRST_SPILL_MRF(devinfo->gen) + 1;
>> > > > + inst->mlen = 1;
>> > > > +
>> > > > + return inst;
>> > > > +}
>> > > > +
>> > > > +vec4_instruction *
>> > > > vec4_visitor::SCRATCH_WRITE(const dst_reg &dst, const src_reg
>> > > > &src,
>> > > > const src_reg &index)
>> > > > {
>> > > > @@ -1472,6 +1490,37 @@
>> > > > vec4_visitor::get_scratch_offset(bblock_t
>> > > > *block, vec4_instruction *inst,
>> > > >
>> > > > /**
>> > > > * Emits an instruction before @inst to load the value named
>> > > > by
>> > > > @orig_src
>> > > > + * from scratch space at @base_offset to @temp. This
>> > > > instruction
>> > > > only reads
>> > > > + * DF value on IVB, one GRF each time.
>> > > > + *
>> > > > + * @base_offset is measured in 32-byte units (the size of a
>> > > > register).
>> > > > + * @first_grf indicates if we want to read first vertex data
>> > > > (true) or
>> > > > + * the second (false).
>> > > > + */
>> > > > +void
>> > > > +vec4_visitor::emit_1grf_df_ivb_scratch_read(bblock_t *block,
>> > > > + vec4_instruction
>> > > > *inst,
>> > > > + dst_reg temp,
>> > > > src_reg
>> > > > orig_src,
>> > > > + int base_offset,
>> > > > bool
>> > > > first_grf)
>> > > > +{
>> > > > + assert(orig_src.offset % REG_SIZE == 0);
>> > > > + src_reg index = get_scratch_offset(block, inst, 0,
>> > > > base_offset);
>> > > > +
>> > > > + assert(devinfo->gen == 7 && !devinfo->is_haswell &&
>> > > > type_sz(temp.type) == 8);
>> > > > + temp.offset = 0;
>> > > > + vec4_instruction *read = DF_IVB_SCRATCH_READ(temp, index,
>> > > > first_grf);
>> > > > + read->exec_size = 4;
>> > > > + /* The instruction will use group 0 but a different message
>> > > > depending of the
>> > > > + * vertex data to load.
>> > > > + */
>> > > > + read->group = 0;
>> > > > + read->offset = base_offset;
>> > > > + read->size_written = 1;
>> > > > + emit_before(block, inst, read);
>> > > > +}
>> > > > +
>> > > > +/**
>> > > > + * Emits an instruction before @inst to load the value named
>> > > > by
>> > > > @orig_src
>> > > > * from scratch space at @base_offset to @temp.
>> > > > *
>> > > > * @base_offset is measured in 32-byte units (the size of a
>> > > > register).
>> > > > --
>> > > > 2.11.0
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 212 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170626/26c01065/attachment-0001.sig>
More information about the mesa-dev
mailing list