From fbea4e177f12cd8655a26711af7e61c784bfa267 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 26 Apr 2016 14:30:31 +1000 Subject: [PATCH] tgsi/exec: implement restartable machine. This lets us restart the machine at a PC value, and exits the machine when we hit a barrier. Compute shaders will then execute all the threads up to the barrier, then restart the machines after the barrier once all are done. v2: comment the code a bit, change return types. Acked-by: Roland Scheidegger Signed-off-by: Dave Airlie --- src/gallium/auxiliary/tgsi/tgsi_exec.c | 50 +++++++++++++++++--------- src/gallium/auxiliary/tgsi/tgsi_exec.h | 2 ++ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 9348528c42a..717ead947e7 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -4821,7 +4821,12 @@ micro_umsb(union tgsi_exec_channel *dst, dst->i[3] = util_last_bit(src->u[3]) - 1; } -static void +/** + * Execute a TGSI instruction. + * Returns TRUE if a barrier instruction is hit, + * otherwise FALSE. + */ +static boolean exec_instruction( struct tgsi_exec_machine *mach, const struct tgsi_full_instruction *inst, @@ -5140,7 +5145,7 @@ exec_instruction( mach->CondStackTop = 0; mach->LoopStackTop = 0; *pc = -1; - return; + return FALSE; } assert(mach->CallStackTop > 0); @@ -5789,10 +5794,12 @@ exec_instruction( break; case TGSI_OPCODE_BARRIER: case TGSI_OPCODE_MEMBAR: + return TRUE; break; default: assert( 0 ); } + return FALSE; } static void @@ -5836,13 +5843,16 @@ uint tgsi_exec_machine_run( struct tgsi_exec_machine *mach, int start_pc ) { uint i; - int pc = 0; - tgsi_exec_machine_setup_masks(mach); + mach->pc = start_pc; + + if (!start_pc) { + tgsi_exec_machine_setup_masks(mach); - /* execute declarations (interpolants) */ - for (i = 0; i < mach->NumDeclarations; i++) { - exec_declaration( mach, mach->Declarations+i ); + /* execute declarations (interpolants) */ + for (i = 0; i < mach->NumDeclarations; i++) { + exec_declaration( mach, mach->Declarations+i ); + } } { @@ -5851,24 +5861,30 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach, int start_pc ) struct tgsi_exec_vector outputs[PIPE_MAX_ATTRIBS]; uint inst = 1; - memset(mach->Temps, 0, sizeof(temps)); - if (mach->Outputs) - memset(mach->Outputs, 0, sizeof(outputs)); - memset(temps, 0, sizeof(temps)); - memset(outputs, 0, sizeof(outputs)); + if (!start_pc) { + memset(mach->Temps, 0, sizeof(temps)); + if (mach->Outputs) + memset(mach->Outputs, 0, sizeof(outputs)); + memset(temps, 0, sizeof(temps)); + memset(outputs, 0, sizeof(outputs)); + } #endif /* execute instructions, until pc is set to -1 */ - while (pc != -1) { - + while (mach->pc != -1) { + boolean barrier_hit; #if DEBUG_EXECUTION uint i; - tgsi_dump_instruction(&mach->Instructions[pc], inst++); + tgsi_dump_instruction(&mach->Instructions[mach->pc], inst++); #endif - assert(pc < (int) mach->NumInstructions); - exec_instruction(mach, mach->Instructions + pc, &pc); + assert(mach->pc < (int) mach->NumInstructions); + barrier_hit = exec_instruction(mach, mach->Instructions + mach->pc, &mach->pc); + + /* for compute shaders if we hit a barrier return now for later rescheduling */ + if (barrier_hit && mach->ShaderType == PIPE_SHADER_COMPUTE) + return 0; #if DEBUG_EXECUTION for (i = 0; i < TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_TEMP_EXTRAS; i++) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index 564b3d5d5cc..9343d788db7 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -445,6 +445,8 @@ struct tgsi_exec_machine SamplerViews[PIPE_MAX_SHADER_SAMPLER_VIEWS]; boolean UsedGeometryShader; + + int pc; }; struct tgsi_exec_machine * -- 2.30.2