Skip to content

Commit 2a730e1

Browse files
committed
Handle image texel pointers in local single-store elim
1 parent 7c4d322 commit 2a730e1

2 files changed

Lines changed: 99 additions & 0 deletions

File tree

source/opt/local_single_store_elim_pass.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,18 @@ bool LocalSingleStoreElimPass::RewriteLoads(
305305
else
306306
stored_id = store_inst->GetSingleWordInOperand(kVariableInitIdInIdx);
307307

308+
const auto get_image_pointer_id = [this](uint32_t value_id) {
309+
Instruction* value_inst = context()->get_def_use_mgr()->GetDef(value_id);
310+
while (value_inst && value_inst->opcode() == spv::Op::OpCopyObject) {
311+
value_id = value_inst->GetSingleWordInOperand(0);
312+
value_inst = context()->get_def_use_mgr()->GetDef(value_id);
313+
}
314+
if (!value_inst || value_inst->opcode() != spv::Op::OpLoad) {
315+
return uint32_t{0};
316+
}
317+
return value_inst->GetSingleWordInOperand(0);
318+
};
319+
308320
*all_rewritten = true;
309321
bool modified = false;
310322
for (Instruction* use : uses) {
@@ -319,6 +331,17 @@ bool LocalSingleStoreElimPass::RewriteLoads(
319331
context()->KillNamesAndDecorates(use->result_id());
320332
context()->ReplaceAllUsesWith(use->result_id(), stored_id);
321333
context()->KillInst(use);
334+
} else if (use->opcode() == spv::Op::OpImageTexelPointer &&
335+
dominator_analysis->Dominates(store_inst, use)) {
336+
const uint32_t image_ptr_id = get_image_pointer_id(stored_id);
337+
if (image_ptr_id == 0) {
338+
*all_rewritten = false;
339+
continue;
340+
}
341+
modified = true;
342+
context()->ForgetUses(use);
343+
use->SetInOperand(0, {image_ptr_id});
344+
context()->AnalyzeUses(use);
322345
} else {
323346
*all_rewritten = false;
324347
}

test/opt/local_single_store_elim_test.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,82 @@ OpFunctionEnd
908908
SinglePassRunAndCheck<LocalSingleStoreElimPass>(before, after, true, true);
909909
}
910910

911+
TEST_F(LocalSingleStoreElimTest, RewriteImageTexelPointerImageOperand) {
912+
const std::string before = R"(OpCapability Shader
913+
OpMemoryModel Logical GLSL450
914+
OpEntryPoint GLCompute %main "main" %g_rwTexture3d
915+
OpExecutionMode %main LocalSize 256 1 1
916+
OpSource HLSL 660
917+
OpName %type_3d_image "type.3d.image"
918+
OpName %g_rwTexture3d "g_rwTexture3d"
919+
OpName %main "main"
920+
OpDecorate %g_rwTexture3d DescriptorSet 0
921+
OpDecorate %g_rwTexture3d Binding 0
922+
%uint = OpTypeInt 32 0
923+
%uint_0 = OpConstant %uint 0
924+
%uint_1 = OpConstant %uint 1
925+
%uint_2 = OpConstant %uint 2
926+
%uint_3 = OpConstant %uint 3
927+
%v3uint = OpTypeVector %uint 3
928+
%10 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
929+
%type_3d_image = OpTypeImage %uint 3D 2 0 0 2 R32ui
930+
%_ptr_UniformConstant_type_3d_image = OpTypePointer UniformConstant %type_3d_image
931+
%void = OpTypeVoid
932+
%13 = OpTypeFunction %void
933+
%_ptr_Function_type_3d_image = OpTypePointer Function %type_3d_image
934+
%_ptr_Image_uint = OpTypePointer Image %uint
935+
%g_rwTexture3d = OpVariable %_ptr_UniformConstant_type_3d_image UniformConstant
936+
%main = OpFunction %void None %13
937+
%16 = OpLabel
938+
%17 = OpVariable %_ptr_Function_type_3d_image Function
939+
%18 = OpLoad %type_3d_image %g_rwTexture3d
940+
OpStore %17 %18
941+
%19 = OpImageTexelPointer %_ptr_Image_uint %17 %10 %uint_0
942+
%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
943+
OpReturn
944+
OpFunctionEnd
945+
)";
946+
947+
const std::string after = R"(OpCapability Shader
948+
OpMemoryModel Logical GLSL450
949+
OpEntryPoint GLCompute %main "main" %g_rwTexture3d
950+
OpExecutionMode %main LocalSize 256 1 1
951+
OpSource HLSL 660
952+
OpName %type_3d_image "type.3d.image"
953+
OpName %g_rwTexture3d "g_rwTexture3d"
954+
OpName %main "main"
955+
OpDecorate %g_rwTexture3d DescriptorSet 0
956+
OpDecorate %g_rwTexture3d Binding 0
957+
%uint = OpTypeInt 32 0
958+
%uint_0 = OpConstant %uint 0
959+
%uint_1 = OpConstant %uint 1
960+
%uint_2 = OpConstant %uint 2
961+
%uint_3 = OpConstant %uint 3
962+
%v3uint = OpTypeVector %uint 3
963+
%10 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
964+
%type_3d_image = OpTypeImage %uint 3D 2 0 0 2 R32ui
965+
%_ptr_UniformConstant_type_3d_image = OpTypePointer UniformConstant %type_3d_image
966+
%void = OpTypeVoid
967+
%13 = OpTypeFunction %void
968+
%_ptr_Function_type_3d_image = OpTypePointer Function %type_3d_image
969+
%_ptr_Image_uint = OpTypePointer Image %uint
970+
%g_rwTexture3d = OpVariable %_ptr_UniformConstant_type_3d_image UniformConstant
971+
%main = OpFunction %void None %13
972+
%16 = OpLabel
973+
%17 = OpVariable %_ptr_Function_type_3d_image Function
974+
%18 = OpLoad %type_3d_image %g_rwTexture3d
975+
OpStore %17 %18
976+
%19 = OpImageTexelPointer %_ptr_Image_uint %g_rwTexture3d %10 %uint_0
977+
%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
978+
OpReturn
979+
OpFunctionEnd
980+
)";
981+
982+
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
983+
SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
984+
SinglePassRunAndCheck<LocalSingleStoreElimPass>(before, after, true, true);
985+
}
986+
911987
// Test that that an unused OpAccessChain between a store and a use does does
912988
// not hinders the replacement of the use. We need to check this because
913989
// local-access-chain-convert does always remove the OpAccessChain instructions

0 commit comments

Comments
 (0)