mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
Add EXT_mesh_shader validation support
1. Each OpEntryPoint with the MeshEXT Execution Model can have at most one global OpVariable of storage class TaskPayloadWorkgroupEXT. 2. PerPrimitiveEXT only be used on a memory object declaration or a member of a structure type 3. PerPrimitiveEXT only Input in Fragment and Output in MeshEXT 4. Added Mesh vulkan validation support for following rules: VUID-Layer-Layer-07039 VUID-PrimitiveId-PrimitiveId-07040,VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07042, VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07048, VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07054, VUID-ViewportIndex-ViewportIndex-07060 VUID-StandaloneSpirv-ExecutionModel-07330 VUID-StandaloneSpirv-ExecutionModel-07331
This commit is contained in:
parent
6761288d39
commit
7e583d0df3
@ -143,6 +143,11 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
|
||||
return fail(0) << "must be a variable";
|
||||
}
|
||||
break;
|
||||
case spv::Decoration::PerPrimitiveNV:
|
||||
if (target->opcode() != spv::Op::OpVariable) {
|
||||
return fail(0) << "must be a memory object declaration";
|
||||
}
|
||||
break;
|
||||
case spv::Decoration::NoPerspective:
|
||||
case spv::Decoration::Flat:
|
||||
case spv::Decoration::Patch:
|
||||
@ -361,6 +366,15 @@ spv_result_t ValidateMemberDecorate(ValidationState_t& _,
|
||||
<< _.SpvDecorationString(decoration)
|
||||
<< " cannot be applied to structure members";
|
||||
}
|
||||
|
||||
const auto target_id = inst->GetOperandAs<uint32_t>(0);
|
||||
const auto target = _.FindDef(target_id);
|
||||
if (decoration == spv::Decoration::PerPrimitiveNV &&
|
||||
target->opcode() != spv::Op::OpTypeStruct) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< _.SpvDecorationString(decoration)
|
||||
<< " must be a memory object declaration";
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
@ -667,6 +667,36 @@ class BuiltInsValidator {
|
||||
// instruction.
|
||||
void Update(const Instruction& inst);
|
||||
|
||||
uint32_t GetMeshEntryPoint() {
|
||||
if (mesh_entry_point_ == 0) {
|
||||
for (const uint32_t entry_point : _.entry_points()) {
|
||||
// Every entry point from which this function is called needs to have
|
||||
// Execution Mode DepthReplacing.
|
||||
const auto* models = _.GetExecutionModels(entry_point);
|
||||
if (models->find(spv::ExecutionModel::MeshEXT ) != models->end() ||
|
||||
models->find(spv::ExecutionModel::MeshNV ) != models->end()) {
|
||||
mesh_entry_point_ = entry_point;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mesh_entry_point_;
|
||||
}
|
||||
|
||||
bool isMeshInterfaceVar(const Instruction& inst) {
|
||||
uint32_t mesh_entry_point = GetMeshEntryPoint();
|
||||
if (!mesh_entry_point) return false;
|
||||
for (const auto& desc : _.entry_point_descriptions(mesh_entry_point)) {
|
||||
for (auto interface : desc.interfaces) {
|
||||
if (inst.id() == interface) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ValidationState_t& _;
|
||||
|
||||
// Mapping id -> list of rules which validate instruction referencing the
|
||||
@ -684,7 +714,7 @@ class BuiltInsValidator {
|
||||
// or to no_entry_points_. The pointer is guaranteed to never be null.
|
||||
const std::vector<uint32_t> no_entry_points;
|
||||
const std::vector<uint32_t>* entry_points_ = &no_entry_points;
|
||||
|
||||
uint32_t mesh_entry_point_ = 0;
|
||||
// Execution models with which the current function can be called.
|
||||
std::set<spv::ExecutionModel> execution_models_;
|
||||
};
|
||||
@ -2146,6 +2176,28 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveIdAtDefinition(
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMeshInterfaceVar(inst)) {
|
||||
if (_.HasCapability(spv::Capability::MeshShadingEXT) &&
|
||||
!_.HasDecoration(inst.id(), spv::Decoration::PerPrimitiveEXT)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< _.VkErrorID(7040)
|
||||
<< "According to the Vulkan spec the variable decorated with "
|
||||
"Builtin PrimitiveId within the MeshEXT Execution Model must "
|
||||
"also be decorated with the PerPrimitiveEXT decoration. ";
|
||||
}
|
||||
#if 0
|
||||
const spv::StorageClass storage_class =
|
||||
inst.GetOperandAs<spv::StorageClass>(2);
|
||||
if (storage_class != spv::StorageClass::Output) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< _.VkErrorID(4336)
|
||||
<< "According to the Vulkan spec the variable decorated with "
|
||||
"Builtin PrimitiveId within the MeshEXT Execution Model must "
|
||||
"must be declared using the Output Storage Class. ";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Seed at reference checks with this built-in.
|
||||
@ -2753,6 +2805,21 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtDefinition(
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMeshInterfaceVar(inst) &&
|
||||
_.HasCapability(spv::Capability::MeshShadingEXT) &&
|
||||
!_.HasDecoration(inst.id(), spv::Decoration::PerPrimitiveEXT)) {
|
||||
const spv::BuiltIn label = spv::BuiltIn(decoration.params()[0]);
|
||||
uint32_t vkerrid = (label == spv::BuiltIn::Layer) ? 7039 : 7060;
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< _.VkErrorID(vkerrid)
|
||||
<< "According to the Vulkan spec the variable decorated with "
|
||||
"Builtin "
|
||||
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
|
||||
decoration.params()[0])
|
||||
<< " within the MeshEXT Execution Model must also be decorated "
|
||||
"with the PerPrimitiveEXT decoration. ";
|
||||
}
|
||||
}
|
||||
|
||||
// Seed at reference checks with this built-in.
|
||||
@ -3458,6 +3525,7 @@ spv_result_t BuiltInsValidator::ValidateViewIndexAtReference(
|
||||
referenced_from_inst, execution_model);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (function_id_ == 0) {
|
||||
@ -4167,6 +4235,23 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
|
||||
spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
|
||||
const Decoration& decoration, const Instruction& inst) {
|
||||
if (spvIsVulkanEnv(_.context()->target_env)) {
|
||||
uint32_t mesh_entry_point = GetMeshEntryPoint();
|
||||
assert(mesh_entry_point);
|
||||
bool execution_mode_OuputPoints = false;
|
||||
bool execution_mode_OutputLinesEXT = false;
|
||||
bool execution_mode_OutputTrianglesEXT = false;
|
||||
|
||||
const auto* modes = _.GetExecutionModes(mesh_entry_point);
|
||||
if (modes->find(spv::ExecutionMode::OutputPoints) != modes->end()) {
|
||||
execution_mode_OuputPoints = true;
|
||||
}
|
||||
if (modes->find(spv::ExecutionMode::OutputLinesEXT) != modes->end()) {
|
||||
execution_mode_OutputLinesEXT = true;
|
||||
}
|
||||
if (modes->find(spv::ExecutionMode::OutputTrianglesEXT) !=
|
||||
modes->end()) {
|
||||
execution_mode_OutputTrianglesEXT = true;
|
||||
}
|
||||
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
|
||||
uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
|
||||
if (builtin == spv::BuiltIn::PrimitivePointIndicesEXT) {
|
||||
@ -4185,6 +4270,12 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
|
||||
})) {
|
||||
return error;
|
||||
}
|
||||
if (!execution_mode_OuputPoints) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< _.VkErrorID(7042)
|
||||
<< "The PrimitivePointIndicesEXT decoration must be used with "
|
||||
"the OutputPoints Execution Mode";
|
||||
}
|
||||
}
|
||||
if (builtin == spv::BuiltIn::PrimitiveLineIndicesEXT) {
|
||||
if (spv_result_t error = ValidateArrayedI32Vec(
|
||||
@ -4203,6 +4294,12 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
|
||||
})) {
|
||||
return error;
|
||||
}
|
||||
if (!execution_mode_OutputLinesEXT) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< _.VkErrorID(7048)
|
||||
<< "The PrimitiveLineIndicesEXT decoration must be used with "
|
||||
"the OutputLinesEXT Execution Mode";
|
||||
}
|
||||
}
|
||||
if (builtin == spv::BuiltIn::PrimitiveTriangleIndicesEXT) {
|
||||
if (spv_result_t error = ValidateArrayedI32Vec(
|
||||
@ -4221,6 +4318,12 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
|
||||
})) {
|
||||
return error;
|
||||
}
|
||||
if (!execution_mode_OutputTrianglesEXT) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
<< _.VkErrorID(7054)
|
||||
<< "The PrimitiveTriangleIndicesEXT decoration must be used with "
|
||||
"the OutputTrianglesEXT Execution Mode";
|
||||
}
|
||||
}
|
||||
}
|
||||
// Seed at reference checks with this built-in.
|
||||
@ -4249,7 +4352,6 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtReference(
|
||||
referenced_from_inst)
|
||||
<< " " << GetStorageClassDesc(referenced_from_inst);
|
||||
}
|
||||
|
||||
for (const spv::ExecutionModel execution_model : execution_models_) {
|
||||
if (execution_model != spv::ExecutionModel::MeshEXT) {
|
||||
uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
|
||||
|
@ -767,6 +767,7 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
|
||||
int num_workgroup_variables = 0;
|
||||
int num_workgroup_variables_with_block = 0;
|
||||
int num_workgroup_variables_with_aliased = 0;
|
||||
bool has_task_payload = false;
|
||||
for (const auto& desc : descs) {
|
||||
std::unordered_set<Instruction*> seen_vars;
|
||||
for (auto interface : desc.interfaces) {
|
||||
@ -779,6 +780,19 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
|
||||
}
|
||||
const spv::StorageClass storage_class =
|
||||
var_instr->GetOperandAs<spv::StorageClass>(2);
|
||||
if (vstate.version() >= SPV_SPIRV_VERSION_WORD(1, 5)) {
|
||||
// SPV_EXT_mesh_shader, at most one task payload is permitted
|
||||
// per entry point
|
||||
if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
|
||||
if (has_task_payload) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
|
||||
<< "There can be at most one OpVariable with storage "
|
||||
"class TaskPayloadWorkgroupEXT associated with "
|
||||
"an OpEntryPoint";
|
||||
}
|
||||
has_task_payload = true;
|
||||
}
|
||||
}
|
||||
if (vstate.version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
|
||||
// Starting in 1.4, OpEntryPoint must list all global variables
|
||||
// it statically uses and those interfaces must be unique.
|
||||
|
@ -15,6 +15,7 @@
|
||||
// Validates ray query instructions from SPV_KHR_ray_query
|
||||
|
||||
#include "source/opcode.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/val/instruction.h"
|
||||
#include "source/val/validate.h"
|
||||
#include "source/val/validation_state.h"
|
||||
@ -22,6 +23,24 @@
|
||||
namespace spvtools {
|
||||
namespace val {
|
||||
|
||||
bool IsInterfaceVariable(ValidationState_t& _, const Instruction* inst,
|
||||
spv::ExecutionModel model) {
|
||||
bool foundInterface = false;
|
||||
for (auto entry_point : _.entry_points()) {
|
||||
const auto* models = _.GetExecutionModels(entry_point);
|
||||
if (models->find(model) == models->end()) return false;
|
||||
for (const auto& desc : _.entry_point_descriptions(entry_point)) {
|
||||
for (auto interface : desc.interfaces) {
|
||||
if (inst->id() == interface) {
|
||||
foundInterface = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return foundInterface;
|
||||
}
|
||||
|
||||
spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst) {
|
||||
const spv::Op opcode = inst->opcode();
|
||||
switch (opcode) {
|
||||
@ -103,7 +122,7 @@ spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Primitive Count must be a 32-bit unsigned int scalar";
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -111,7 +130,40 @@ spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst) {
|
||||
// No validation rules (for the moment).
|
||||
break;
|
||||
}
|
||||
case spv::Op::OpVariable: {
|
||||
if (_.HasCapability(spv::Capability::MeshShadingEXT)) {
|
||||
bool meshInterfaceVar = IsInterfaceVariable(
|
||||
_, inst, spv::ExecutionModel::MeshEXT);
|
||||
bool fragInterfaceVar = IsInterfaceVariable(
|
||||
_, inst, spv::ExecutionModel::Fragment);
|
||||
|
||||
const spv::StorageClass storage_class =
|
||||
inst->GetOperandAs<spv::StorageClass>(2);
|
||||
bool storage_output = (storage_class == spv::StorageClass::Output);
|
||||
bool storage_input = (storage_class == spv::StorageClass::Input);
|
||||
|
||||
if (_.HasDecoration(inst->id(), spv::Decoration::PerPrimitiveEXT)) {
|
||||
if (fragInterfaceVar && !storage_input) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "PerPrimitiveEXT decoration must be applied only to "
|
||||
"variables in the Input Storage Class in the Fragment "
|
||||
"Execution Model.";
|
||||
}
|
||||
|
||||
if (meshInterfaceVar && !storage_output) {
|
||||
std::string vkerror = (spvIsVulkanEnv(_.context()->target_env))
|
||||
? _.VkErrorID(4336)
|
||||
: "";
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< vkerror
|
||||
<< "PerPrimitiveEXT decoration must be applied only to "
|
||||
"variables in the Output Storage Class in the "
|
||||
"Storage Class in the MeshEXT Execution Model.";
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -543,6 +543,15 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
|
||||
"tessellation execution model.";
|
||||
}
|
||||
}
|
||||
if (spvIsVulkanEnv(_.context()->target_env)) {
|
||||
if (_.HasCapability(spv::Capability::MeshShadingEXT) &&
|
||||
inst->GetOperandAs<uint32_t>(2) == 0) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< _.VkErrorID(7330)
|
||||
<< "In mesh shaders using the MeshEXT Execution Model the "
|
||||
"OutputVertices Execution Mode must be greater than 0";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case spv::ExecutionMode::OutputLinesEXT:
|
||||
case spv::ExecutionMode::OutputTrianglesEXT:
|
||||
@ -557,6 +566,16 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
|
||||
"execution "
|
||||
"model.";
|
||||
}
|
||||
if (mode == spv::ExecutionMode::OutputPrimitivesEXT &&
|
||||
spvIsVulkanEnv(_.context()->target_env)) {
|
||||
if (_.HasCapability(spv::Capability::MeshShadingEXT) &&
|
||||
inst->GetOperandAs<uint32_t>(2) == 0) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< _.VkErrorID(7331)
|
||||
<< "In mesh shaders using the MeshEXT Execution Model the "
|
||||
"OutputPrimitivesEXT Execution Mode must be greater than 0";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case spv::ExecutionMode::QuadDerivativesKHR:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
|
@ -1985,6 +1985,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
|
||||
return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04330);
|
||||
case 4334:
|
||||
return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
|
||||
case 4336:
|
||||
return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04336);
|
||||
case 4337:
|
||||
return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
|
||||
case 4345:
|
||||
@ -2311,30 +2313,46 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06808);
|
||||
case 6925:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925);
|
||||
case 7039:
|
||||
return VUID_WRAP(VUID-Layer-Layer-07039);
|
||||
case 7040:
|
||||
return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-07040);
|
||||
case 7041:
|
||||
return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07041);
|
||||
case 7042:
|
||||
return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07042);
|
||||
case 7043:
|
||||
return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07043);
|
||||
case 7044:
|
||||
return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07044);
|
||||
case 7047:
|
||||
return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07047);
|
||||
case 7048:
|
||||
return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07048);
|
||||
case 7049:
|
||||
return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07049);
|
||||
case 7050:
|
||||
return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07050);
|
||||
case 7053:
|
||||
return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07053);
|
||||
case 7054:
|
||||
return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07054);
|
||||
case 7055:
|
||||
return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07055);
|
||||
case 7056:
|
||||
return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07056);
|
||||
case 7060:
|
||||
return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-07060);
|
||||
case 7102:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102);
|
||||
case 7320:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320);
|
||||
case 7290:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Input-07290);
|
||||
case 7320:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320);
|
||||
case 7330:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07330);
|
||||
case 7331:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07331);
|
||||
case 7650:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Base-07650);
|
||||
case 7651:
|
||||
|
@ -4325,6 +4325,29 @@ TEST_F(ValidateBuiltIns, VulkanPrimitiveTriangleIndicesEXTSuccess) {
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, VulkanPrimitiveTriangleIndicesEXTInvalidExecutionMode) {
|
||||
const std::string declarations = R"(
|
||||
%array = OpTypeArray %v3uint %uint_16
|
||||
%array_ptr = OpTypePointer Output %array
|
||||
%var = OpVariable %array_ptr Output
|
||||
%ptr = OpTypePointer Output %v3uint
|
||||
)";
|
||||
const std::string body = R"(
|
||||
%access = OpAccessChain %ptr %var %int_0
|
||||
)";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateMeshShadingCode("PrimitiveTriangleIndicesEXT",
|
||||
"OutputPoints", body, declarations)
|
||||
.c_str(),
|
||||
SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-PrimitiveTriangleIndicesEXT-"
|
||||
"PrimitiveTriangleIndicesEXT-07054"));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, VulkanPrimitiveTriangleIndicesEXTStorageClass) {
|
||||
const std::string declarations = R"(
|
||||
%array = OpTypeArray %v3uint %uint_16
|
||||
@ -4408,6 +4431,29 @@ TEST_F(ValidateBuiltIns, VulkanPrimitiveLineIndicesEXTSuccess) {
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, VulkanPrimitiveLineIndicesEXTInvalidExecutionMode) {
|
||||
const std::string declarations = R"(
|
||||
%array = OpTypeArray %v2uint %uint_16
|
||||
%array_ptr = OpTypePointer Output %array
|
||||
%var = OpVariable %array_ptr Output
|
||||
%ptr = OpTypePointer Output %v2uint
|
||||
)";
|
||||
const std::string body = R"(
|
||||
%access = OpAccessChain %ptr %var %int_0
|
||||
)";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateMeshShadingCode("PrimitiveLineIndicesEXT", "OutputPoints", body,
|
||||
declarations)
|
||||
.c_str(),
|
||||
SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
AnyVUID("VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07048"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ValidateBuiltIns, VulkanPrimitiveLineIndicesEXTStorageClass) {
|
||||
const std::string declarations = R"(
|
||||
%array = OpTypeArray %v2uint %uint_16
|
||||
@ -4471,6 +4517,28 @@ TEST_F(ValidateBuiltIns, VulkanPrimitivePointIndicesEXTSuccess) {
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, VulkanPrimitivePointIndicesEXTInvalidExecutionMode) {
|
||||
const std::string declarations = R"(
|
||||
%array = OpTypeArray %uint %uint_16
|
||||
%array_ptr = OpTypePointer Output %array
|
||||
%var = OpVariable %array_ptr Output
|
||||
%ptr = OpTypePointer Output %uint
|
||||
)";
|
||||
const std::string body = R"(
|
||||
%access = OpAccessChain %ptr %var %int_0
|
||||
)";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateMeshShadingCode("PrimitivePointIndicesEXT", "OutputTrianglesNV",
|
||||
body, declarations)
|
||||
.c_str(),
|
||||
SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
AnyVUID("VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07042"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, VulkanPrimitivePointIndicesEXTStorageClass) {
|
||||
const std::string declarations = R"(
|
||||
%array = OpTypeArray %uint %uint_16
|
||||
@ -4515,6 +4583,192 @@ TEST_F(ValidateBuiltIns, VulkanPrimitivePointIndicesEXTType) {
|
||||
AnyVUID("VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07044"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, VulkanBuiltinPrimtiveIDWithPerPrimitiveEXT) {
|
||||
const std::string text = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %MainMesh "MainMesh" %gl_PrimitiveID
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputVertices 3
|
||||
OpExecutionMode %MainMesh OutputTrianglesNV
|
||||
OpExecutionMode %MainMesh LocalSize 1 1 1
|
||||
OpSource Slang 1
|
||||
OpName %MainMesh "MainMesh"
|
||||
OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
|
||||
OpDecorate %gl_PrimitiveID PerPrimitiveNV
|
||||
%void = OpTypeVoid
|
||||
%9 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%int = OpTypeInt 32 1
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_3 = OpConstant %int 3
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Output_v3uint = OpTypePointer Output %v3uint
|
||||
%_ptr_Output_int = OpTypePointer Output %int
|
||||
%_arr_int_int_1 = OpTypeArray %int %int_1
|
||||
%_ptr_Output__arr_int_int_1 = OpTypePointer Output %_arr_int_int_1
|
||||
%gl_PrimitiveID = OpVariable %_ptr_Output__arr_int_int_1 Output
|
||||
%MainMesh = OpFunction %void None %9
|
||||
%25 = OpLabel
|
||||
OpSetMeshOutputsEXT %uint_3 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, BadVulkanBuiltinPrimtiveIDWithPerPrimitiveEXT) {
|
||||
const std::string text = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %MainMesh "MainMesh" %gl_PrimitiveID
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputVertices 3
|
||||
OpExecutionMode %MainMesh OutputTrianglesNV
|
||||
OpExecutionMode %MainMesh LocalSize 1 1 1
|
||||
OpSource Slang 1
|
||||
OpName %MainMesh "MainMesh"
|
||||
OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
|
||||
%void = OpTypeVoid
|
||||
%9 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%int = OpTypeInt 32 1
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_3 = OpConstant %int 3
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Output_v3uint = OpTypePointer Output %v3uint
|
||||
%_ptr_Output_int = OpTypePointer Output %int
|
||||
%_arr_int_int_1 = OpTypeArray %int %int_1
|
||||
%_ptr_Output__arr_int_int_1 = OpTypePointer Output %_arr_int_int_1
|
||||
%gl_PrimitiveID = OpVariable %_ptr_Output__arr_int_int_1 Output
|
||||
%MainMesh = OpFunction %void None %9
|
||||
%25 = OpLabel
|
||||
OpSetMeshOutputsEXT %uint_3 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-PrimitiveId-PrimitiveId-07040"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, BadVulkanBuiltinLayerWithPerPrimitiveEXT) {
|
||||
const std::string text = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %MainMesh "MainMesh" %gl_Layer
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputVertices 3
|
||||
OpExecutionMode %MainMesh OutputTrianglesNV
|
||||
OpExecutionMode %MainMesh LocalSize 1 1 1
|
||||
OpSource Slang 1
|
||||
OpName %MainMesh "MainMesh"
|
||||
OpDecorate %gl_Layer BuiltIn Layer
|
||||
%void = OpTypeVoid
|
||||
%9 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%float = OpTypeFloat 32
|
||||
%int = OpTypeInt 32 1
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_3 = OpConstant %int 3
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Output_v3uint = OpTypePointer Output %v3uint
|
||||
%_ptr_Output_int = OpTypePointer Output %int
|
||||
%_arr_int_int_1 = OpTypeArray %int %int_1
|
||||
%_ptr_Output__arr_int_int_1 = OpTypePointer Output %_arr_int_int_1
|
||||
%gl_Layer = OpVariable %_ptr_Output__arr_int_int_1 Output
|
||||
%MainMesh = OpFunction %void None %9
|
||||
%25 = OpLabel
|
||||
OpSetMeshOutputsEXT %uint_3 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-Layer-Layer-07039"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBuiltIns, BadVulkanBuiltinViewportIndexWithPerPrimitiveEXT) {
|
||||
const std::string text = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %MainMesh "MainMesh" %gl_ViewportIndex
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputPrimitivesNV 1
|
||||
OpExecutionMode %MainMesh OutputVertices 3
|
||||
OpExecutionMode %MainMesh OutputTrianglesNV
|
||||
OpExecutionMode %MainMesh LocalSize 1 1 1
|
||||
OpSource Slang 1
|
||||
OpName %MainMesh "MainMesh"
|
||||
OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex
|
||||
%void = OpTypeVoid
|
||||
%9 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%float = OpTypeFloat 32
|
||||
%int = OpTypeInt 32 1
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_3 = OpConstant %int 3
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Output_v3uint = OpTypePointer Output %v3uint
|
||||
%_ptr_Output_int = OpTypePointer Output %int
|
||||
%_arr_int_int_1 = OpTypeArray %int %int_1
|
||||
%_ptr_Output__arr_int_int_1 = OpTypePointer Output %_arr_int_int_1
|
||||
%gl_ViewportIndex = OpVariable %_ptr_Output__arr_int_int_1 Output
|
||||
%MainMesh = OpFunction %void None %9
|
||||
%25 = OpLabel
|
||||
OpSetMeshOutputsEXT %uint_3 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-ViewportIndex-ViewportIndex-07060"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
@ -467,6 +467,82 @@ TEST_F(ValidateMeshShading, TaskPayloadWorkgroupBadExecutionModel) {
|
||||
"TaskEXT and MeshKHR execution model"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMeshShading, BadMultipleTaskPayloadWorkgroupEXT) {
|
||||
const std::string body = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TaskEXT %main "main" %payload %payload1
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
|
||||
%payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT
|
||||
%payload1 = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT
|
||||
%main = OpFunction %void None %func
|
||||
%label = OpLabel
|
||||
%load = OpLoad %uint %payload
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("There can be at most one OpVariable with storage "
|
||||
"class TaskPayloadWorkgroupEXT associated with "
|
||||
"an OpEntryPoint"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ValidateMeshShading, TaskPayloadWorkgroupTaskExtExecutionModel) {
|
||||
const std::string body = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint TaskEXT %main "main" %payload
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
|
||||
%payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT
|
||||
%main = OpFunction %void None %func
|
||||
%label = OpLabel
|
||||
%load = OpLoad %uint %payload
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ValidateMeshShading, TaskPayloadWorkgroupMeshExtExecutionModel) {
|
||||
const std::string body = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %main "main" %payload
|
||||
OpExecutionMode %main OutputVertices 1
|
||||
OpExecutionMode %main OutputPrimitivesEXT 1
|
||||
OpExecutionMode %main OutputTrianglesEXT
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
|
||||
%payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT
|
||||
%main = OpFunction %void None %func
|
||||
%label = OpLabel
|
||||
%load = OpLoad %uint %payload
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ValidateMeshShading, OpSetMeshOutputsBadVertexCount) {
|
||||
const std::string body = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
@ -598,6 +674,320 @@ TEST_F(ValidateMeshShading, OpEmitMeshTasksZeroSuccess) {
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMeshShading, BadPerPrimitiveEXTStorageClassInMeshEXT) {
|
||||
const std::string body = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %main "main" %gl_LocalInvocationID %blk %triangleNormal
|
||||
OpExecutionMode %main LocalSize 32 1 1
|
||||
OpExecutionMode %main OutputVertices 81
|
||||
OpExecutionMode %main OutputPrimitivesNV 32
|
||||
OpExecutionMode %main OutputTrianglesNV
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpName %iid "iid"
|
||||
OpName %gl_LocalInvocationID "gl_LocalInvocationID"
|
||||
OpName %myblock "myblock"
|
||||
OpMemberName %myblock 0 "f"
|
||||
OpName %blk "blk"
|
||||
OpName %triangleNormal "triangleNormal"
|
||||
OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
|
||||
OpMemberDecorate %myblock 0 PerPrimitiveEXT
|
||||
OpDecorate %myblock Block
|
||||
OpDecorate %blk Location 0
|
||||
OpDecorate %triangleNormal PerPrimitiveEXT
|
||||
OpDecorate %triangleNormal Location 0
|
||||
OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%_ptr_Function_uint = OpTypePointer Function %uint
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
|
||||
%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Input_uint = OpTypePointer Input %uint
|
||||
%float = OpTypeFloat 32
|
||||
%myblock = OpTypeStruct %float
|
||||
%uint_32 = OpConstant %uint 32
|
||||
%_arr_myblock_uint_32 = OpTypeArray %myblock %uint_32
|
||||
%_ptr_Output__arr_myblock_uint_32 = OpTypePointer Output %_arr_myblock_uint_32
|
||||
%blk = OpVariable %_ptr_Output__arr_myblock_uint_32 Output
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%float_11 = OpConstant %float 11
|
||||
%_ptr_Output_float = OpTypePointer Output %float
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_arr_v3float_uint_32 = OpTypeArray %v3float %uint_32
|
||||
%_ptr_Output__arr_v3float_uint_32 = OpTypePointer Input %_arr_v3float_uint_32
|
||||
%triangleNormal = OpVariable %_ptr_Output__arr_v3float_uint_32 Input
|
||||
%33 = OpConstantComposite %v3float %float_11 %float_11 %float_11
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_32 %uint_1 %uint_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%iid = OpVariable %_ptr_Function_uint Function
|
||||
%14 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0
|
||||
%15 = OpLoad %uint %14
|
||||
OpStore %iid %15
|
||||
%22 = OpLoad %uint %iid
|
||||
%27 = OpAccessChain %_ptr_Output_float %blk %22 %int_0
|
||||
OpStore %27 %float_11
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("PerPrimitiveEXT decoration must be applied only to "
|
||||
"variables in the Output Storage Class in the Storage "
|
||||
"Class in the MeshEXT Execution Model."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMeshShading, VulkanPerPrimitiveEXTStorageClassInMeshEXT) {
|
||||
const std::string body = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %main "main" %gl_LocalInvocationID %blk %triangleNormal
|
||||
OpExecutionMode %main LocalSize 32 1 1
|
||||
OpExecutionMode %main OutputVertices 81
|
||||
OpExecutionMode %main OutputPrimitivesNV 32
|
||||
OpExecutionMode %main OutputTrianglesNV
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpName %iid "iid"
|
||||
OpName %gl_LocalInvocationID "gl_LocalInvocationID"
|
||||
OpName %myblock "myblock"
|
||||
OpMemberName %myblock 0 "f"
|
||||
OpName %blk "blk"
|
||||
OpName %triangleNormal "triangleNormal"
|
||||
OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
|
||||
OpMemberDecorate %myblock 0 PerPrimitiveEXT
|
||||
OpDecorate %myblock Block
|
||||
OpDecorate %blk Location 0
|
||||
OpDecorate %triangleNormal PerPrimitiveEXT
|
||||
OpDecorate %triangleNormal Location 0
|
||||
OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%_ptr_Function_uint = OpTypePointer Function %uint
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
|
||||
%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Input_uint = OpTypePointer Input %uint
|
||||
%float = OpTypeFloat 32
|
||||
%myblock = OpTypeStruct %float
|
||||
%uint_32 = OpConstant %uint 32
|
||||
%_arr_myblock_uint_32 = OpTypeArray %myblock %uint_32
|
||||
%_ptr_Output__arr_myblock_uint_32 = OpTypePointer Output %_arr_myblock_uint_32
|
||||
%blk = OpVariable %_ptr_Output__arr_myblock_uint_32 Output
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%float_11 = OpConstant %float 11
|
||||
%_ptr_Output_float = OpTypePointer Output %float
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_arr_v3float_uint_32 = OpTypeArray %v3float %uint_32
|
||||
%_ptr_Output__arr_v3float_uint_32 = OpTypePointer Input %_arr_v3float_uint_32
|
||||
%triangleNormal = OpVariable %_ptr_Output__arr_v3float_uint_32 Input
|
||||
%33 = OpConstantComposite %v3float %float_11 %float_11 %float_11
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_32 %uint_1 %uint_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%iid = OpVariable %_ptr_Function_uint Function
|
||||
%14 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0
|
||||
%15 = OpLoad %uint %14
|
||||
OpStore %iid %15
|
||||
%22 = OpLoad %uint %iid
|
||||
%27 = OpAccessChain %_ptr_Output_float %blk %22 %int_0
|
||||
OpStore %27 %float_11
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
AnyVUID("VUID-PrimitiveId-PrimitiveId-04336"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMeshShading, BadPerPrimitiveEXTStorageClassInFrag) {
|
||||
const std::string body = R"(
|
||||
OpCapability Shader
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %triangleNormal
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpName %triangleNormal "triangleNormal"
|
||||
OpDecorate %triangleNormal PerPrimitiveNV
|
||||
OpDecorate %triangleNormal Location 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v3float = OpTypeVector %float 3
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%_arr_v3float_uint_3 = OpTypeArray %v3float %uint_3
|
||||
%_ptr_Input__arr_v3float_uint_3 = OpTypePointer Output %_arr_v3float_uint_3
|
||||
%triangleNormal = OpVariable %_ptr_Input__arr_v3float_uint_3 Output
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_v3float = OpTypePointer Input %v3float
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%18 = OpAccessChain %_ptr_Input_v3float %triangleNormal %int_0
|
||||
%19 = OpLoad %v3float %18
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("PerPrimitiveEXT decoration must be applied only to "
|
||||
"variables in the Input Storage Class in the Fragment "
|
||||
"Execution Model."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMeshShading, PerPrimitiveEXTStorageClassInFrag) {
|
||||
const std::string body = R"(
|
||||
OpCapability Shader
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %res3 %triangleNormal
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpName %res3 "res3"
|
||||
OpName %triangleNormal "triangleNormal"
|
||||
OpDecorate %res3 Location 0
|
||||
OpDecorate %triangleNormal PerPrimitiveNV
|
||||
OpDecorate %triangleNormal Location 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%res3 = OpVariable %_ptr_Output_v3float Output
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%_arr_v3float_uint_3 = OpTypeArray %v3float %uint_3
|
||||
%_ptr_Input__arr_v3float_uint_3 = OpTypePointer Input %_arr_v3float_uint_3
|
||||
%triangleNormal = OpVariable %_ptr_Input__arr_v3float_uint_3 Input
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_v3float = OpTypePointer Input %v3float
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%18 = OpAccessChain %_ptr_Input_v3float %triangleNormal %int_0
|
||||
%19 = OpLoad %v3float %18
|
||||
OpStore %res3 %19
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMeshShading, PerPrimitiveEXTStorageClassInMeshEXT) {
|
||||
const std::string body = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %main "main" %gl_LocalInvocationID %blk %triangleNormal
|
||||
OpExecutionMode %main LocalSize 32 1 1
|
||||
OpExecutionMode %main OutputVertices 81
|
||||
OpExecutionMode %main OutputPrimitivesNV 32
|
||||
OpExecutionMode %main OutputTrianglesNV
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpName %iid "iid"
|
||||
OpName %gl_LocalInvocationID "gl_LocalInvocationID"
|
||||
OpName %myblock "myblock"
|
||||
OpMemberName %myblock 0 "f"
|
||||
OpName %blk "blk"
|
||||
OpName %triangleNormal "triangleNormal"
|
||||
OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
|
||||
OpMemberDecorate %myblock 0 PerPrimitiveNV
|
||||
OpDecorate %myblock Block
|
||||
OpDecorate %blk Location 0
|
||||
OpDecorate %triangleNormal PerPrimitiveNV
|
||||
OpDecorate %triangleNormal Location 0
|
||||
OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%_ptr_Function_uint = OpTypePointer Function %uint
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
|
||||
%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Input_uint = OpTypePointer Input %uint
|
||||
%float = OpTypeFloat 32
|
||||
%myblock = OpTypeStruct %float
|
||||
%uint_32 = OpConstant %uint 32
|
||||
%_arr_myblock_uint_32 = OpTypeArray %myblock %uint_32
|
||||
%_ptr_Output__arr_myblock_uint_32 = OpTypePointer Output %_arr_myblock_uint_32
|
||||
%blk = OpVariable %_ptr_Output__arr_myblock_uint_32 Output
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%float_11 = OpConstant %float 11
|
||||
%_ptr_Output_float = OpTypePointer Output %float
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_arr_v3float_uint_32 = OpTypeArray %v3float %uint_32
|
||||
%_ptr_Output__arr_v3float_uint_32 = OpTypePointer Output %_arr_v3float_uint_32
|
||||
%triangleNormal = OpVariable %_ptr_Output__arr_v3float_uint_32 Output
|
||||
%33 = OpConstantComposite %v3float %float_11 %float_11 %float_11
|
||||
%_ptr_Output_v3float = OpTypePointer Output %v3float
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_32 %uint_1 %uint_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%iid = OpVariable %_ptr_Function_uint Function
|
||||
%14 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0
|
||||
%15 = OpLoad %uint %14
|
||||
OpStore %iid %15
|
||||
%22 = OpLoad %uint %iid
|
||||
%27 = OpAccessChain %_ptr_Output_float %blk %22 %int_0
|
||||
OpStore %27 %float_11
|
||||
%32 = OpLoad %uint %iid
|
||||
%35 = OpAccessChain %_ptr_Output_v3float %triangleNormal %32
|
||||
OpStore %35 %33
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
@ -814,6 +814,110 @@ OpExecutionMode %main OutputPoints
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateModeExecution, MeshEXTOutputVertices) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %main "main"
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
OpExecutionMode %main OutputVertices 3
|
||||
OpExecutionMode %main OutputPrimitivesNV 1
|
||||
OpExecutionMode %main OutputTrianglesNV
|
||||
OpSource GLSL 460
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpSetMeshOutputsEXT %uint_3 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ValidateModeExecution, VulkanBadMeshEXTOutputVertices) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %main "main"
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
OpExecutionMode %main OutputVertices 0
|
||||
OpExecutionMode %main OutputPrimitivesNV 1
|
||||
OpExecutionMode %main OutputTrianglesNV
|
||||
OpSource GLSL 460
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpSetMeshOutputsEXT %uint_3 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-StandaloneSpirv-ExecutionModel-07330"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateModeExecution, VulkanBadMeshEXTOutputOutputPrimitivesEXT) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability MeshShadingEXT
|
||||
OpExtension "SPV_EXT_mesh_shader"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint MeshEXT %main "main"
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
OpExecutionMode %main OutputVertices 1
|
||||
OpExecutionMode %main OutputPrimitivesNV 0
|
||||
OpExecutionMode %main OutputTrianglesNV
|
||||
OpSource GLSL 460
|
||||
OpSourceExtension "GL_EXT_mesh_shader"
|
||||
OpName %main "main"
|
||||
OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpSetMeshOutputsEXT %uint_3 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-StandaloneSpirv-ExecutionModel-07331"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateModeExecution, MeshNVOutputVertices) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
|
Loading…
Reference in New Issue
Block a user