Emit complex continue blocks "properly".
This commit is contained in:
Родитель
54549a624f
Коммит
28cccc3dbb
|
@ -28,11 +28,15 @@ void main()
|
|||
float _58;
|
||||
_55 = 0.0;
|
||||
_58 = 0.0;
|
||||
float _64;
|
||||
vec4 _72;
|
||||
float _78;
|
||||
for (int _60 = -3; _60 <= 3; _64 = float(_60), _72 = texture(SPIRV_Cross_CombinedmapTexturemapSampler, IN_uv + (vec2(0.0, _8.CB1.TextureSize.w) * _64)), _78 = exp(((-_64) * _64) * 0.2222220003604888916015625) * float(abs(_72.y - _50) < clamp((_50 * 80.0) * 0.0007999999797903001308441162109375, 7.999999797903001308441162109375e-05, 0.008000000379979610443115234375)), _55 += (_72.x * _78), _58 += _78, _60++)
|
||||
for (int _60 = -3; _60 <= 3; )
|
||||
{
|
||||
float _64 = float(_60);
|
||||
vec4 _72 = texture(SPIRV_Cross_CombinedmapTexturemapSampler, IN_uv + (vec2(0.0, _8.CB1.TextureSize.w) * _64));
|
||||
float _78 = exp(((-_64) * _64) * 0.2222220003604888916015625) * float(abs(_72.y - _50) < clamp((_50 * 80.0) * 0.0007999999797903001308441162109375, 7.999999797903001308441162109375e-05, 0.008000000379979610443115234375));
|
||||
_55 += (_72.x * _78);
|
||||
_58 += _78;
|
||||
_60++;
|
||||
continue;
|
||||
}
|
||||
_entryPointOutput = vec4(_55 / _58, _50, 0.0, 1.0);
|
||||
}
|
||||
|
|
|
@ -28,11 +28,15 @@ void main()
|
|||
float _58;
|
||||
_55 = 0.0;
|
||||
_58 = 0.0;
|
||||
float _64;
|
||||
vec4 _72;
|
||||
float _78;
|
||||
for (int _60 = -3; _60 <= 3; _64 = float(_60), _72 = texture(SPIRV_Cross_CombinedmapTexturemapSampler, IN_uv + (vec2(0.0, _8.CB1.TextureSize.w) * _64)), _78 = exp(((-_64) * _64) * 0.2222220003604888916015625) * float(abs(_72.y - _50) < clamp((_50 * 80.0) * 0.0007999999797903001308441162109375, 7.999999797903001308441162109375e-05, 0.008000000379979610443115234375)), _55 += (_72.x * _78), _58 += _78, _60++)
|
||||
for (int _60 = -3; _60 <= 3; )
|
||||
{
|
||||
float _64 = float(_60);
|
||||
vec4 _72 = texture(SPIRV_Cross_CombinedmapTexturemapSampler, IN_uv + (vec2(0.0, _8.CB1.TextureSize.w) * _64));
|
||||
float _78 = exp(((-_64) * _64) * 0.2222220003604888916015625) * float(abs(_72.y - _50) < clamp((_50 * 80.0) * 0.0007999999797903001308441162109375, 7.999999797903001308441162109375e-05, 0.008000000379979610443115234375));
|
||||
_55 += (_72.x * _78);
|
||||
_58 += _78;
|
||||
_60++;
|
||||
continue;
|
||||
}
|
||||
_entryPointOutput = vec4(_55 / _58, _50, 0.0, 1.0);
|
||||
}
|
||||
|
|
|
@ -460,7 +460,8 @@ struct SPIRBlock : IVariant
|
|||
enum Method
|
||||
{
|
||||
MergeToSelectForLoop,
|
||||
MergeToDirectForLoop
|
||||
MergeToDirectForLoop,
|
||||
MergeToSelectContinueForLoop
|
||||
};
|
||||
|
||||
enum ContinueBlockType
|
||||
|
|
|
@ -2108,7 +2108,7 @@ bool Compiler::block_is_loop_candidate(const SPIRBlock &block, SPIRBlock::Method
|
|||
if (block.disable_block_optimization || block.complex_continue)
|
||||
return false;
|
||||
|
||||
if (method == SPIRBlock::MergeToSelectForLoop)
|
||||
if (method == SPIRBlock::MergeToSelectForLoop || method == SPIRBlock::MergeToSelectContinueForLoop)
|
||||
{
|
||||
// Try to detect common for loop pattern
|
||||
// which the code backend can use to create cleaner code.
|
||||
|
@ -2118,6 +2118,9 @@ bool Compiler::block_is_loop_candidate(const SPIRBlock &block, SPIRBlock::Method
|
|||
block.true_block != block.merge_block && block.true_block != block.self &&
|
||||
block.false_block == block.merge_block;
|
||||
|
||||
if (ret && method == SPIRBlock::MergeToSelectContinueForLoop)
|
||||
ret = block.true_block == block.continue_block;
|
||||
|
||||
// If we have OpPhi which depends on branches which came from our own block,
|
||||
// we need to flush phi variables in else block instead of a trivial break,
|
||||
// so we cannot assume this is a for loop candidate.
|
||||
|
|
|
@ -8635,7 +8635,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
|
|||
{
|
||||
SPIRBlock::ContinueBlockType continue_type = continue_block_type(get<SPIRBlock>(block.continue_block));
|
||||
|
||||
if (method == SPIRBlock::MergeToSelectForLoop)
|
||||
if (method == SPIRBlock::MergeToSelectForLoop || method == SPIRBlock::MergeToSelectContinueForLoop)
|
||||
{
|
||||
uint32_t current_count = statement_count;
|
||||
// If we're trying to create a true for loop,
|
||||
|
@ -8659,8 +8659,13 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
|
|||
// emitting the continue block can invalidate the condition expression.
|
||||
auto initializer = emit_for_loop_initializers(block);
|
||||
auto condition = to_expression(block.condition);
|
||||
if (method != SPIRBlock::MergeToSelectContinueForLoop)
|
||||
{
|
||||
auto continue_block = emit_continue_block(block.continue_block);
|
||||
statement("for (", initializer, "; ", condition, "; ", continue_block, ")");
|
||||
}
|
||||
else
|
||||
statement("for (", initializer, "; ", condition, "; )");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -8763,6 +8768,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||
bool select_branch_to_true_block = false;
|
||||
bool skip_direct_branch = false;
|
||||
bool emitted_for_loop_header = false;
|
||||
bool force_complex_continue_block = false;
|
||||
|
||||
// If we need to force temporaries for certain IDs due to continue blocks, do it before starting loop header.
|
||||
// Need to sort these to ensure that reference output is stable.
|
||||
|
@ -8787,8 +8793,22 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||
for (auto var : block.loop_variables)
|
||||
get<SPIRVariable>(var).loop_variable_enable = true;
|
||||
|
||||
// This is the method often used by spirv-opt to implement loops.
|
||||
// The loop header goes straight into the continue block.
|
||||
// However, don't attempt this on ESSL 1.0, because if a loop variable is used in a continue block,
|
||||
// it *MUST* be used in the continue block. This loop method will not work.
|
||||
if (!is_legacy_es() && block_is_loop_candidate(block, SPIRBlock::MergeToSelectContinueForLoop))
|
||||
{
|
||||
flush_undeclared_variables(block);
|
||||
if (attempt_emit_loop_header(block, SPIRBlock::MergeToSelectContinueForLoop))
|
||||
{
|
||||
select_branch_to_true_block = true;
|
||||
emitted_for_loop_header = true;
|
||||
force_complex_continue_block = true;
|
||||
}
|
||||
}
|
||||
// This is the older loop behavior in glslang which branches to loop body directly from the loop header.
|
||||
if (block_is_loop_candidate(block, SPIRBlock::MergeToSelectForLoop))
|
||||
else if (block_is_loop_candidate(block, SPIRBlock::MergeToSelectForLoop))
|
||||
{
|
||||
flush_undeclared_variables(block);
|
||||
if (attempt_emit_loop_header(block, SPIRBlock::MergeToSelectForLoop))
|
||||
|
@ -8869,9 +8889,23 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||
break;
|
||||
|
||||
case SPIRBlock::Select:
|
||||
// True if MergeToSelectForLoop succeeded.
|
||||
// True if MergeToSelectForLoop or MergeToSelectContinueForLoop succeeded.
|
||||
if (select_branch_to_true_block)
|
||||
{
|
||||
if (force_complex_continue_block)
|
||||
{
|
||||
assert(block.true_block == block.continue_block);
|
||||
|
||||
// We're going to emit a continue block directly here, so make sure it's marked as complex.
|
||||
auto &complex_continue = get<SPIRBlock>(block.continue_block).complex_continue;
|
||||
bool old_complex = complex_continue;
|
||||
complex_continue = true;
|
||||
branch(block.self, block.true_block);
|
||||
complex_continue = old_complex;
|
||||
}
|
||||
else
|
||||
branch(block.self, block.true_block);
|
||||
}
|
||||
else
|
||||
branch(block.self, block.condition, block.true_block, block.false_block);
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче