diff options
author | Rafael Antognolli <[email protected]> | 2017-01-20 09:53:25 -0800 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2017-02-21 16:28:32 -0800 |
commit | d03ec496ee6bbf356d64682450155704b2e21a27 (patch) | |
tree | c66a43c0faa1d1665082f93b1d2cd8cac4ded32b /src/mesa/drivers | |
parent | 5933ec86fde21cf43077987f28ed68e8d69a0bf3 (diff) |
i965: Add support for xfb overflow on query buffer objects.
Enable getting the results of a transform feedback overflow query with a
buffer object.
v4:
- hsw_overflow_result_to_gpr0 a public function, so it can be used
by conditional render. (Kenneth)
- fix typo grp0/gpr0 (Kenneth)
- rename load_gen_written_data_to_regs to
load_overflow_data_to_cs_gprs (Kenneth)
Signed-off-by: Rafael Antognolli <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_context.h | 3 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/hsw_queryobj.c | 112 |
2 files changed, 115 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 4cb96ce6cff..83c91db5b2e 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -1264,6 +1264,9 @@ void brw_write_timestamp(struct brw_context *brw, drm_intel_bo *bo, int idx); void brw_write_depth_count(struct brw_context *brw, drm_intel_bo *bo, int idx); /** hsw_queryobj.c */ +void hsw_overflow_result_to_gpr0(struct brw_context *brw, + struct brw_query_object *query, + int count); void hsw_init_queryobj_functions(struct dd_function_table *functions); /** brw_conditional_render.c */ diff --git a/src/mesa/drivers/dri/i965/hsw_queryobj.c b/src/mesa/drivers/dri/i965/hsw_queryobj.c index 0da2c3d3888..938fe06c874 100644 --- a/src/mesa/drivers/dri/i965/hsw_queryobj.c +++ b/src/mesa/drivers/dri/i965/hsw_queryobj.c @@ -187,6 +187,107 @@ gpr0_to_bool(struct brw_context *brw) } static void +load_overflow_data_to_cs_gprs(struct brw_context *brw, + struct brw_query_object *query, + int idx) +{ + int offset = idx * sizeof(uint64_t) * 4; + + brw_load_register_mem64(brw, + HSW_CS_GPR(1), + query->bo, + I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, + offset); + + offset += sizeof(uint64_t); + brw_load_register_mem64(brw, + HSW_CS_GPR(2), + query->bo, + I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, + offset); + + offset += sizeof(uint64_t); + brw_load_register_mem64(brw, + HSW_CS_GPR(3), + query->bo, + I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, + offset); + + offset += sizeof(uint64_t); + brw_load_register_mem64(brw, + HSW_CS_GPR(4), + query->bo, + I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, + offset); +} + +/* + * R3 = R4 - R3; + * R1 = R2 - R1; + * R1 = R3 - R1; + * R0 = R0 | R1; + */ +static void +calc_overflow_for_stream(struct brw_context *brw) +{ + static const uint32_t maths[] = { + MI_MATH_ALU2(LOAD, SRCA, R4), + MI_MATH_ALU2(LOAD, SRCB, R3), + MI_MATH_ALU0(SUB), + MI_MATH_ALU2(STORE, R3, ACCU), + MI_MATH_ALU2(LOAD, SRCA, R2), + MI_MATH_ALU2(LOAD, SRCB, R1), + MI_MATH_ALU0(SUB), + MI_MATH_ALU2(STORE, R1, ACCU), + MI_MATH_ALU2(LOAD, SRCA, R3), + MI_MATH_ALU2(LOAD, SRCB, R1), + MI_MATH_ALU0(SUB), + MI_MATH_ALU2(STORE, R1, ACCU), + MI_MATH_ALU2(LOAD, SRCA, R1), + MI_MATH_ALU2(LOAD, SRCB, R0), + MI_MATH_ALU0(OR), + MI_MATH_ALU2(STORE, R0, ACCU), + }; + + BEGIN_BATCH(1 + ARRAY_SIZE(maths)); + OUT_BATCH(HSW_MI_MATH | (1 + ARRAY_SIZE(maths) - 2)); + + for (int m = 0; m < ARRAY_SIZE(maths); m++) + OUT_BATCH(maths[m]); + + ADVANCE_BATCH(); +} + +static void +calc_overflow_to_gpr0(struct brw_context *brw, struct brw_query_object *query, + int count) +{ + brw_load_register_imm64(brw, HSW_CS_GPR(0), 0ull); + + for (int i = 0; i < count; i++) { + load_overflow_data_to_cs_gprs(brw, query, i); + calc_overflow_for_stream(brw); + } +} + +/* + * Take a query and calculate whether there was overflow during transform + * feedback. Store the result in the gpr0 register. + */ +void +hsw_overflow_result_to_gpr0(struct brw_context *brw, + struct brw_query_object *query, + int count) +{ + calc_overflow_to_gpr0(brw, query, count); + gpr0_to_bool(brw); +} + +static void hsw_result_to_gpr0(struct gl_context *ctx, struct brw_query_object *query, struct gl_buffer_object *buf, intptr_t offset, GLenum pname, GLenum ptype) @@ -223,6 +324,11 @@ hsw_result_to_gpr0(struct gl_context *ctx, struct brw_query_object *query, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0 * sizeof(uint64_t)); + } else if (query->Base.Target == GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB + || query->Base.Target == GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB) { + /* Don't do anything in advance here, since the math for this is a little + * more complex. + */ } else { brw_load_register_mem64(brw, HSW_CS_GPR(1), @@ -274,6 +380,12 @@ hsw_result_to_gpr0(struct gl_context *ctx, struct brw_query_object *query, case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: gpr0_to_bool(brw); break; + case GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB: + hsw_overflow_result_to_gpr0(brw, query, 1); + break; + case GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB: + hsw_overflow_result_to_gpr0(brw, query, MAX_VERTEX_STREAMS); + break; } } |