Handle chains of OpAccessChain in replacing variable index access for flattened resources. (#4797)

This commit is contained in:
Daniele Vettorel 2022-05-10 11:41:43 -04:00 committed by GitHub
parent ad3514b732
commit f7a6e3b9d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 14 deletions

View File

@ -95,7 +95,7 @@ void ReplaceDescArrayAccessUsingVarIndex::ReplaceUsersOfAccessChain(
CollectRecursiveUsersWithConcreteType(access_chain, &final_users);
for (auto* inst : final_users) {
std::deque<Instruction*> insts_to_be_cloned =
CollectRequiredImageInsts(inst);
CollectRequiredImageAndAccessInsts(inst);
ReplaceNonUniformAccessWithSwitchCase(
inst, access_chain, number_of_elements, insts_to_be_cloned);
}
@ -121,8 +121,8 @@ void ReplaceDescArrayAccessUsingVarIndex::CollectRecursiveUsersWithConcreteType(
}
std::deque<Instruction*>
ReplaceDescArrayAccessUsingVarIndex::CollectRequiredImageInsts(
Instruction* user_of_image_insts) const {
ReplaceDescArrayAccessUsingVarIndex::CollectRequiredImageAndAccessInsts(
Instruction* user) const {
std::unordered_set<uint32_t> seen_inst_ids;
std::queue<Instruction*> work_list;
@ -131,21 +131,23 @@ ReplaceDescArrayAccessUsingVarIndex::CollectRequiredImageInsts(
if (!seen_inst_ids.insert(*idp).second) return;
Instruction* operand = get_def_use_mgr()->GetDef(*idp);
if (context()->get_instr_block(operand) != nullptr &&
HasImageOrImagePtrType(operand)) {
(HasImageOrImagePtrType(operand) ||
operand->opcode() == SpvOpAccessChain ||
operand->opcode() == SpvOpInBoundsAccessChain)) {
work_list.push(operand);
}
};
std::deque<Instruction*> required_image_insts;
required_image_insts.push_front(user_of_image_insts);
user_of_image_insts->ForEachInId(decision_to_include_operand);
std::deque<Instruction*> required_insts;
required_insts.push_front(user);
user->ForEachInId(decision_to_include_operand);
while (!work_list.empty()) {
auto* inst_from_work_list = work_list.front();
work_list.pop();
required_image_insts.push_front(inst_from_work_list);
required_insts.push_front(inst_from_work_list);
inst_from_work_list->ForEachInId(decision_to_include_operand);
}
return required_image_insts;
return required_insts;
}
bool ReplaceDescArrayAccessUsingVarIndex::HasImageOrImagePtrType(

View File

@ -76,11 +76,12 @@ class ReplaceDescArrayAccessUsingVarIndex : public Pass {
void CollectRecursiveUsersWithConcreteType(
Instruction* access_chain, std::vector<Instruction*>* final_users) const;
// Recursively collects the operands of |user_of_image_insts| (and operands
// of the operands) whose result types are images/samplers or pointers/array/
// struct of them and returns them.
std::deque<Instruction*> CollectRequiredImageInsts(
Instruction* user_of_image_insts) const;
// Recursively collects the operands of |user| (and operands of the operands)
// whose result types are images/samplers (or pointers/arrays/ structs of
// them) and access chains instructions and returns them. The returned
// collection includes |user|.
std::deque<Instruction*> CollectRequiredImageAndAccessInsts(
Instruction* user) const;
// Returns whether result type of |inst| is an image/sampler/pointer of image
// or sampler or not.

View File

@ -406,6 +406,83 @@ TEST_F(ReplaceDescArrayAccessUsingVarIndexTest,
SinglePassRunAndMatch<ReplaceDescArrayAccessUsingVarIndex>(text, true);
}
TEST_F(ReplaceDescArrayAccessUsingVarIndexTest, ReplaceMultipleAccessChains) {
const std::string text = R"(
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %1 "TestFragment" %2
OpExecutionMode %1 OriginUpperLeft
OpName %11 "type.ConstantBuffer.TestStruct"
OpMemberName %11 0 "val1"
OpMemberName %11 1 "val2"
OpName %3 "TestResources"
OpName %13 "type.2d.image"
OpName %4 "OutBuffer"
OpName %2 "in.var.SV_INSTANCEID"
OpName %1 "TestFragment"
OpDecorate %2 Flat
OpDecorate %2 Location 0
OpDecorate %3 DescriptorSet 0
OpDecorate %3 Binding 0
OpDecorate %4 DescriptorSet 0
OpDecorate %4 Binding 1
OpMemberDecorate %11 0 Offset 0
OpMemberDecorate %11 1 Offset 4
OpDecorate %11 Block
%9 = OpTypeInt 32 0
%10 = OpConstant %9 2
%11 = OpTypeStruct %9 %9
%8 = OpTypeArray %11 %10
%7 = OpTypePointer Uniform %8
%13 = OpTypeImage %9 2D 2 0 0 2 R32ui
%12 = OpTypePointer UniformConstant %13
%14 = OpTypePointer Input %9
%15 = OpTypeVoid
%16 = OpTypeFunction %15
%40 = OpTypeVector %9 2
%3 = OpVariable %7 Uniform
%4 = OpVariable %12 UniformConstant
%2 = OpVariable %14 Input
%57 = OpTypePointer Uniform %11
%61 = OpTypePointer Uniform %9
%62 = OpConstant %9 0
%1 = OpFunction %15 None %16
%17 = OpLabel
%20 = OpLoad %9 %2
%47 = OpAccessChain %57 %3 %20
%63 = OpAccessChain %61 %47 %62
%64 = OpLoad %9 %63
; CHECK: [[null_value:%\w+]] = OpConstantNull %uint
; CHECK: [[var_index:%\w+]] = OpLoad %uint %in_var_SV_INSTANCEID
; CHECK: OpSelectionMerge [[merge:%\w+]] None
; CHECK: OpSwitch [[var_index]] [[default:%\w+]] 0 [[case0:%\w+]] 1 [[case1:%\w+]]
; CHECK: [[case0]] = OpLabel
; CHECK: OpAccessChain
; CHECK: OpAccessChain
; CHECK: [[result0:%\w+]] = OpLoad
; CHECK: OpBranch [[merge]]
; CHECK: [[case1]] = OpLabel
; CHECK: OpAccessChain
; CHECK: OpAccessChain
; CHECK: [[result1:%\w+]] = OpLoad
; CHECK: OpBranch [[merge]]
; CHECK: [[default]] = OpLabel
; CHECK: OpBranch [[merge]]
; CHECK: [[merge]] = OpLabel
; CHECK: OpPhi %uint [[result0]] [[case0]] [[result1]] [[case1]] [[null_value]] [[default]]
%55 = OpCompositeConstruct %40 %20 %20
%56 = OpLoad %13 %4
OpImageWrite %56 %55 %64 None
OpReturn
OpFunctionEnd
)";
SinglePassRunAndMatch<ReplaceDescArrayAccessUsingVarIndex>(text, true);
}
TEST_F(ReplaceDescArrayAccessUsingVarIndexTest,
ReplaceAccessChainToTextureArrayWithNonUniformIndex) {
const std::string text = R"(