From da9838e6c3500901120b1a6899839a4275eb589d Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 2 Sep 2022 11:29:25 -0700 Subject: [PATCH] [spv-out] Don't emit no-op `OpBitCast` instructions. As reported in #2015, some drivers trip over these. --- src/back/spv/block.rs | 40 ++++++++++++++++++++++++++-------- tests/out/spv/image.spvasm | 3 +-- tests/out/spv/operators.spvasm | 6 ----- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/back/spv/block.rs b/src/back/spv/block.rs index 8a388be22e..10fd5d72aa 100644 --- a/src/back/spv/block.rs +++ b/src/back/spv/block.rs @@ -1029,6 +1029,7 @@ impl<'w> BlockContext<'w> { }; enum Cast { + Identity, Unary(spirv::Op), Binary(spirv::Op, Word), Ternary(spirv::Op, Word, Word), @@ -1039,6 +1040,13 @@ impl<'w> BlockContext<'w> { Cast::Unary(spirv::Op::CopyObject) } else { match (src_kind, kind, convert) { + // Filter out identity casts. Some Adreno drivers are + // confused by no-op OpBitCast instructions. + (src_kind, kind, convert) + if src_kind == kind && convert.unwrap_or(src_width) == src_width => + { + Cast::Identity + } (Sk::Bool, Sk::Bool, _) => Cast::Unary(spirv::Op::CopyObject), (_, _, None) => Cast::Unary(spirv::Op::Bitcast), // casting to a bool - generate `OpXxxNotEqual` @@ -1144,16 +1152,30 @@ impl<'w> BlockContext<'w> { let id = self.gen_id(); let instruction = match cast { - Cast::Unary(op) => Instruction::unary(op, result_type_id, id, expr_id), - Cast::Binary(op, operand) => { - Instruction::binary(op, result_type_id, id, expr_id, operand) - } - Cast::Ternary(op, op1, op2) => { - Instruction::ternary(op, result_type_id, id, expr_id, op1, op2) - } + Cast::Identity => None, + Cast::Unary(op) => Some(Instruction::unary(op, result_type_id, id, expr_id)), + Cast::Binary(op, operand) => Some(Instruction::binary( + op, + result_type_id, + id, + expr_id, + operand, + )), + Cast::Ternary(op, op1, op2) => Some(Instruction::ternary( + op, + result_type_id, + id, + expr_id, + op1, + op2, + )), }; - block.body.push(instruction); - id + if let Some(instruction) = instruction { + block.body.push(instruction); + id + } else { + expr_id + } } crate::Expression::ImageLoad { image, diff --git a/tests/out/spv/image.spvasm b/tests/out/spv/image.spvasm index 7ad2b35603..f0556d35d4 100644 --- a/tests/out/spv/image.spvasm +++ b/tests/out/spv/image.spvasm @@ -277,8 +277,7 @@ OpFunctionEnd OpBranch %150 %150 = OpLabel %152 = OpImageQuerySizeLod %4 %143 %151 -%153 = OpBitcast %4 %152 -%154 = OpImageQuerySizeLod %4 %143 %153 +%154 = OpImageQuerySizeLod %4 %143 %152 %155 = OpImageQuerySizeLod %21 %144 %151 %156 = OpImageQuerySizeLod %21 %144 %6 %157 = OpImageQuerySizeLod %105 %145 %151 diff --git a/tests/out/spv/operators.spvasm b/tests/out/spv/operators.spvasm index 2e7cc31391..bdd3551109 100644 --- a/tests/out/spv/operators.spvasm +++ b/tests/out/spv/operators.spvasm @@ -161,13 +161,7 @@ OpStore %110 %118 %129 = OpCompositeConstruct %31 %5 %5 %130 = OpCompositeConstruct %32 %128 %129 %131 = OpCompositeConstruct %36 %11 %7 %18 %21 -%132 = OpCopyObject %10 %12 -%133 = OpBitcast %8 %11 -%134 = OpBitcast %20 %19 -%135 = OpBitcast %4 %5 -%136 = OpBitcast %34 %46 %137 = OpCopyObject %37 %53 -%138 = OpBitcast %34 %46 %139 = OpCopyObject %37 %53 %142 = OpAccessChain %141 %110 %19 %19 %143 = OpLoad %4 %142