mirror of
https://gitee.com/openharmony/third_party_spirv-tools
synced 2024-11-24 16:00:01 +00:00
Add validation for execution modes
* Check rules from Execution Mode tables, 2.16.2 and the Vulkan environment spec * Allows MeshNV execution model with the following execution modes * LocalSize, LocalSizeId, OutputPoints and OutputVertices * Done to not break their validation
This commit is contained in:
parent
146eb3bdcf
commit
a77bb2e54b
@ -17,6 +17,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "source/opcode.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/val/instruction.h"
|
||||
#include "source/val/validation_state.h"
|
||||
|
||||
@ -53,6 +54,171 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) {
|
||||
<< "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_point_id)
|
||||
<< "'s function return type is not void.";
|
||||
}
|
||||
|
||||
const auto* execution_modes = _.GetExecutionModes(entry_point_id);
|
||||
if (_.HasCapability(SpvCapabilityShader)) {
|
||||
switch (execution_model) {
|
||||
case SpvExecutionModelFragment:
|
||||
if (execution_modes &&
|
||||
execution_modes->count(SpvExecutionModeOriginUpperLeft) &&
|
||||
execution_modes->count(SpvExecutionModeOriginLowerLeft)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Fragment execution model entry points can only specify "
|
||||
"one of OriginUpperLeft or OriginLowerLeft execution "
|
||||
"modes.";
|
||||
}
|
||||
if (!execution_modes ||
|
||||
(!execution_modes->count(SpvExecutionModeOriginUpperLeft) &&
|
||||
!execution_modes->count(SpvExecutionModeOriginLowerLeft))) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Fragment execution model entry points require either an "
|
||||
"OriginUpperLeft or OriginLowerLeft execution mode.";
|
||||
}
|
||||
if (execution_modes &&
|
||||
1 < std::count_if(execution_modes->begin(), execution_modes->end(),
|
||||
[](const SpvExecutionMode& mode) {
|
||||
switch (mode) {
|
||||
case SpvExecutionModeDepthGreater:
|
||||
case SpvExecutionModeDepthLess:
|
||||
case SpvExecutionModeDepthUnchanged:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Fragment execution model entry points can specify at most "
|
||||
"one of DepthGreater, DepthLess or DepthUnchanged "
|
||||
"execution modes.";
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModelTessellationControl:
|
||||
case SpvExecutionModelTessellationEvaluation:
|
||||
if (execution_modes &&
|
||||
1 < std::count_if(execution_modes->begin(), execution_modes->end(),
|
||||
[](const SpvExecutionMode& mode) {
|
||||
switch (mode) {
|
||||
case SpvExecutionModeSpacingEqual:
|
||||
case SpvExecutionModeSpacingFractionalEven:
|
||||
case SpvExecutionModeSpacingFractionalOdd:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Tessellation execution model entry points can specify at "
|
||||
"most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes.";
|
||||
}
|
||||
if (execution_modes &&
|
||||
1 < std::count_if(execution_modes->begin(), execution_modes->end(),
|
||||
[](const SpvExecutionMode& mode) {
|
||||
switch (mode) {
|
||||
case SpvExecutionModeTriangles:
|
||||
case SpvExecutionModeQuads:
|
||||
case SpvExecutionModeIsolines:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Tessellation execution model entry points can specify at "
|
||||
"most one of Triangles, Quads or Isolines execution modes.";
|
||||
}
|
||||
if (execution_modes &&
|
||||
1 < std::count_if(execution_modes->begin(), execution_modes->end(),
|
||||
[](const SpvExecutionMode& mode) {
|
||||
switch (mode) {
|
||||
case SpvExecutionModeVertexOrderCw:
|
||||
case SpvExecutionModeVertexOrderCcw:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Tessellation execution model entry points can specify at "
|
||||
"most one of VertexOrderCw or VertexOrderCcw execution "
|
||||
"modes.";
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModelGeometry:
|
||||
if (!execution_modes ||
|
||||
1 != std::count_if(execution_modes->begin(), execution_modes->end(),
|
||||
[](const SpvExecutionMode& mode) {
|
||||
switch (mode) {
|
||||
case SpvExecutionModeInputPoints:
|
||||
case SpvExecutionModeInputLines:
|
||||
case SpvExecutionModeInputLinesAdjacency:
|
||||
case SpvExecutionModeTriangles:
|
||||
case SpvExecutionModeInputTrianglesAdjacency:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Geometry execution model entry points must specify "
|
||||
"exactly one of InputPoints, InputLines, "
|
||||
"InputLinesAdjacency, Triangles or InputTrianglesAdjacency "
|
||||
"execution modes.";
|
||||
}
|
||||
if (!execution_modes ||
|
||||
1 != std::count_if(execution_modes->begin(), execution_modes->end(),
|
||||
[](const SpvExecutionMode& mode) {
|
||||
switch (mode) {
|
||||
case SpvExecutionModeOutputPoints:
|
||||
case SpvExecutionModeOutputLineStrip:
|
||||
case SpvExecutionModeOutputTriangleStrip:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Geometry execution model entry points must specify "
|
||||
"exactly one of OutputPoints, OutputLineStrip or "
|
||||
"OutputTriangleStrip execution modes.";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (spvIsVulkanEnv(_.context()->target_env)) {
|
||||
switch (execution_model) {
|
||||
case SpvExecutionModelGLCompute:
|
||||
if (!execution_modes ||
|
||||
!execution_modes->count(SpvExecutionModeLocalSize)) {
|
||||
bool ok = false;
|
||||
for (auto& i : _.ordered_instructions()) {
|
||||
if (i.opcode() == SpvOpDecorate) {
|
||||
if (i.operands().size() > 2) {
|
||||
if (i.GetOperandAs<SpvDecoration>(1) == SpvDecorationBuiltIn &&
|
||||
i.GetOperandAs<SpvBuiltIn>(2) == SpvBuiltInWorkgroupSize) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "In the Vulkan environment, GLCompute execution model "
|
||||
"entry points require either the LocalSize execution "
|
||||
"mode or an object decorated with WorkgroupSize must be "
|
||||
"specified.";
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
@ -68,6 +234,182 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
|
||||
<< "' is not the Entry Point "
|
||||
"operand of an OpEntryPoint.";
|
||||
}
|
||||
|
||||
const auto mode = inst->GetOperandAs<SpvExecutionMode>(1);
|
||||
const auto* models = _.GetExecutionModels(entry_point_id);
|
||||
switch (mode) {
|
||||
case SpvExecutionModeInvocations:
|
||||
case SpvExecutionModeInputPoints:
|
||||
case SpvExecutionModeInputLines:
|
||||
case SpvExecutionModeInputLinesAdjacency:
|
||||
case SpvExecutionModeInputTrianglesAdjacency:
|
||||
case SpvExecutionModeOutputLineStrip:
|
||||
case SpvExecutionModeOutputTriangleStrip:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
[](const SpvExecutionModel& model) {
|
||||
return model == SpvExecutionModelGeometry;
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with the Geometry execution "
|
||||
"model.";
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModeOutputPoints:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
[&_](const SpvExecutionModel& model) {
|
||||
switch (model) {
|
||||
case SpvExecutionModelGeometry:
|
||||
return true;
|
||||
case SpvExecutionModelMeshNV:
|
||||
return _.HasCapability(SpvCapabilityMeshShadingNV);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
if (_.HasCapability(SpvCapabilityMeshShadingNV)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with the Geometry or "
|
||||
"MeshNV execution model.";
|
||||
} else {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with the Geometry "
|
||||
"execution "
|
||||
"model.";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModeSpacingEqual:
|
||||
case SpvExecutionModeSpacingFractionalEven:
|
||||
case SpvExecutionModeSpacingFractionalOdd:
|
||||
case SpvExecutionModeVertexOrderCw:
|
||||
case SpvExecutionModeVertexOrderCcw:
|
||||
case SpvExecutionModePointMode:
|
||||
case SpvExecutionModeQuads:
|
||||
case SpvExecutionModeIsolines:
|
||||
if (!std::all_of(
|
||||
models->begin(), models->end(),
|
||||
[](const SpvExecutionModel& model) {
|
||||
return (model == SpvExecutionModelTessellationControl) ||
|
||||
(model == SpvExecutionModelTessellationEvaluation);
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with a tessellation "
|
||||
"execution model.";
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModeTriangles:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
[](const SpvExecutionModel& model) {
|
||||
switch (model) {
|
||||
case SpvExecutionModelGeometry:
|
||||
case SpvExecutionModelTessellationControl:
|
||||
case SpvExecutionModelTessellationEvaluation:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with a Geometry or "
|
||||
"tessellation execution model.";
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModeOutputVertices:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
[&_](const SpvExecutionModel& model) {
|
||||
switch (model) {
|
||||
case SpvExecutionModelGeometry:
|
||||
case SpvExecutionModelTessellationControl:
|
||||
case SpvExecutionModelTessellationEvaluation:
|
||||
return true;
|
||||
case SpvExecutionModelMeshNV:
|
||||
return _.HasCapability(SpvCapabilityMeshShadingNV);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
if (_.HasCapability(SpvCapabilityMeshShadingNV)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with a Geometry, "
|
||||
"tessellation or MeshNV execution model.";
|
||||
} else {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with a Geometry or "
|
||||
"tessellation execution model.";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModePixelCenterInteger:
|
||||
case SpvExecutionModeOriginUpperLeft:
|
||||
case SpvExecutionModeOriginLowerLeft:
|
||||
case SpvExecutionModeEarlyFragmentTests:
|
||||
case SpvExecutionModeDepthReplacing:
|
||||
case SpvExecutionModeDepthLess:
|
||||
case SpvExecutionModeDepthUnchanged:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
[](const SpvExecutionModel& model) {
|
||||
return model == SpvExecutionModelFragment;
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with the Fragment execution "
|
||||
"model.";
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModeLocalSizeHint:
|
||||
case SpvExecutionModeVecTypeHint:
|
||||
case SpvExecutionModeContractionOff:
|
||||
case SpvExecutionModeLocalSizeHintId:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
[](const SpvExecutionModel& model) {
|
||||
return model == SpvExecutionModelKernel;
|
||||
})) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with the Kernel execution "
|
||||
"model.";
|
||||
}
|
||||
break;
|
||||
case SpvExecutionModeLocalSize:
|
||||
case SpvExecutionModeLocalSizeId:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
[&_](const SpvExecutionModel& model) {
|
||||
switch (model) {
|
||||
case SpvExecutionModelKernel:
|
||||
case SpvExecutionModelGLCompute:
|
||||
return true;
|
||||
case SpvExecutionModelMeshNV:
|
||||
return _.HasCapability(SpvCapabilityMeshShadingNV);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
if (_.HasCapability(SpvCapabilityMeshShadingNV)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with a Kernel, GLCompute "
|
||||
"or MeshNV execution model.";
|
||||
} else {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode can only be used with a Kernel or "
|
||||
"GLCompute "
|
||||
"execution model.";
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (spvIsVulkanEnv(_.context()->target_env)) {
|
||||
if (mode == SpvExecutionModeOriginLowerLeft) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "In the Vulkan environment, the OriginLowerLeft execution mode "
|
||||
"must not be used.";
|
||||
}
|
||||
if (mode == SpvExecutionModePixelCenterInteger) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "In the Vulkan environment, the PixelCenterInteger execution "
|
||||
"mode must not be used.";
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
@ -79,6 +421,7 @@ spv_result_t ModeSettingPass(ValidationState_t& _, const Instruction* inst) {
|
||||
if (auto error = ValidateEntryPoint(_, inst)) return error;
|
||||
break;
|
||||
case SpvOpExecutionMode:
|
||||
case SpvOpExecutionModeId:
|
||||
if (auto error = ValidateExecutionMode(_, inst)) return error;
|
||||
break;
|
||||
default:
|
||||
|
@ -5523,6 +5523,7 @@ TEST_F(AggressiveDCETest, SafelyRemoveDecorateString) {
|
||||
OpExtension "SPV_GOOGLE_hlsl_functionality1"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
)";
|
||||
|
||||
const std::string body_before =
|
||||
|
@ -287,6 +287,7 @@ TEST_F(BlockMergeTest, PhiInSuccessorOfMergedBlock) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -324,6 +325,7 @@ TEST_F(BlockMergeTest, UpdateMergeInstruction) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -358,6 +360,7 @@ TEST_F(BlockMergeTest, TwoMergeBlocksCannotBeMerged) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -398,6 +401,7 @@ TEST_F(BlockMergeTest, MergeContinue) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -431,6 +435,7 @@ TEST_F(BlockMergeTest, TwoHeadersCannotBeMerged) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -532,6 +537,7 @@ TEST_F(BlockMergeTest, DontMergeKill) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%functy = OpTypeFunction %void
|
||||
@ -564,6 +570,7 @@ TEST_F(BlockMergeTest, DontMergeUnreachable) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%functy = OpTypeFunction %void
|
||||
@ -596,6 +603,7 @@ TEST_F(BlockMergeTest, DontMergeReturn) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%functy = OpTypeFunction %void
|
||||
@ -628,6 +636,7 @@ TEST_F(BlockMergeTest, DontMergeSwitch) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%int = OpTypeInt 32 1
|
||||
@ -664,6 +673,7 @@ TEST_F(BlockMergeTest, DontMergeReturnValue) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%functy = OpTypeFunction %void
|
||||
@ -705,6 +715,7 @@ TEST_F(BlockMergeTest, MergeHeaders) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%functy = OpTypeFunction %void
|
||||
|
@ -589,6 +589,7 @@ TEST_F(CCPTest, UpdateSubsequentPhisToVarying) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func" %in
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%int = OpTypeInt 32 1
|
||||
@ -743,6 +744,7 @@ TEST_F(CCPTest, NullBranchCondition) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%int = OpTypeInt 32 1
|
||||
@ -774,6 +776,7 @@ TEST_F(CCPTest, UndefBranchCondition) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%int = OpTypeInt 32 1
|
||||
@ -805,6 +808,7 @@ TEST_F(CCPTest, NullSwitchCondition) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 1
|
||||
%null = OpConstantNull %int
|
||||
@ -835,6 +839,7 @@ TEST_F(CCPTest, UndefSwitchCondition) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 1
|
||||
%undef = OpUndef %int
|
||||
@ -865,6 +870,7 @@ TEST_F(CCPTest, CompositeConstructOfGlobalValue) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func" %in
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 1
|
||||
%bool = OpTypeBool
|
||||
|
@ -91,6 +91,7 @@ TEST_F(CFGCleanupTest, RemoveDecorations) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %x "x"
|
||||
OpName %dead "dead"
|
||||
@ -123,6 +124,7 @@ TEST_F(CFGCleanupTest, RemoveDecorations) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %x "x"
|
||||
OpDecorate %x RelaxedPrecision
|
||||
@ -153,6 +155,7 @@ TEST_F(CFGCleanupTest, UpdatePhis) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %y %outparm
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %y "y"
|
||||
OpName %outparm "outparm"
|
||||
@ -194,6 +197,7 @@ TEST_F(CFGCleanupTest, UpdatePhis) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %y %outparm
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %y "y"
|
||||
OpName %outparm "outparm"
|
||||
@ -272,6 +276,7 @@ TEST_F(CFGCleanupTest, RemovePhiArgsFromFarBlocks) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %y %outparm
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %y "y"
|
||||
OpName %outparm "outparm"
|
||||
@ -319,6 +324,7 @@ TEST_F(CFGCleanupTest, RemovePhiArgsFromFarBlocks) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %y %outparm
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %y "y"
|
||||
OpName %outparm "outparm"
|
||||
@ -370,6 +376,7 @@ TEST_F(CFGCleanupTest, RemovePhiConstantArgs) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %y %outparm
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %y "y"
|
||||
OpName %outparm "outparm"
|
||||
@ -410,6 +417,7 @@ TEST_F(CFGCleanupTest, RemovePhiConstantArgs) {
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %y %outparm
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %y "y"
|
||||
OpName %outparm "outparm"
|
||||
|
@ -38,6 +38,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -71,6 +72,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -104,6 +106,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -139,6 +142,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -177,6 +181,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -219,6 +224,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -255,6 +261,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -289,6 +296,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -326,6 +334,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -361,6 +370,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -399,6 +409,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -435,6 +446,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -468,6 +480,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -505,6 +518,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -543,6 +557,7 @@ OpCapability Addresses
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -579,6 +594,7 @@ OpCapability Addresses
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -616,6 +632,7 @@ OpCapability Addresses
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -646,6 +663,7 @@ TEST_F(CombineAccessChainsTest, NoIndexAccessChains) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%ptr_Workgroup_uint = OpTypePointer Workgroup %uint
|
||||
@ -673,6 +691,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -700,6 +719,7 @@ OpCapability VariablePointers
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
@ -729,6 +749,7 @@ OpCapability Addresses
|
||||
OpExtension "SPV_KHR_variable_pointers"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%int = OpTypeInt 32 1
|
||||
|
@ -2018,6 +2018,7 @@ TEST_F(DeadBranchElimTest, ReorderBlocks) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -2045,6 +2046,7 @@ TEST_F(DeadBranchElimTest, ReorderBlocksMultiple) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -2073,6 +2075,7 @@ TEST_F(DeadBranchElimTest, ReorderBlocksMultiple2) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
|
@ -31,6 +31,7 @@ std::string PreambleAssembly() {
|
||||
R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %hue %saturation %value
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %main "main"
|
||||
OpName %void_fn "void_fn"
|
||||
OpName %hue "hue"
|
||||
|
@ -2601,6 +2601,7 @@ TEST_F(InlineTest, OpKill) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%voidfuncty = OpTypeFunction %void
|
||||
%main = OpFunction %void None %voidfuncty
|
||||
@ -2630,6 +2631,7 @@ TEST_F(InlineTest, OpKillWithTrailingInstructions) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -2679,6 +2681,7 @@ TEST_F(InlineTest, OpKillInIf) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -2731,6 +2734,7 @@ TEST_F(InlineTest, OpKillInLoop) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
|
@ -1084,7 +1084,7 @@ TEST_F(VectorDCETest, VectorIntoCompositeConstruct) {
|
||||
const std::string text = R"(OpCapability Linkage
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %1 "EntryPoint_Main" %2 %3
|
||||
OpEntryPoint Fragment %1 "EntryPoint_Main" %2 %3
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
OpDecorate %2 Location 0
|
||||
OpDecorate %_struct_4 Block
|
||||
|
@ -54,6 +54,7 @@ add_spvtools_unittest(TARGET val_ijklmnop
|
||||
val_layout_test.cpp
|
||||
val_literals_test.cpp
|
||||
val_logicals_test.cpp
|
||||
val_modes_test.cpp
|
||||
val_non_uniform_test.cpp
|
||||
val_primitives_test.cpp
|
||||
${VAL_TEST_COMMON_SRCS}
|
||||
|
@ -34,6 +34,7 @@ TEST_F(ValidateAdjacency, OpPhiBeginsModuleFail) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -60,6 +61,7 @@ TEST_F(ValidateAdjacency, OpLoopMergeEndsModuleFail) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%main = OpFunction %void None %func
|
||||
@ -80,6 +82,7 @@ TEST_F(ValidateAdjacency, OpSelectionMergeEndsModuleFail) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%main = OpFunction %void None %func
|
||||
@ -103,6 +106,9 @@ std::string GenerateShaderCode(
|
||||
ss << capabilities_and_extensions << "\n";
|
||||
ss << "OpMemoryModel Logical GLSL450\n";
|
||||
ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%string = OpString ""
|
||||
|
@ -39,6 +39,7 @@ OpCapability Matrix
|
||||
%ext_inst = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
|
@ -41,6 +41,7 @@ OpCapability Int64
|
||||
ss << R"(
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
|
@ -41,6 +41,14 @@ OpCapability Int64
|
||||
ss << capabilities_and_extensions;
|
||||
ss << "OpMemoryModel Logical GLSL450\n";
|
||||
ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
} else if (execution_model == "Geometry") {
|
||||
ss << "OpExecutionMode %main InputPoints\n";
|
||||
ss << "OpExecutionMode %main OutputPoints\n";
|
||||
} else if (execution_model == "GLCompute") {
|
||||
ss << "OpExecutionMode %main LocalSize 1 1 1\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
|
@ -42,6 +42,7 @@ OpCapability Float64)";
|
||||
R"(
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
|
@ -243,10 +243,20 @@ TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InMain) {
|
||||
if (0 == std::strcmp(execution_model, "Fragment")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OriginUpperLeft\n";
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
}
|
||||
}
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
if (0 == std::strcmp(execution_model, "Geometry")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
<< " InputPoints\n";
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OutputPoints\n";
|
||||
}
|
||||
if (0 == std::strcmp(execution_model, "GLCompute")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " LocalSize 1 1 1\n";
|
||||
}
|
||||
entry_point.execution_modes = execution_modes.str();
|
||||
|
||||
@ -300,10 +310,20 @@ TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InFunction) {
|
||||
if (0 == std::strcmp(execution_model, "Fragment")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OriginUpperLeft\n";
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
}
|
||||
}
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
if (0 == std::strcmp(execution_model, "Geometry")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
<< " InputPoints\n";
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OutputPoints\n";
|
||||
}
|
||||
if (0 == std::strcmp(execution_model, "GLCompute")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " LocalSize 1 1 1\n";
|
||||
}
|
||||
entry_point.execution_modes = execution_modes.str();
|
||||
|
||||
@ -366,10 +386,20 @@ TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, Variable) {
|
||||
if (0 == std::strcmp(execution_model, "Fragment")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OriginUpperLeft\n";
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
}
|
||||
}
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
if (0 == std::strcmp(execution_model, "Geometry")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
<< " InputPoints\n";
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OutputPoints\n";
|
||||
}
|
||||
if (0 == std::strcmp(execution_model, "GLCompute")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " LocalSize 1 1 1\n";
|
||||
}
|
||||
entry_point.execution_modes = execution_modes.str();
|
||||
|
||||
@ -1542,10 +1572,20 @@ TEST_P(ValidateVulkanCombineBuiltInArrayedVariable, Variable) {
|
||||
if (0 == std::strcmp(execution_model, "Fragment")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OriginUpperLeft\n";
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
}
|
||||
}
|
||||
if (0 == std::strcmp(built_in, "FragDepth")) {
|
||||
if (0 == std::strcmp(execution_model, "Geometry")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " DepthReplacing\n";
|
||||
<< " InputPoints\n";
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " OutputPoints\n";
|
||||
}
|
||||
if (0 == std::strcmp(execution_model, "GLCompute")) {
|
||||
execution_modes << "OpExecutionMode %" << entry_point.name
|
||||
<< " LocalSize 1 1 1\n";
|
||||
}
|
||||
entry_point.execution_modes = execution_modes.str();
|
||||
|
||||
@ -1869,6 +1909,8 @@ OpMemberDecorate %output_type 0 BuiltIn Position
|
||||
OpStore %output_pos %pos
|
||||
)";
|
||||
generator.entry_points_.push_back(std::move(entry_point));
|
||||
generator.entry_points_[0].execution_modes =
|
||||
"OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
|
||||
|
||||
CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
@ -1904,6 +1946,8 @@ OpMemberDecorate %output_type 0 BuiltIn Position
|
||||
OpStore %output_pos %pos
|
||||
)";
|
||||
generator.entry_points_.push_back(std::move(entry_point));
|
||||
generator.entry_points_[0].execution_modes =
|
||||
"OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
|
||||
|
||||
CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
@ -1942,6 +1986,8 @@ OpMemberDecorate %output_type 0 BuiltIn FragCoord
|
||||
OpStore %output_pos %pos
|
||||
)";
|
||||
generator.entry_points_.push_back(std::move(entry_point));
|
||||
generator.entry_points_[0].execution_modes =
|
||||
"OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
|
||||
|
||||
CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
|
@ -598,9 +598,12 @@ std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
std::string(kVoidFVoid), TessellationDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
" OpEntryPoint Geometry %func \"shader\"" +
|
||||
" OpExecutionMode %func InputPoints" +
|
||||
" OpExecutionMode %func OutputPoints" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
" OpEntryPoint Fragment %func \"shader\"" +
|
||||
" OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
" OpEntryPoint GLCompute %func \"shader\"" +
|
||||
@ -659,6 +662,8 @@ INSTANTIATE_TEST_CASE_P(ExecutionMode, ValidateCapability,
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func Invocations 42" +
|
||||
" OpExecutionMode %func InputPoints" +
|
||||
" OpExecutionMode %func OutputPoints" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint TessellationControl %func \"shader\" "
|
||||
@ -681,20 +686,22 @@ std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpExecutionMode %func VertexOrderCcw" +
|
||||
std::string(kVoidFVoid), TessellationDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func PixelCenterInteger" +
|
||||
" OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func OriginLowerLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func EarlyFragmentTests" +
|
||||
" OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint TessellationControl %func \"shader\" "
|
||||
@ -705,20 +712,24 @@ std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpExecutionMode %func Xfb" +
|
||||
std::string(kVoidFVoid), std::vector<std::string>{"TransformFeedback"}),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func DepthReplacing" +
|
||||
" OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func DepthGreater" +
|
||||
" OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func DepthLess" +
|
||||
" OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" "
|
||||
"OpEntryPoint Fragment %func \"shader\" "
|
||||
"OpExecutionMode %func DepthUnchanged" +
|
||||
" OpExecutionMode %func OriginUpperLeft" +
|
||||
std::string(kVoidFVoid), ShaderDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Kernel %func \"shader\" "
|
||||
@ -731,18 +742,22 @@ std::make_pair(std::string(kGLSL450MemoryModel) +
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func InputPoints" +
|
||||
" OpExecutionMode %func OutputPoints" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func InputLines" +
|
||||
" OpExecutionMode %func OutputLineStrip" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func InputLinesAdjacency" +
|
||||
" OpExecutionMode %func OutputLineStrip" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func Triangles" +
|
||||
" OpExecutionMode %func OutputTriangleStrip" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint TessellationControl %func \"shader\" "
|
||||
@ -751,6 +766,7 @@ std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func InputTrianglesAdjacency" +
|
||||
" OpExecutionMode %func OutputTriangleStrip" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint TessellationControl %func \"shader\" "
|
||||
@ -763,6 +779,8 @@ std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func OutputVertices 42" +
|
||||
" OpExecutionMode %func OutputPoints" +
|
||||
" OpExecutionMode %func InputPoints" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint TessellationControl %func \"shader\" "
|
||||
@ -771,14 +789,17 @@ std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func OutputPoints" +
|
||||
" OpExecutionMode %func InputPoints" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func OutputLineStrip" +
|
||||
" OpExecutionMode %func InputLines" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kOpenCLMemoryModel) +
|
||||
"OpEntryPoint Geometry %func \"shader\" "
|
||||
"OpExecutionMode %func OutputTriangleStrip" +
|
||||
" OpExecutionMode %func Triangles" +
|
||||
std::string(kVoidFVoid), GeometryDependencies()),
|
||||
std::make_pair(std::string(kGLSL450MemoryModel) +
|
||||
"OpEntryPoint Kernel %func \"shader\" "
|
||||
|
@ -1206,6 +1206,7 @@ TEST_F(ValidateCFG, LoopWithZeroBackEdgesBad) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %loop "loop"
|
||||
%voidt = OpTypeVoid
|
||||
%funct = OpTypeFunction %voidt
|
||||
@ -1231,6 +1232,7 @@ TEST_F(ValidateCFG, LoopWithBackEdgeFromUnreachableContinueConstructGood) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %loop "loop"
|
||||
%voidt = OpTypeVoid
|
||||
%funct = OpTypeFunction %voidt
|
||||
@ -1465,6 +1467,7 @@ TEST_F(ValidateCFG, StructuredCFGBranchIntoSelectionBody) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
@ -1779,6 +1782,7 @@ TEST_F(ValidateCFG, InvalidCaseExit) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "func"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 32 0
|
||||
%4 = OpTypeFunction %2
|
||||
@ -1811,6 +1815,7 @@ TEST_F(ValidateCFG, GoodCaseExitsToOuterConstructs) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
|
@ -41,6 +41,9 @@ OpCapability Float64
|
||||
ss << capabilities_and_extensions;
|
||||
ss << "OpMemoryModel Logical GLSL450\n";
|
||||
ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
|
@ -42,6 +42,7 @@ OpCapability Float64)";
|
||||
R"(
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
|
@ -90,6 +90,7 @@ TEST_F(ValidateDecorations, ValidateOpMemberDecorateOutOfBound) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "Main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
OpMemberDecorate %_struct_2 1 RelaxedPrecision
|
||||
%void = OpTypeVoid
|
||||
%4 = OpTypeFunction %void
|
||||
@ -286,6 +287,8 @@ TEST_F(ValidateDecorations, MultipleBuiltInObjectsConsumedByOpEntryPointBad) {
|
||||
OpCapability Geometry
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main" %in_1 %in_2
|
||||
OpExecutionMode %main InputPoints
|
||||
OpExecutionMode %main OutputPoints
|
||||
OpMemberDecorate %struct_1 0 BuiltIn InvocationId
|
||||
OpMemberDecorate %struct_2 0 BuiltIn Position
|
||||
%int = OpTypeInt 32 1
|
||||
@ -318,6 +321,8 @@ TEST_F(ValidateDecorations,
|
||||
OpCapability Geometry
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main" %in_1 %out_1
|
||||
OpExecutionMode %main InputPoints
|
||||
OpExecutionMode %main OutputPoints
|
||||
OpMemberDecorate %struct_1 0 BuiltIn InvocationId
|
||||
OpMemberDecorate %struct_2 0 BuiltIn Position
|
||||
%int = OpTypeInt 32 1
|
||||
@ -345,6 +350,8 @@ TEST_F(ValidateDecorations, NoBuiltInObjectsConsumedByOpEntryPointGood) {
|
||||
OpCapability Geometry
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main" %in_1 %out_1
|
||||
OpExecutionMode %main InputPoints
|
||||
OpExecutionMode %main OutputPoints
|
||||
%int = OpTypeInt 32 1
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
@ -3037,6 +3044,7 @@ TEST_F(ValidateDecorations, EntryPointVariableWrongStorageClass) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "func" %var
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 0
|
||||
%ptr_int_Workgroup = OpTypePointer Workgroup %int
|
||||
|
@ -44,6 +44,9 @@ OpCapability DerivativeControl
|
||||
<< " %f32_var_input"
|
||||
<< " %f32vec4_var_input"
|
||||
<< "\n";
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
|
@ -107,6 +107,9 @@ OpCapability Int64
|
||||
<< " %u32vec2_input"
|
||||
<< " %u64_input"
|
||||
<< "\n";
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
|
@ -424,6 +424,8 @@ TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) {
|
||||
OpCapability Geometry
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main" %ptr_builtin_1
|
||||
OpExecutionMode %main InputPoints
|
||||
OpExecutionMode %main OutputPoints
|
||||
OpMemberDecorate %struct_1 0 BuiltIn InvocationId
|
||||
%int = OpTypeInt 32 1
|
||||
%void = OpTypeVoid
|
||||
@ -448,6 +450,8 @@ TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceStorageClassBad) {
|
||||
OpCapability Geometry
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main" %in_1
|
||||
OpExecutionMode %main InputPoints
|
||||
OpExecutionMode %main OutputPoints
|
||||
OpMemberDecorate %struct_1 0 BuiltIn InvocationId
|
||||
%int = OpTypeInt 32 1
|
||||
%void = OpTypeVoid
|
||||
|
@ -56,6 +56,9 @@ OpCapability ImageBuffer
|
||||
ss << capabilities_and_extensions;
|
||||
ss << "OpMemoryModel Logical GLSL450\n";
|
||||
ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
@ -374,7 +377,8 @@ OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
|
||||
if (include_entry_point) {
|
||||
ss << "OpEntryPoint Fragment %main \"main\"";
|
||||
ss << "OpEntryPoint Fragment %main \"main\"\n";
|
||||
ss << "OpExecutionMode %main OriginUpperLeft";
|
||||
}
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
|
@ -31,6 +31,7 @@ TEST_F(ValidateInterfacesTest, EntryPointMissingInput) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "func"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 32 0
|
||||
%4 = OpTypePointer Input %3
|
||||
@ -56,6 +57,7 @@ TEST_F(ValidateInterfacesTest, EntryPointMissingOutput) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "func"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 32 0
|
||||
%4 = OpTypePointer Output %3
|
||||
@ -81,6 +83,7 @@ TEST_F(ValidateInterfacesTest, InterfaceMissingUseInSubfunction) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "func"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 32 0
|
||||
%4 = OpTypePointer Input %3
|
||||
@ -112,6 +115,7 @@ OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "func" %2
|
||||
OpEntryPoint Fragment %1 "func2"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%3 = OpTypeVoid
|
||||
%4 = OpTypeInt 32 0
|
||||
%5 = OpTypePointer Input %4
|
||||
@ -138,6 +142,7 @@ OpCapability Shader
|
||||
OpCapability VariablePointers
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "func"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 32 0
|
||||
%4 = OpTypePointer Input %3
|
||||
|
@ -481,6 +481,7 @@ TEST_F(ValidateEntryPoint, FunctionIsTargetOfEntryPointAndFunctionCallBad) {
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %foo "foo"
|
||||
OpExecutionMode %foo OriginUpperLeft
|
||||
%voidt = OpTypeVoid
|
||||
%funct = OpTypeFunction %voidt
|
||||
%foo = OpFunction %voidt None %funct
|
||||
|
@ -43,6 +43,7 @@ OpCapability Float64)";
|
||||
%ext_inst = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
|
770
test/val/val_modes_test.cpp
Normal file
770
test/val/val_modes_test.cpp
Normal file
@ -0,0 +1,770 @@
|
||||
// Copyright (c) 2018 Google LLC.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "test/test_fixture.h"
|
||||
#include "test/unit_spirv.h"
|
||||
#include "test/val/val_fixtures.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace val {
|
||||
namespace {
|
||||
|
||||
using ::testing::Combine;
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Values;
|
||||
using ::testing::ValuesIn;
|
||||
|
||||
using ValidateMode = spvtest::ValidateBase<bool>;
|
||||
|
||||
const std::string kVoidFunction = R"(%void = OpTypeVoid
|
||||
%void_fn = OpTypeFunction %void
|
||||
%main = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
TEST_F(ValidateMode, GLComputeNoMode) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main"
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, GLComputeNoModeVulkan) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main"
|
||||
)" + kVoidFunction;
|
||||
|
||||
spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(spirv, env);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("In the Vulkan environment, GLCompute execution model entry "
|
||||
"points require either the LocalSize execution mode or an "
|
||||
"object decorated with WorkgroupSize must be specified."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, GLComputeNoModeVulkanWorkgroupSize) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main"
|
||||
OpDecorate %int3_1 BuiltIn WorkgroupSize
|
||||
%int = OpTypeInt 32 0
|
||||
%int3 = OpTypeVector %int 3
|
||||
%int_1 = OpConstant %int 1
|
||||
%int3_1 = OpConstantComposite %int3 %int_1 %int_1 %int_1
|
||||
)" + kVoidFunction;
|
||||
|
||||
spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(spirv, env);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, GLComputeVulkanLocalSize) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main"
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
)" + kVoidFunction;
|
||||
|
||||
spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(spirv, env);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentOriginLowerLeftVulkan) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
)" + kVoidFunction;
|
||||
|
||||
spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(spirv, env);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("In the Vulkan environment, the OriginLowerLeft "
|
||||
"execution mode must not be used."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentPixelCenterIntegerVulkan) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpExecutionMode %main PixelCenterInteger
|
||||
)" + kVoidFunction;
|
||||
|
||||
spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(spirv, env);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("In the Vulkan environment, the PixelCenterInteger "
|
||||
"execution mode must not be used."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, GeometryNoOutputMode) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Geometry
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main"
|
||||
OpExecutionMode %main InputPoints
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Geometry execution model entry points must specify "
|
||||
"exactly one of OutputPoints, OutputLineStrip or "
|
||||
"OutputTriangleStrip execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, GeometryNoInputMode) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Geometry
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Geometry %main "main"
|
||||
OpExecutionMode %main OutputPoints
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Geometry execution model entry points must specify exactly "
|
||||
"one of InputPoints, InputLines, InputLinesAdjacency, "
|
||||
"Triangles or InputTrianglesAdjacency execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentNoOrigin) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Fragment execution model entry points require either an "
|
||||
"OriginUpperLeft or OriginLowerLeft execution mode."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentBothOrigins) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Fragment execution model entry points can only specify one of "
|
||||
"OriginUpperLeft or OriginLowerLeft execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentDepthGreaterAndLess) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpExecutionMode %main DepthGreater
|
||||
OpExecutionMode %main DepthLess
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Fragment execution model entry points can specify at "
|
||||
"most one of DepthGreater, DepthLess or DepthUnchanged "
|
||||
"execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentDepthGreaterAndUnchanged) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpExecutionMode %main DepthGreater
|
||||
OpExecutionMode %main DepthUnchanged
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Fragment execution model entry points can specify at "
|
||||
"most one of DepthGreater, DepthLess or DepthUnchanged "
|
||||
"execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentDepthLessAndUnchanged) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpExecutionMode %main DepthLess
|
||||
OpExecutionMode %main DepthUnchanged
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Fragment execution model entry points can specify at "
|
||||
"most one of DepthGreater, DepthLess or DepthUnchanged "
|
||||
"execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, FragmentAllDepths) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpExecutionMode %main DepthGreater
|
||||
OpExecutionMode %main DepthLess
|
||||
OpExecutionMode %main DepthUnchanged
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Fragment execution model entry points can specify at "
|
||||
"most one of DepthGreater, DepthLess or DepthUnchanged "
|
||||
"execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, TessellationControlSpacingEqualAndFractionalOdd) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationControl %main "main"
|
||||
OpExecutionMode %main SpacingEqual
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, TessellationControlSpacingEqualAndSpacingFractionalEven) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationControl %main "main"
|
||||
OpExecutionMode %main SpacingEqual
|
||||
OpExecutionMode %main SpacingFractionalEven
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode,
|
||||
TessellationControlSpacingFractionalOddAndSpacingFractionalEven) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationControl %main "main"
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
OpExecutionMode %main SpacingFractionalEven
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, TessellationControlAllSpacing) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationControl %main "main"
|
||||
OpExecutionMode %main SpacingEqual
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
OpExecutionMode %main SpacingFractionalEven
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode,
|
||||
TessellationEvaluationSpacingEqualAndSpacingFractionalOdd) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationEvaluation %main "main"
|
||||
OpExecutionMode %main SpacingEqual
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode,
|
||||
TessellationEvaluationSpacingEqualAndSpacingFractionalEven) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationEvaluation %main "main"
|
||||
OpExecutionMode %main SpacingEqual
|
||||
OpExecutionMode %main SpacingFractionalEven
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode,
|
||||
TessellationEvaluationSpacingFractionalOddAndSpacingFractionalEven) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationEvaluation %main "main"
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
OpExecutionMode %main SpacingFractionalEven
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, TessellationEvaluationAllSpacing) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationEvaluation %main "main"
|
||||
OpExecutionMode %main SpacingEqual
|
||||
OpExecutionMode %main SpacingFractionalOdd
|
||||
OpExecutionMode %main SpacingFractionalEven
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify "
|
||||
"at most one of SpacingEqual, SpacingFractionalOdd or "
|
||||
"SpacingFractionalEven execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, TessellationControlBothVertex) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationControl %main "main"
|
||||
OpExecutionMode %main VertexOrderCw
|
||||
OpExecutionMode %main VertexOrderCcw
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify at most "
|
||||
"one of VertexOrderCw or VertexOrderCcw execution modes."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMode, TessellationEvaluationBothVertex) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Tessellation
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TessellationEvaluation %main "main"
|
||||
OpExecutionMode %main VertexOrderCw
|
||||
OpExecutionMode %main VertexOrderCcw
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Tessellation execution model entry points can specify at most "
|
||||
"one of VertexOrderCw or VertexOrderCcw execution modes."));
|
||||
}
|
||||
|
||||
using ValidateModeGeometry = spvtest::ValidateBase<std::tuple<
|
||||
std::tuple<std::string, std::string, std::string, std::string, std::string>,
|
||||
std::tuple<std::string, std::string, std::string>>>;
|
||||
|
||||
TEST_P(ValidateModeGeometry, ExecutionMode) {
|
||||
std::vector<std::string> input_modes;
|
||||
std::vector<std::string> output_modes;
|
||||
input_modes.push_back(std::get<0>(std::get<0>(GetParam())));
|
||||
input_modes.push_back(std::get<1>(std::get<0>(GetParam())));
|
||||
input_modes.push_back(std::get<2>(std::get<0>(GetParam())));
|
||||
input_modes.push_back(std::get<3>(std::get<0>(GetParam())));
|
||||
input_modes.push_back(std::get<4>(std::get<0>(GetParam())));
|
||||
output_modes.push_back(std::get<0>(std::get<1>(GetParam())));
|
||||
output_modes.push_back(std::get<1>(std::get<1>(GetParam())));
|
||||
output_modes.push_back(std::get<2>(std::get<1>(GetParam())));
|
||||
|
||||
std::ostringstream sstr;
|
||||
sstr << "OpCapability Geometry\n";
|
||||
sstr << "OpMemoryModel Logical GLSL450\n";
|
||||
sstr << "OpEntryPoint Geometry %main \"main\"\n";
|
||||
size_t num_input_modes = 0;
|
||||
for (auto input : input_modes) {
|
||||
if (!input.empty()) {
|
||||
num_input_modes++;
|
||||
sstr << "OpExecutionMode %main " << input << "\n";
|
||||
}
|
||||
}
|
||||
size_t num_output_modes = 0;
|
||||
for (auto output : output_modes) {
|
||||
if (!output.empty()) {
|
||||
num_output_modes++;
|
||||
sstr << "OpExecutionMode %main " << output << "\n";
|
||||
}
|
||||
}
|
||||
sstr << "%void = OpTypeVoid\n";
|
||||
sstr << "%void_fn = OpTypeFunction %void\n";
|
||||
sstr << "%int = OpTypeInt 32 0\n";
|
||||
sstr << "%int1 = OpConstant %int 1\n";
|
||||
sstr << "%main = OpFunction %void None %void_fn\n";
|
||||
sstr << "%entry = OpLabel\n";
|
||||
sstr << "OpReturn\n";
|
||||
sstr << "OpFunctionEnd\n";
|
||||
|
||||
CompileSuccessfully(sstr.str());
|
||||
if (num_input_modes == 1 && num_output_modes == 1) {
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
|
||||
} else {
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
if (num_input_modes != 1) {
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Geometry execution model entry points must "
|
||||
"specify exactly one of InputPoints, InputLines, "
|
||||
"InputLinesAdjacency, Triangles or "
|
||||
"InputTrianglesAdjacency execution modes."));
|
||||
} else {
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Geometry execution model entry points must specify "
|
||||
"exactly one of OutputPoints, OutputLineStrip or "
|
||||
"OutputTriangleStrip execution modes."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
GeometryRequiredModes, ValidateModeGeometry,
|
||||
Combine(Combine(Values("InputPoints", ""), Values("InputLines", ""),
|
||||
Values("InputLinesAdjacency", ""), Values("Triangles", ""),
|
||||
Values("InputTrianglesAdjacency", "")),
|
||||
Combine(Values("OutputPoints", ""), Values("OutputLineStrip", ""),
|
||||
Values("OutputTriangleStrip", ""))));
|
||||
|
||||
using ValidateModeExecution =
|
||||
spvtest::ValidateBase<std::tuple<spv_result_t, std::string, std::string,
|
||||
std::string, spv_target_env>>;
|
||||
|
||||
TEST_P(ValidateModeExecution, ExecutionMode) {
|
||||
const spv_result_t expectation = std::get<0>(GetParam());
|
||||
const std::string error = std::get<1>(GetParam());
|
||||
const std::string model = std::get<2>(GetParam());
|
||||
const std::string mode = std::get<3>(GetParam());
|
||||
const spv_target_env env = std::get<4>(GetParam());
|
||||
|
||||
std::ostringstream sstr;
|
||||
sstr << "OpCapability Shader\n";
|
||||
sstr << "OpCapability Geometry\n";
|
||||
sstr << "OpCapability Tessellation\n";
|
||||
sstr << "OpCapability TransformFeedback\n";
|
||||
if (!spvIsVulkanEnv(env)) {
|
||||
sstr << "OpCapability Kernel\n";
|
||||
if (env == SPV_ENV_UNIVERSAL_1_3) {
|
||||
sstr << "OpCapability SubgroupDispatch\n";
|
||||
}
|
||||
}
|
||||
sstr << "OpMemoryModel Logical GLSL450\n";
|
||||
sstr << "OpEntryPoint " << model << " %main \"main\"\n";
|
||||
if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 ||
|
||||
mode.find("SubgroupsPerWorkgroupId") == 0) {
|
||||
sstr << "OpExecutionModeId %main " << mode << "\n";
|
||||
} else {
|
||||
sstr << "OpExecutionMode %main " << mode << "\n";
|
||||
}
|
||||
if (model == "Geometry") {
|
||||
if (!(mode.find("InputPoints") == 0 || mode.find("InputLines") == 0 ||
|
||||
mode.find("InputLinesAdjacency") == 0 ||
|
||||
mode.find("Triangles") == 0 ||
|
||||
mode.find("InputTrianglesAdjacency") == 0)) {
|
||||
// Exactly one of the above modes is required for Geometry shaders.
|
||||
sstr << "OpExecutionMode %main InputPoints\n";
|
||||
}
|
||||
if (!(mode.find("OutputPoints") == 0 || mode.find("OutputLineStrip") == 0 ||
|
||||
mode.find("OutputTriangleStrip") == 0)) {
|
||||
// Exactly one of the above modes is required for Geometry shaders.
|
||||
sstr << "OpExecutionMode %main OutputPoints\n";
|
||||
}
|
||||
} else if (model == "Fragment") {
|
||||
if (!(mode.find("OriginUpperLeft") == 0 ||
|
||||
mode.find("OriginLowerLeft") == 0)) {
|
||||
// Exactly one of the above modes is required for Fragment shaders.
|
||||
sstr << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
}
|
||||
sstr << "%void = OpTypeVoid\n";
|
||||
sstr << "%void_fn = OpTypeFunction %void\n";
|
||||
sstr << "%int = OpTypeInt 32 0\n";
|
||||
sstr << "%int1 = OpConstant %int 1\n";
|
||||
sstr << "%main = OpFunction %void None %void_fn\n";
|
||||
sstr << "%entry = OpLabel\n";
|
||||
sstr << "OpReturn\n";
|
||||
sstr << "OpFunctionEnd\n";
|
||||
|
||||
CompileSuccessfully(sstr.str(), env);
|
||||
EXPECT_THAT(expectation, ValidateInstructions(env));
|
||||
if (expectation != SPV_SUCCESS) {
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeGeometryOnlyGoodSpv10, ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""), Values("Geometry"),
|
||||
Values("Invocations 3", "InputPoints", "InputLines",
|
||||
"InputLinesAdjacency", "InputTrianglesAdjacency",
|
||||
"OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeGeometryOnlyBadSpv10, ValidateModeExecution,
|
||||
Combine(Values(SPV_ERROR_INVALID_DATA),
|
||||
Values("Execution mode can only be used with the Geometry "
|
||||
"execution model."),
|
||||
Values("Fragment", "TessellationEvaluation", "TessellationControl",
|
||||
"GLCompute", "Vertex", "Kernel"),
|
||||
Values("Invocations 3", "InputPoints", "InputLines",
|
||||
"InputLinesAdjacency", "InputTrianglesAdjacency",
|
||||
"OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeTessellationOnlyGoodSpv10, ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""),
|
||||
Values("TessellationControl", "TessellationEvaluation"),
|
||||
Values("SpacingEqual", "SpacingFractionalEven",
|
||||
"SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
|
||||
"PointMode", "Quads", "Isolines"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeTessellationOnlyBadSpv10, ValidateModeExecution,
|
||||
Combine(Values(SPV_ERROR_INVALID_DATA),
|
||||
Values("Execution mode can only be used with a tessellation "
|
||||
"execution model."),
|
||||
Values("Fragment", "Geometry", "GLCompute", "Vertex", "Kernel"),
|
||||
Values("SpacingEqual", "SpacingFractionalEven",
|
||||
"SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
|
||||
"PointMode", "Quads", "Isolines"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ValidateModeGeometryAndTessellationGoodSpv10,
|
||||
ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""),
|
||||
Values("TessellationControl",
|
||||
"TessellationEvaluation", "Geometry"),
|
||||
Values("Triangles", "OutputVertices 3"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeGeometryAndTessellationBadSpv10, ValidateModeExecution,
|
||||
Combine(Values(SPV_ERROR_INVALID_DATA),
|
||||
Values("Execution mode can only be used with a Geometry or "
|
||||
"tessellation execution model."),
|
||||
Values("Fragment", "GLCompute", "Vertex", "Kernel"),
|
||||
Values("Triangles", "OutputVertices 3"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeFragmentOnlyGoodSpv10, ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"),
|
||||
Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
|
||||
"EarlyFragmentTests", "DepthReplacing", "DepthLess",
|
||||
"DepthUnchanged"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeFragmentOnlyBadSpv10, ValidateModeExecution,
|
||||
Combine(Values(SPV_ERROR_INVALID_DATA),
|
||||
Values("Execution mode can only be used with the Fragment "
|
||||
"execution model."),
|
||||
Values("Geometry", "TessellationControl", "TessellationEvaluation",
|
||||
"GLCompute", "Vertex", "Kernel"),
|
||||
Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
|
||||
"EarlyFragmentTests", "DepthReplacing", "DepthLess",
|
||||
"DepthUnchanged"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""),
|
||||
Values("Kernel"),
|
||||
Values("LocalSizeHint 1 1 1", "VecTypeHint 4",
|
||||
"ContractionOff",
|
||||
"LocalSizeHintId %int1"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_3)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeKernelOnlyBadSpv13, ValidateModeExecution,
|
||||
Combine(
|
||||
Values(SPV_ERROR_INVALID_DATA),
|
||||
Values(
|
||||
"Execution mode can only be used with the Kernel execution model."),
|
||||
Values("Geometry", "TessellationControl", "TessellationEvaluation",
|
||||
"GLCompute", "Vertex", "Fragment"),
|
||||
Values("LocalSizeHint 1 1 1", "VecTypeHint 4", "ContractionOff",
|
||||
"LocalSizeHintId %int1"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_3)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeGLComputeAndKernelGoodSpv13, ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""), Values("Kernel", "GLCompute"),
|
||||
Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_3)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeGLComputeAndKernelBadSpv13, ValidateModeExecution,
|
||||
Combine(Values(SPV_ERROR_INVALID_DATA),
|
||||
Values("Execution mode can only be used with a Kernel or GLCompute "
|
||||
"execution model."),
|
||||
Values("Geometry", "TessellationControl", "TessellationEvaluation",
|
||||
"Fragment", "Vertex"),
|
||||
Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_3)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ValidateModeAllGoodSpv13, ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""),
|
||||
Values("Kernel", "GLCompute", "Geometry", "TessellationControl",
|
||||
"TessellationEvaluation", "Fragment", "Vertex"),
|
||||
Values("Xfb", "Initializer", "Finalizer", "SubgroupSize 1",
|
||||
"SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_3)));
|
||||
|
||||
TEST_F(ValidateModeExecution, MeshNVLocalSize) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability MeshShadingNV
|
||||
OpExtension "SPV_NV_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshNV %main "main"
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateModeExecution, MeshNVOutputPoints) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability MeshShadingNV
|
||||
OpExtension "SPV_NV_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshNV %main "main"
|
||||
OpExecutionMode %main OutputPoints
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateModeExecution, MeshNVOutputVertices) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability MeshShadingNV
|
||||
OpExtension "SPV_NV_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshNV %main "main"
|
||||
OpExecutionMode %main OutputVertices 42
|
||||
)" + kVoidFunction;
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateModeExecution, MeshNVLocalSizeId) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability MeshShadingNV
|
||||
OpExtension "SPV_NV_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshNV %main "main"
|
||||
OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
|
||||
%int = OpTypeInt 32 0
|
||||
%int_1 = OpConstant %int 1
|
||||
)" + kVoidFunction;
|
||||
|
||||
spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
|
||||
CompileSuccessfully(spirv, env);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
@ -49,6 +49,9 @@ OpCapability GroupNonUniformQuad
|
||||
ss << capabilities_and_extensions;
|
||||
ss << "OpMemoryModel Logical GLSL450\n";
|
||||
ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
|
||||
if (execution_model == "GLCompute") {
|
||||
ss << "OpExecutionMode %main LocalSize 1 1 1\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
|
@ -37,6 +37,10 @@ std::string GenerateShaderCode(
|
||||
ss << capabilities_and_extensions << "\n";
|
||||
ss << "OpMemoryModel Logical GLSL450\n";
|
||||
ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
|
||||
if (execution_model == "Geometry") {
|
||||
ss << "OpExecutionMode %main InputPoints\n";
|
||||
ss << "OpExecutionMode %main OutputPoints\n";
|
||||
}
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
|
@ -31,6 +31,7 @@ const std::string vulkan_spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%functy = OpTypeFunction %void
|
||||
%func = OpFunction %void None %functy
|
||||
|
Loading…
Reference in New Issue
Block a user