Add support for tesc, tese and geom to EliminateDead*Components (#4990)
This commit is contained in:
Родитель
1a7f71afb4
Коммит
46ca66e699
|
@ -28,17 +28,26 @@ namespace opt {
|
|||
namespace {
|
||||
constexpr uint32_t kAccessChainBaseInIdx = 0;
|
||||
constexpr uint32_t kAccessChainIndex0InIdx = 1;
|
||||
constexpr uint32_t kAccessChainIndex1InIdx = 2;
|
||||
constexpr uint32_t kConstantValueInIdx = 0;
|
||||
} // namespace
|
||||
|
||||
Pass::Status EliminateDeadInputComponentsPass::Process() {
|
||||
// Process non-vertex only if explicitly allowed.
|
||||
auto stage = context()->GetStage();
|
||||
const auto stage = context()->GetStage();
|
||||
if (stage != spv::ExecutionModel::Vertex && vertex_shader_only_)
|
||||
return Status::SuccessWithoutChange;
|
||||
// Current functionality assumes shader capability.
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return Status::SuccessWithoutChange;
|
||||
// Current functionality assumes vert, frag, tesc, tese or geom shader.
|
||||
// TODO(issue #4988): Add GLCompute.
|
||||
if (stage != spv::ExecutionModel::Vertex &&
|
||||
stage != spv::ExecutionModel::Fragment &&
|
||||
stage != spv::ExecutionModel::TessellationControl &&
|
||||
stage != spv::ExecutionModel::TessellationEvaluation &&
|
||||
stage != spv::ExecutionModel::Geometry)
|
||||
return Status::SuccessWithoutChange;
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
bool modified = false;
|
||||
|
@ -52,23 +61,39 @@ Pass::Status EliminateDeadInputComponentsPass::Process() {
|
|||
if (ptr_type == nullptr) {
|
||||
continue;
|
||||
}
|
||||
const auto sclass = ptr_type->storage_class();
|
||||
if (output_instead_) {
|
||||
if (ptr_type->storage_class() != spv::StorageClass::Output) {
|
||||
if (sclass != spv::StorageClass::Output) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (ptr_type->storage_class() != spv::StorageClass::Input) {
|
||||
if (sclass != spv::StorageClass::Input) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const analysis::Array* arr_type = ptr_type->pointee_type()->AsArray();
|
||||
// For tesc, or input variables in tese or geom shaders,
|
||||
// there is a outer per-vertex-array that must be ignored
|
||||
// for the purposes of this analysis/optimization. Do the
|
||||
// analysis on the inner type in these cases.
|
||||
bool skip_first_index = false;
|
||||
auto core_type = ptr_type->pointee_type();
|
||||
if (stage == spv::ExecutionModel::TessellationControl ||
|
||||
(sclass == spv::StorageClass::Input &&
|
||||
(stage == spv::ExecutionModel::TessellationEvaluation ||
|
||||
stage == spv::ExecutionModel::Geometry))) {
|
||||
auto arr_type = core_type->AsArray();
|
||||
if (!arr_type) continue;
|
||||
core_type = arr_type->element_type();
|
||||
skip_first_index = true;
|
||||
}
|
||||
const analysis::Array* arr_type = core_type->AsArray();
|
||||
if (arr_type != nullptr) {
|
||||
// Only process array if input of vertex shader, or output of
|
||||
// fragment shader. Otherwise, if one shader has a runtime index and the
|
||||
// other does not, interface incompatibility can occur.
|
||||
if (!((ptr_type->storage_class() == spv::StorageClass::Input &&
|
||||
if (!((sclass == spv::StorageClass::Input &&
|
||||
stage == spv::ExecutionModel::Vertex) ||
|
||||
(ptr_type->storage_class() == spv::StorageClass::Output &&
|
||||
(sclass == spv::StorageClass::Output &&
|
||||
stage == spv::ExecutionModel::Fragment)))
|
||||
continue;
|
||||
unsigned arr_len_id = arr_type->LengthId();
|
||||
|
@ -88,13 +113,13 @@ Pass::Status EliminateDeadInputComponentsPass::Process() {
|
|||
}
|
||||
continue;
|
||||
}
|
||||
const analysis::Struct* struct_type = ptr_type->pointee_type()->AsStruct();
|
||||
const analysis::Struct* struct_type = core_type->AsStruct();
|
||||
if (struct_type == nullptr) continue;
|
||||
const auto elt_types = struct_type->element_types();
|
||||
unsigned original_max = static_cast<unsigned>(elt_types.size()) - 1;
|
||||
unsigned max_idx = FindMaxIndex(var, original_max);
|
||||
unsigned max_idx = FindMaxIndex(var, original_max, skip_first_index);
|
||||
if (max_idx != original_max) {
|
||||
ChangeStructLength(var, max_idx + 1);
|
||||
ChangeIOVarStructLength(var, max_idx + 1);
|
||||
vars_to_move.push_back(&var);
|
||||
modified = true;
|
||||
}
|
||||
|
@ -112,13 +137,15 @@ Pass::Status EliminateDeadInputComponentsPass::Process() {
|
|||
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
unsigned EliminateDeadInputComponentsPass::FindMaxIndex(Instruction& var,
|
||||
unsigned original_max) {
|
||||
unsigned EliminateDeadInputComponentsPass::FindMaxIndex(
|
||||
const Instruction& var, const unsigned original_max,
|
||||
const bool skip_first_index) {
|
||||
unsigned max = 0;
|
||||
bool seen_non_const_ac = false;
|
||||
assert(var.opcode() == spv::Op::OpVariable && "must be variable");
|
||||
context()->get_def_use_mgr()->WhileEachUser(
|
||||
var.result_id(), [&max, &seen_non_const_ac, var, this](Instruction* use) {
|
||||
var.result_id(), [&max, &seen_non_const_ac, var, skip_first_index,
|
||||
this](Instruction* use) {
|
||||
auto use_opcode = use->opcode();
|
||||
if (use_opcode == spv::Op::OpLoad || use_opcode == spv::Op::OpStore ||
|
||||
use_opcode == spv::Op::OpCopyMemory ||
|
||||
|
@ -132,13 +159,17 @@ unsigned EliminateDeadInputComponentsPass::FindMaxIndex(Instruction& var,
|
|||
return true;
|
||||
}
|
||||
// OpAccessChain with no indices currently not optimized
|
||||
if (use->NumInOperands() == 1) {
|
||||
if (use->NumInOperands() == 1 ||
|
||||
(skip_first_index && use->NumInOperands() == 2)) {
|
||||
seen_non_const_ac = true;
|
||||
return false;
|
||||
}
|
||||
unsigned base_id = use->GetSingleWordInOperand(kAccessChainBaseInIdx);
|
||||
const unsigned base_id =
|
||||
use->GetSingleWordInOperand(kAccessChainBaseInIdx);
|
||||
USE_ASSERT(base_id == var.result_id() && "unexpected base");
|
||||
unsigned idx_id = use->GetSingleWordInOperand(kAccessChainIndex0InIdx);
|
||||
const unsigned in_idx = skip_first_index ? kAccessChainIndex1InIdx
|
||||
: kAccessChainIndex0InIdx;
|
||||
const unsigned idx_id = use->GetSingleWordInOperand(in_idx);
|
||||
Instruction* idx_inst = context()->get_def_use_mgr()->GetDef(idx_id);
|
||||
if (idx_inst->opcode() != spv::Op::OpConstant) {
|
||||
seen_non_const_ac = true;
|
||||
|
@ -171,12 +202,17 @@ void EliminateDeadInputComponentsPass::ChangeArrayLength(Instruction& arr_var,
|
|||
def_use_mgr->AnalyzeInstUse(&arr_var);
|
||||
}
|
||||
|
||||
void EliminateDeadInputComponentsPass::ChangeStructLength(
|
||||
Instruction& struct_var, unsigned length) {
|
||||
void EliminateDeadInputComponentsPass::ChangeIOVarStructLength(
|
||||
Instruction& io_var, unsigned length) {
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
analysis::Pointer* ptr_type =
|
||||
type_mgr->GetType(struct_var.type_id())->AsPointer();
|
||||
const analysis::Struct* struct_ty = ptr_type->pointee_type()->AsStruct();
|
||||
type_mgr->GetType(io_var.type_id())->AsPointer();
|
||||
auto core_type = ptr_type->pointee_type();
|
||||
// Check for per-vertex-array of struct from tesc, tese and geom and grab
|
||||
// embedded struct type.
|
||||
const auto arr_type = core_type->AsArray();
|
||||
if (arr_type) core_type = arr_type->element_type();
|
||||
const analysis::Struct* struct_ty = core_type->AsStruct();
|
||||
assert(struct_ty && "expecting struct type");
|
||||
const auto orig_elt_types = struct_ty->element_types();
|
||||
std::vector<const analysis::Type*> new_elt_types;
|
||||
|
@ -194,14 +230,19 @@ void EliminateDeadInputComponentsPass::ChangeStructLength(
|
|||
}
|
||||
type_mgr->AttachDecoration(*dec, &new_struct_ty);
|
||||
}
|
||||
analysis::Type* reg_new_struct_ty =
|
||||
type_mgr->GetRegisteredType(&new_struct_ty);
|
||||
analysis::Pointer new_ptr_ty(reg_new_struct_ty, ptr_type->storage_class());
|
||||
analysis::Type* reg_new_var_ty = type_mgr->GetRegisteredType(&new_struct_ty);
|
||||
if (arr_type) {
|
||||
analysis::Array new_arr_ty(reg_new_var_ty, arr_type->length_info());
|
||||
reg_new_var_ty = type_mgr->GetRegisteredType(&new_arr_ty);
|
||||
}
|
||||
auto sclass =
|
||||
output_instead_ ? spv::StorageClass::Output : spv::StorageClass::Input;
|
||||
analysis::Pointer new_ptr_ty(reg_new_var_ty, sclass);
|
||||
analysis::Type* reg_new_ptr_ty = type_mgr->GetRegisteredType(&new_ptr_ty);
|
||||
uint32_t new_ptr_ty_id = type_mgr->GetTypeInstruction(reg_new_ptr_ty);
|
||||
struct_var.SetResultType(new_ptr_ty_id);
|
||||
io_var.SetResultType(new_ptr_ty_id);
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
def_use_mgr->AnalyzeInstUse(&struct_var);
|
||||
def_use_mgr->AnalyzeInstUse(&io_var);
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
|
|
|
@ -52,13 +52,15 @@ class EliminateDeadInputComponentsPass : public Pass {
|
|||
// Find the max constant used to index the variable declared by |var|
|
||||
// through OpAccessChain or OpInBoundsAccessChain. If any non-constant
|
||||
// indices or non-Op*AccessChain use of |var|, return |original_max|.
|
||||
unsigned FindMaxIndex(Instruction& var, unsigned original_max);
|
||||
unsigned FindMaxIndex(const Instruction& var, const unsigned original_max,
|
||||
const bool skip_first_index = false);
|
||||
|
||||
// Change the length of the array |inst| to |length|
|
||||
void ChangeArrayLength(Instruction& inst, unsigned length);
|
||||
|
||||
// Change the length of the struct |struct_var| to |length|
|
||||
void ChangeStructLength(Instruction& struct_var, unsigned length);
|
||||
// Change the length of the struct in |io_var| to |length|. |io_var|
|
||||
// is either the struct or a per-vertex-array of the struct.
|
||||
void ChangeIOVarStructLength(Instruction& io_var, unsigned length);
|
||||
|
||||
// Process output variables instead
|
||||
bool output_instead_;
|
||||
|
|
|
@ -686,6 +686,569 @@ TEST_F(ElimDeadInputComponentsTest, VertexOnly) {
|
|||
true);
|
||||
}
|
||||
|
||||
TEST_F(ElimDeadInputComponentsTest, TescInput) {
|
||||
// Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// layout (vertices = 4) out;
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// vec4 pos = gl_in[gl_InvocationID].gl_Position;
|
||||
// gl_out[gl_InvocationID].gl_Position = pos;
|
||||
// }
|
||||
const std::string text = R"(
|
||||
OpCapability Tessellation
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationControl %main "main" %gl_in %gl_InvocationID %gl_out
|
||||
OpExecutionMode %main OutputVertices 4
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %pos "pos"
|
||||
OpName %gl_PerVertex "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex 0 "gl_Position"
|
||||
OpMemberName %gl_PerVertex 1 "gl_PointSize"
|
||||
OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
|
||||
OpMemberName %gl_PerVertex 3 "gl_CullDistance"
|
||||
OpName %gl_in "gl_in"
|
||||
OpName %gl_InvocationID "gl_InvocationID"
|
||||
OpName %gl_PerVertex_0 "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex_0 0 "gl_Position"
|
||||
OpName %gl_out "gl_out"
|
||||
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
|
||||
OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
|
||||
OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
|
||||
OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
|
||||
OpDecorate %gl_PerVertex Block
|
||||
OpDecorate %gl_InvocationID BuiltIn InvocationId
|
||||
OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
|
||||
OpDecorate %gl_PerVertex_0 Block
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%_arr_float_uint_1 = OpTypeArray %float %uint_1
|
||||
%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
%uint_32 = OpConstant %uint 32
|
||||
%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
|
||||
%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
|
||||
%gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%gl_InvocationID = OpVariable %_ptr_Input_int Input
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_PerVertex_0 = OpTypeStruct %v4float
|
||||
%uint_4 = OpConstant %uint 4
|
||||
%_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4
|
||||
%_ptr_Output__arr_gl_PerVertex_0_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_0_uint_4
|
||||
%gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_0_uint_4 Output
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
|
||||
; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_32
|
||||
; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
|
||||
; CHECK: %gl_in = OpVariable [[pasty]] Input
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%pos = OpVariable %_ptr_Function_v4float Function
|
||||
%21 = OpLoad %int %gl_InvocationID
|
||||
%24 = OpAccessChain %_ptr_Input_v4float %gl_in %21 %int_0
|
||||
%25 = OpLoad %v4float %24
|
||||
OpStore %pos %25
|
||||
%31 = OpLoad %int %gl_InvocationID
|
||||
%32 = OpLoad %v4float %pos
|
||||
%34 = OpAccessChain %_ptr_Output_v4float %gl_out %31 %int_0
|
||||
OpStore %34 %32
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_3);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(ElimDeadInputComponentsTest, TescOutput) {
|
||||
// Eliminate PointSize, ClipDistance, CullDistance from gl_out[]
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// layout (vertices = 4) out;
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// vec4 pos = gl_in[gl_InvocationID].gl_Position;
|
||||
// gl_out[gl_InvocationID].gl_Position = pos;
|
||||
// }
|
||||
const std::string text = R"(
|
||||
OpCapability Tessellation
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationControl %main "main" %gl_in %gl_InvocationID %gl_out
|
||||
OpExecutionMode %main OutputVertices 4
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %pos "pos"
|
||||
OpName %gl_PerVertex "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex 0 "gl_Position"
|
||||
OpName %gl_in "gl_in"
|
||||
OpName %gl_InvocationID "gl_InvocationID"
|
||||
OpName %gl_PerVertex_0 "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex_0 0 "gl_Position"
|
||||
OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
|
||||
OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
|
||||
OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
|
||||
OpName %gl_out "gl_out"
|
||||
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
|
||||
OpDecorate %gl_PerVertex Block
|
||||
OpDecorate %gl_InvocationID BuiltIn InvocationId
|
||||
OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
|
||||
OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
|
||||
OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
|
||||
OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
|
||||
OpDecorate %gl_PerVertex_0 Block
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%_arr_float_uint_1 = OpTypeArray %float %uint_1
|
||||
%gl_PerVertex = OpTypeStruct %v4float
|
||||
%uint_32 = OpConstant %uint 32
|
||||
%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
|
||||
%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
|
||||
%gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%gl_InvocationID = OpVariable %_ptr_Input_int Input
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
%uint_4 = OpConstant %uint 4
|
||||
%_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4
|
||||
%_ptr_Output__arr_gl_PerVertex_0_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_0_uint_4
|
||||
%gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_0_uint_4 Output
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
|
||||
; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_4
|
||||
; CHECK: [[pasty:%\w+]] = OpTypePointer Output [[asty]]
|
||||
; CHECK: %gl_out = OpVariable [[pasty]] Output
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%pos = OpVariable %_ptr_Function_v4float Function
|
||||
%21 = OpLoad %int %gl_InvocationID
|
||||
%24 = OpAccessChain %_ptr_Input_v4float %gl_in %21 %int_0
|
||||
%25 = OpLoad %v4float %24
|
||||
OpStore %pos %25
|
||||
%31 = OpLoad %int %gl_InvocationID
|
||||
%32 = OpLoad %v4float %pos
|
||||
%34 = OpAccessChain %_ptr_Output_v4float %gl_out %31 %int_0
|
||||
OpStore %34 %32
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_3);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, true,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(ElimDeadInputComponentsTest, TeseInput) {
|
||||
// Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// layout(triangles, ccw) in;
|
||||
// layout(fractional_odd_spacing) in;
|
||||
// layout(point_mode) in;
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// vec4 p = gl_in[1].gl_Position;
|
||||
// gl_Position = p;
|
||||
// }
|
||||
const std::string text = R"(
|
||||
OpCapability Tessellation
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationEvaluation %main "main" %gl_in %_
|
||||
OpExecutionMode %main Triangles
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
OpExecutionMode %main VertexOrderCcw
|
||||
OpExecutionMode %main PointMode
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %p "p"
|
||||
OpName %gl_PerVertex "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex 0 "gl_Position"
|
||||
OpMemberName %gl_PerVertex 1 "gl_PointSize"
|
||||
OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
|
||||
OpMemberName %gl_PerVertex 3 "gl_CullDistance"
|
||||
OpName %gl_in "gl_in"
|
||||
OpName %gl_PerVertex_0 "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex_0 0 "gl_Position"
|
||||
OpName %_ ""
|
||||
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
|
||||
OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
|
||||
OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
|
||||
OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
|
||||
OpDecorate %gl_PerVertex Block
|
||||
OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
|
||||
OpDecorate %gl_PerVertex_0 Block
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%_arr_float_uint_1 = OpTypeArray %float %uint_1
|
||||
%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
%uint_32 = OpConstant %uint 32
|
||||
%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
|
||||
%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
|
||||
%gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
|
||||
%int = OpTypeInt 32 1
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_PerVertex_0 = OpTypeStruct %v4float
|
||||
%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
|
||||
%_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
|
||||
; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_32
|
||||
; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
|
||||
; CHECK: %gl_in = OpVariable [[pasty]] Input
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%p = OpVariable %_ptr_Function_v4float Function
|
||||
%22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
|
||||
%23 = OpLoad %v4float %22
|
||||
OpStore %p %23
|
||||
%27 = OpLoad %v4float %p
|
||||
%29 = OpAccessChain %_ptr_Output_v4float %_ %int_0
|
||||
OpStore %29 %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_3);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(ElimDeadInputComponentsTest, TeseOutput) {
|
||||
// Eliminate PointSize, ClipDistance, CullDistance from gl_out
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// layout(triangles, ccw) in;
|
||||
// layout(fractional_odd_spacing) in;
|
||||
// layout(point_mode) in;
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// vec4 p = gl_in[1].gl_Position;
|
||||
// gl_Position = p;
|
||||
// }
|
||||
const std::string text = R"(
|
||||
OpCapability Tessellation
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationEvaluation %main "main" %gl_in %_
|
||||
OpExecutionMode %main Triangles
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
OpExecutionMode %main VertexOrderCcw
|
||||
OpExecutionMode %main PointMode
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %p "p"
|
||||
OpName %gl_PerVertex "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex 0 "gl_Position"
|
||||
OpName %gl_in "gl_in"
|
||||
OpName %gl_PerVertex_0 "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex_0 0 "gl_Position"
|
||||
OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
|
||||
OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
|
||||
OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
|
||||
OpName %_ ""
|
||||
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
|
||||
OpDecorate %gl_PerVertex Block
|
||||
OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
|
||||
OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
|
||||
OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
|
||||
OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
|
||||
OpDecorate %gl_PerVertex_0 Block
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%_arr_float_uint_1 = OpTypeArray %float %uint_1
|
||||
%gl_PerVertex = OpTypeStruct %v4float
|
||||
%uint_32 = OpConstant %uint 32
|
||||
%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
|
||||
%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
|
||||
%gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
|
||||
%int = OpTypeInt 32 1
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
|
||||
%_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
; CHECK: %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
|
||||
; CHECK: %_ = OpVariable %_ptr_Output_gl_PerVertex Output
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%p = OpVariable %_ptr_Function_v4float Function
|
||||
%22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
|
||||
%23 = OpLoad %v4float %22
|
||||
OpStore %p %23
|
||||
%27 = OpLoad %v4float %p
|
||||
%29 = OpAccessChain %_ptr_Output_v4float %_ %int_0
|
||||
OpStore %29 %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_3);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, true,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(ElimDeadInputComponentsTest, GeomInput) {
|
||||
// Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// layout(triangle_strip, max_vertices = 3) out;
|
||||
// layout(triangles) in;
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// for (int i = 0; i < 3; i++)
|
||||
// {
|
||||
// gl_Position = gl_in[i].gl_Position;
|
||||
// EmitVertex();
|
||||
// }
|
||||
// EndPrimitive();
|
||||
// }
|
||||
const std::string text = R"(
|
||||
OpCapability Geometry
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main" %_ %gl_in
|
||||
OpExecutionMode %main Triangles
|
||||
OpExecutionMode %main Invocations 1
|
||||
OpExecutionMode %main OutputTriangleStrip
|
||||
OpExecutionMode %main OutputVertices 3
|
||||
OpSource GLSL 460
|
||||
OpName %main "main"
|
||||
OpName %i "i"
|
||||
OpName %gl_PerVertex "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex 0 "gl_Position"
|
||||
OpName %_ ""
|
||||
OpName %gl_PerVertex_0 "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex_0 0 "gl_Position"
|
||||
OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
|
||||
OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
|
||||
OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
|
||||
OpName %gl_in "gl_in"
|
||||
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
|
||||
OpDecorate %gl_PerVertex Block
|
||||
OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
|
||||
OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
|
||||
OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
|
||||
OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
|
||||
OpDecorate %gl_PerVertex_0 Block
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_3 = OpConstant %int 3
|
||||
%bool = OpTypeBool
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%_arr_float_uint_1 = OpTypeArray %float %uint_1
|
||||
%gl_PerVertex = OpTypeStruct %v4float
|
||||
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
|
||||
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
|
||||
%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
|
||||
%_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
|
||||
%gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%int_1 = OpConstant %int 1
|
||||
; CHECK: [[asty:%\w+]] = OpTypeArray %gl_PerVertex %uint_3
|
||||
; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
|
||||
; CHECK: %gl_in = OpVariable [[pasty]] Input
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%i = OpVariable %_ptr_Function_int Function
|
||||
OpStore %i %int_0
|
||||
OpBranch %10
|
||||
%10 = OpLabel
|
||||
OpLoopMerge %12 %13 None
|
||||
OpBranch %14
|
||||
%14 = OpLabel
|
||||
%15 = OpLoad %int %i
|
||||
%18 = OpSLessThan %bool %15 %int_3
|
||||
OpBranchConditional %18 %11 %12
|
||||
%11 = OpLabel
|
||||
%32 = OpLoad %int %i
|
||||
%34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
|
||||
%35 = OpLoad %v4float %34
|
||||
%37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
|
||||
OpStore %37 %35
|
||||
OpEmitVertex
|
||||
OpBranch %13
|
||||
%13 = OpLabel
|
||||
%38 = OpLoad %int %i
|
||||
%40 = OpIAdd %int %38 %int_1
|
||||
OpStore %i %40
|
||||
OpBranch %10
|
||||
%12 = OpLabel
|
||||
OpEndPrimitive
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_3);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(ElimDeadInputComponentsTest, GeomOutput) {
|
||||
// Eliminate PointSize, ClipDistance, CullDistance from gl_out
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// layout(triangle_strip, max_vertices = 3) out;
|
||||
// layout(triangles) in;
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// for (int i = 0; i < 3; i++)
|
||||
// {
|
||||
// gl_Position = gl_in[i].gl_Position;
|
||||
// EmitVertex();
|
||||
// }
|
||||
// EndPrimitive();
|
||||
// }
|
||||
const std::string text = R"(
|
||||
OpCapability Geometry
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main" %_ %gl_in
|
||||
OpExecutionMode %main Triangles
|
||||
OpExecutionMode %main Invocations 1
|
||||
OpExecutionMode %main OutputTriangleStrip
|
||||
OpExecutionMode %main OutputVertices 3
|
||||
OpSource GLSL 460
|
||||
OpName %main "main"
|
||||
OpName %i "i"
|
||||
OpName %gl_PerVertex "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex 0 "gl_Position"
|
||||
OpMemberName %gl_PerVertex 1 "gl_PointSize"
|
||||
OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
|
||||
OpMemberName %gl_PerVertex 3 "gl_CullDistance"
|
||||
OpName %_ ""
|
||||
OpName %gl_PerVertex_0 "gl_PerVertex"
|
||||
OpMemberName %gl_PerVertex_0 0 "gl_Position"
|
||||
OpName %gl_in "gl_in"
|
||||
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
|
||||
OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
|
||||
OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
|
||||
OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
|
||||
OpDecorate %gl_PerVertex Block
|
||||
OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
|
||||
OpDecorate %gl_PerVertex_0 Block
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_3 = OpConstant %int 3
|
||||
%bool = OpTypeBool
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%_arr_float_uint_1 = OpTypeArray %float %uint_1
|
||||
%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
|
||||
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
|
||||
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
|
||||
%gl_PerVertex_0 = OpTypeStruct %v4float
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
|
||||
%_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
|
||||
%gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%int_1 = OpConstant %int 1
|
||||
; CHECK: %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
|
||||
; CHECK: %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%i = OpVariable %_ptr_Function_int Function
|
||||
OpStore %i %int_0
|
||||
OpBranch %10
|
||||
%10 = OpLabel
|
||||
OpLoopMerge %12 %13 None
|
||||
OpBranch %14
|
||||
%14 = OpLabel
|
||||
%15 = OpLoad %int %i
|
||||
%18 = OpSLessThan %bool %15 %int_3
|
||||
OpBranchConditional %18 %11 %12
|
||||
%11 = OpLabel
|
||||
%32 = OpLoad %int %i
|
||||
%34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
|
||||
%35 = OpLoad %v4float %34
|
||||
%37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
|
||||
OpStore %37 %35
|
||||
OpEmitVertex
|
||||
OpBranch %13
|
||||
%13 = OpLabel
|
||||
%38 = OpLoad %int %i
|
||||
%40 = OpIAdd %int %38 %int_1
|
||||
OpStore %i %40
|
||||
OpBranch %10
|
||||
%12 = OpLabel
|
||||
OpEndPrimitive
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_3);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, true,
|
||||
false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
|
Загрузка…
Ссылка в новой задаче