[Mesa-dev] [PATCH v2 9/8+1] i965: Enable ARB_transform_feedback2 on Gen7+ if register writes work.

Kenneth Graunke kenneth at whitecape.org
Mon Oct 28 23:57:32 CET 2013


On 10/28/2013 03:08 PM, Eric Anholt wrote:
> Kenneth Graunke <kenneth at whitecape.org> writes:
> 
>> With Linux 3.12, register writes work on Ivybridge and Baytrail, but not
>> Haswell.  That will be fixed in a future kernel revision, at which point
>> this extension will automatically be enabled.
>>
>> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
>> ---
>>  src/mesa/drivers/dri/i965/intel_extensions.c | 61 +++++++++++++++++++++++++++-
>>  1 file changed, 60 insertions(+), 1 deletion(-)
>>
>> Tested on Ivybridge (extension is on) and Haswell (extension is off).
>> So the register write testing is working as expected.
>>
>> diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
>> index 22e4aa2..0c6ed02 100644
>> --- a/src/mesa/drivers/dri/i965/intel_extensions.c
>> +++ b/src/mesa/drivers/dri/i965/intel_extensions.c
>> @@ -28,11 +28,68 @@
>>  #include "main/version.h"
>>  
>>  #include "brw_context.h"
>> -#include "intel_chipset.h"
>> +#include "intel_batchbuffer.h"
>>  #include "intel_reg.h"
>>  #include "utils.h"
>>  
>>  /**
>> + * Test if we can use MI_LOAD_REGISTER_MEM from an untrusted batchbuffer.
>> + *
>> + * Some combinations of hardware and kernel versions allow this feature,
>> + * while others don't.  Instead of trying to enumerate every case, just
>> + * try and write a register and see if works.
>> + */
> 
> We actually get noops instead of hangs in the not-supported case?
> Sweet.
> 
>> +static bool
>> +can_do_pipelined_register_writes(struct brw_context *brw)
>> +{
>> +   /* We use SO_WRITE_OFFSET0 since you're supposed to write it (unlike the
>> +    * statistics registers), and we already reset it to zero before using it.
>> +    */
>> +   const int reg = GEN7_SO_WRITE_OFFSET(0);
>> +   const int expected_value = 0x1337d0d0;
>> +   const int offset = 100;
>> +
>> +   /* The register we picked only exists on Gen7+. */
>> +   assert(brw->gen >= 7);
>> +
>> +   uint32_t *data;
>> +   /* Set a value in a BO to a known quantity.  The workaround BO already
>> +    * exists and doesn't contain anything important, so we may as well use it.
>> +    */
>> +   drm_intel_bo_map(brw->batch.workaround_bo, false);
> 
> You're writing, so that should be "true".

Oops.  Right, thanks.

>> +   data = brw->batch.workaround_bo->virtual;
>> +   data[offset] = 0xffffffff;
>> +   drm_intel_bo_unmap(brw->batch.workaround_bo);
>> +
>> +   /* Write the register. */
>> +   BEGIN_BATCH(3);
>> +   OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
>> +   OUT_BATCH(reg);
>> +   OUT_BATCH(expected_value);
>> +   ADVANCE_BATCH();
>> +
>> +   intel_batchbuffer_emit_mi_flush(brw);
>> +
>> +   /* Save the register's value back to the buffer. */
>> +   BEGIN_BATCH(3);
>> +   OUT_BATCH(MI_STORE_REGISTER_MEM | (3 - 2));
>> +   OUT_BATCH(reg);
>> +   OUT_RELOC(brw->batch.workaround_bo,
>> +             I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
> 
> I thought we decided these were supposed to be _INSTRUCTION

Definitely for Sandybridge, but this only works on Ivybridge.  I didn't
think it mattered there.  But INSTRUCTION is fine, I'll use that for
consistency.

>> +             offset * sizeof(uint32_t));
>> +   ADVANCE_BATCH();
>> +
>> +   intel_batchbuffer_flush(brw);
>> +
>> +   /* Check whether the value got written. */
>> +   drm_intel_bo_map(brw->batch.workaround_bo, false);
>> +   bool success = data[offset] == expected_value;
>> +   drm_intel_bo_unmap(brw->batch.workaround_bo);
>> +
>> +   return success;
>> +}
> 
> Other than that, Reviewed-by: Eric Anholt <eric at anholt.net>



More information about the mesa-dev mailing list