Skip to content

Commit

Permalink
Handle TimeAMD in AmdExtensionToKhrPass. (#3168)
Browse files Browse the repository at this point in the history
This adds support for replacing TimeAMD with OpReadClockKHR.  The scope
for OpReadClockKHR is fixed to be a subgroup because TimeAMD operates
only on subgroup.
  • Loading branch information
dnovillo authored Feb 3, 2020
1 parent ddcc117 commit a9624b4
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 11 deletions.
45 changes: 35 additions & 10 deletions source/opt/amd_ext_to_khr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,6 @@ analysis::Type* GetUIntType(IRContext* ctx) {
return ctx->get_type_mgr()->GetRegisteredType(&int_type);
}

bool NotImplementedYet(IRContext*, Instruction*,
const std::vector<const analysis::Constant*>&) {
assert(false && "Not implemented.");
return false;
}

// Returns a folding rule that replaces |op(a,b,c)| by |op(op(a,b),c)|, where
// |op| is either min or max. |opcode| is the binary opcode in the GLSLstd450
// extended instruction set that corresponds to the trinary instruction being
Expand Down Expand Up @@ -686,13 +680,13 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst,
return true;
}

// A folding rule that will replace the CubeFaceCoordAMD extended
// A folding rule that will replace the CubeFaceIndexAMD extended
// instruction in the SPV_AMD_gcn_shader_ballot. Returns true if the folding
// is successful.
//
// The instruction
//
// %result = OpExtInst %v2float %1 CubeFaceCoordAMD %input
// %result = OpExtInst %float %1 CubeFaceIndexAMD %input
//
// with
//
Expand All @@ -705,7 +699,7 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst,
// %is_z_neg = OpFOrdLessThan %bool %z %float_0
// %is_y_neg = OpFOrdLessThan %bool %y %float_0
// %is_x_neg = OpFOrdLessThan %bool %x %float_0
// %amax_x_y = OpExtInst %float %n_1 FMax %ay %ax
// %amax_x_y = OpExtInst %float %n_1 FMax %ax %ay
// %is_z_max = OpFOrdGreaterThanEqual %bool %az %amax_x_y
// %y_gt_x = OpFOrdGreaterThanEqual %bool %ay %ax
// %case_z = OpSelect %float %is_z_neg %float_5 %float4
Expand Down Expand Up @@ -800,6 +794,37 @@ bool ReplaceCubeFaceIndex(IRContext* ctx, Instruction* inst,
return true;
}

// A folding rule that will replace the TimeAMD extended instruction in the
// SPV_AMD_gcn_shader_ballot. It returns true if the folding is successful.
// It returns False, otherwise.
//
// The instruction
//
// %result = OpExtInst %uint64 %1 TimeAMD
//
// with
//
// %result = OpReadClockKHR %uint64 %uint_3
//
// NOTE: TimeAMD uses subgroup scope (it is not a real time clock).
bool ReplaceTimeAMD(IRContext* ctx, Instruction* inst,
const std::vector<const analysis::Constant*>&) {
InstructionBuilder ir_builder(
ctx, inst,
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
ctx->AddExtension("SPV_KHR_shader_clock");
ctx->AddCapability(SpvCapabilityShaderClockKHR);

inst->SetOpcode(SpvOpReadClockKHR);
Instruction::OperandList args;
uint32_t subgroup_scope_id = ir_builder.GetUintConstantId(SpvScopeSubgroup);
args.push_back({SPV_OPERAND_TYPE_ID, {subgroup_scope_id}});
inst->SetInOperands(std::move(args));
ctx->UpdateDefUse(inst);

return true;
}

class AmdExtFoldingRules : public FoldingRules {
public:
explicit AmdExtFoldingRules(IRContext* ctx) : FoldingRules(ctx) {}
Expand Down Expand Up @@ -869,7 +894,7 @@ class AmdExtFoldingRules : public FoldingRules {
ReplaceCubeFaceCoord);
ext_rules_[{extension_id, CubeFaceIndexAMD}].push_back(
ReplaceCubeFaceIndex);
ext_rules_[{extension_id, TimeAMD}].push_back(NotImplementedYet);
ext_rules_[{extension_id, TimeAMD}].push_back(ReplaceTimeAMD);
}
}
};
Expand Down
37 changes: 36 additions & 1 deletion test/opt/amd_ext_to_khr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <vector>

#include "gmock/gmock.h"

#include "test/opt/pass_fixture.h"
#include "test/opt/pass_utils.h"

Expand Down Expand Up @@ -913,6 +912,42 @@ TEST_F(AmdExtToKhrTest, SetVersion1) {
EXPECT_THAT(output, HasSubstr("Version: 1.4"));
}

TEST_F(AmdExtToKhrTest, TimeAMD) {
const std::string text = R"(
OpCapability Shader
OpCapability Int64
OpExtension "SPV_AMD_gcn_shader"
; CHECK-NOT: OpExtension "SPV_AMD_gcn_shader"
; CHECK: OpExtension "SPV_KHR_shader_clock"
%1 = OpExtInstImport "GLSL.std.450"
%2 = OpExtInstImport "SPV_AMD_gcn_shader"
; CHECK-NOT: OpExtInstImport "SPV_AMD_gcn_shader"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpSourceExtension "GL_AMD_gcn_shader"
OpSourceExtension "GL_ARB_gpu_shader_int64"
OpName %main "main"
OpName %time "time"
%void = OpTypeVoid
%6 = OpTypeFunction %void
%ulong = OpTypeInt 64 0
%_ptr_Function_ulong = OpTypePointer Function %ulong
%main = OpFunction %void None %6
%9 = OpLabel
%time = OpVariable %_ptr_Function_ulong Function
; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
; CHECK: [[uint_3:%\w+]] = OpConstant [[uint]] 3
%10 = OpExtInst %ulong %2 TimeAMD
; CHECK: %10 = OpReadClockKHR %ulong [[uint_3]]
OpStore %time %10
OpReturn
OpFunctionEnd
)";

SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
}
} // namespace
} // namespace opt
} // namespace spvtools

0 comments on commit a9624b4

Please sign in to comment.