external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp \
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.cpp \
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp \
+ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmLoopDepInfTests.cpp \
+ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmLoopDepLenTests.cpp \
+ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmSpirvVersionTests.cpp \
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmTests.cpp \
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUboMatrixPaddingTests.cpp \
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp \
dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.multiple_arbitrary_descriptors.offset_view_nonzero
dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_zero
dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_nonzero
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_0_compute
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_1_compute
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_2_compute
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_3_compute
dEQP-VK.spirv_assembly.instruction.compute.opnop.literal_localsize
dEQP-VK.spirv_assembly.instruction.compute.opnop.literal_and_specid_localsize
dEQP-VK.spirv_assembly.instruction.compute.opnop.specid_localsize
dEQP-VK.spirv_assembly.instruction.compute.opatomic_storage_buffer.store
dEQP-VK.spirv_assembly.instruction.compute.opatomic_storage_buffer.compex
dEQP-VK.spirv_assembly.instruction.compute.opline.all
+dEQP-VK.spirv_assembly.instruction.compute.opmoduleprocessed.all
dEQP-VK.spirv_assembly.instruction.compute.opnoline.all
dEQP-VK.spirv_assembly.instruction.compute.opconstantnull.bool
dEQP-VK.spirv_assembly.instruction.compute.opconstantnull.sint32
dEQP-VK.spirv_assembly.instruction.compute.loop_control.unroll
dEQP-VK.spirv_assembly.instruction.compute.loop_control.dont_unroll
dEQP-VK.spirv_assembly.instruction.compute.loop_control.unroll_dont_unroll
+dEQP-VK.spirv_assembly.instruction.compute.loop_control.dependency_length
+dEQP-VK.spirv_assembly.instruction.compute.loop_control.dependency_infinite
dEQP-VK.spirv_assembly.instruction.compute.function_control.none
dEQP-VK.spirv_assembly.instruction.compute.function_control.inline
dEQP-VK.spirv_assembly.instruction.compute.function_control.dont_inline
dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compute.opptraccesschain_float_single_buffer_first_input
dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opvariable_initialized_null
dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opselect_null_or_valid_ptr
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_fragment
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_fragment
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_fragment
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_fragment
dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_vert
dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_tessc
dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_tesse
dEQP-VK.spirv_assembly.instruction.graphics.opsourcecontinued.long_tesse
dEQP-VK.spirv_assembly.instruction.graphics.opsourcecontinued.long_geom
dEQP-VK.spirv_assembly.instruction.graphics.opsourcecontinued.long_frag
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_vert
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_geom
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_frag
dEQP-VK.spirv_assembly.instruction.graphics.opline.opline_empty_name_vert
dEQP-VK.spirv_assembly.instruction.graphics.opline.opline_empty_name_tessc
dEQP-VK.spirv_assembly.instruction.graphics.opline.opline_empty_name_tesse
enum SpirvVersion
{
SPIRV_VERSION_1_0 = 0, //!< SPIR-V 1.0
+ SPIRV_VERSION_1_1 = 1, //!< SPIR-V 1.1
+ SPIRV_VERSION_1_2 = 2, //!< SPIR-V 1.2
+ SPIRV_VERSION_1_3 = 3, //!< SPIR-V 1.3
SPIRV_VERSION_LAST
};
+typedef struct
+{
+ deUint32 magic;
+ deUint32 version;
+ deUint32 generator;
+ deUint32 bound;
+} SpirvBinaryHeader;
+
namespace wsi
{
} // anonymous
-void validateCompiledBinary(const vector<deUint32>& binary, glu::ShaderProgramInfo* buildInfo)
+void validateCompiledBinary(const vector<deUint32>& binary, glu::ShaderProgramInfo* buildInfo, const SpirvVersion spirvVersion)
{
std::ostringstream validationLog;
- if (!validateSpirV(binary.size(), &binary[0], &validationLog))
+ if (!validateSpirV(binary.size(), &binary[0], &validationLog, spirvVersion))
{
buildInfo->program.linkOk = false;
buildInfo->program.infoLog += "\n" + validationLog.str();
ProgramBinary* buildProgram (const GlslSource& program, glu::ShaderProgramInfo* buildInfo)
{
+ const SpirvVersion spirvVersion = program.buildOptions.targetVersion;
const bool validateBinary = VALIDATE_BINARIES;
vector<deUint32> binary;
}
if (validateBinary)
- validateCompiledBinary(binary, buildInfo);
+ validateCompiledBinary(binary, buildInfo, spirvVersion);
return createProgramBinaryFromSpirV(binary);
}
ProgramBinary* buildProgram (const HlslSource& program, glu::ShaderProgramInfo* buildInfo)
{
+ const SpirvVersion spirvVersion = program.buildOptions.targetVersion;
const bool validateBinary = VALIDATE_BINARIES;
vector<deUint32> binary;
}
if (validateBinary)
- validateCompiledBinary(binary, buildInfo);
+ validateCompiledBinary(binary, buildInfo, spirvVersion);
return createProgramBinaryFromSpirV(binary);
}
ProgramBinary* assembleProgram (const SpirVAsmSource& program, SpirVProgramInfo* buildInfo)
{
+ const SpirvVersion spirvVersion = program.buildOptions.targetVersion;
const bool validateBinary = VALIDATE_BINARIES;
vector<deUint32> binary;
- if (!assembleSpirV(&program, &binary, buildInfo))
+ if (!assembleSpirV(&program, &binary, buildInfo, spirvVersion))
TCU_THROW(InternalError, "Failed to assemble SPIR-V");
if (validateBinary)
{
std::ostringstream validationLog;
- if (!validateSpirV(binary.size(), &binary[0], &validationLog))
+ if (!validateSpirV(binary.size(), &binary[0], &validationLog, spirvVersion))
{
buildInfo->compileOk = false;
buildInfo->infoLog += "\n" + validationLog.str();
return createProgramBinaryFromSpirV(binary);
}
-void disassembleProgram (const ProgramBinary& program, std::ostream* dst)
+void disassembleProgram (const ProgramBinary& program, std::ostream* dst, SpirvVersion spirvVersion)
{
if (program.getFormat() == PROGRAM_FORMAT_SPIRV)
{
TCU_CHECK_INTERNAL(isSaneSpirVBinary(program));
if (isNativeSpirVBinaryEndianness())
- disassembleSpirV(program.getSize()/sizeof(deUint32), (const deUint32*)program.getBinary(), dst);
+ disassembleSpirV(program.getSize()/sizeof(deUint32), (const deUint32*)program.getBinary(), dst, spirvVersion);
else
TCU_THROW(InternalError, "SPIR-V endianness translation not supported");
}
TCU_THROW(NotSupportedError, "Unsupported program format");
}
-bool validateProgram (const ProgramBinary& program, std::ostream* dst)
+bool validateProgram (const ProgramBinary& program, std::ostream* dst, SpirvVersion spirvVersion)
{
if (program.getFormat() == PROGRAM_FORMAT_SPIRV)
{
}
if (isNativeSpirVBinaryEndianness())
- return validateSpirV(program.getSize()/sizeof(deUint32), (const deUint32*)program.getBinary(), dst);
+ return validateSpirV(program.getSize()/sizeof(deUint32), (const deUint32*)program.getBinary(), dst, spirvVersion);
else
TCU_THROW(InternalError, "SPIR-V endianness translation not supported");
}
return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(s_shaderStages, shaderType);
}
+vk::SpirvVersion getSpirvVersionForAsm (const deUint32 vulkanVersion)
+{
+ vk::SpirvVersion result = vk::SPIRV_VERSION_LAST;
+
+ if (vulkanVersion == VK_API_VERSION_1_0)
+ result = vk::SPIRV_VERSION_1_0;
+ else if (vulkanVersion >= VK_API_VERSION_1_1)
+ result = vk::SPIRV_VERSION_1_3;
+
+ DE_ASSERT(result < vk::SPIRV_VERSION_LAST);
+
+ return result;
+}
+
+vk::SpirvVersion getSpirvVersionForGlsl (const deUint32 vulkanVersion)
+{
+ vk::SpirvVersion result = vk::SPIRV_VERSION_LAST;
+
+ if (vulkanVersion == VK_API_VERSION_1_0)
+ result = vk::SPIRV_VERSION_1_0;
+ else if (vulkanVersion >= VK_API_VERSION_1_1)
+ result = vk::SPIRV_VERSION_1_3;
+
+ DE_ASSERT(result < vk::SPIRV_VERSION_LAST);
+
+ return result;
+}
+
+SpirvVersion extractSpirvVersion (const ProgramBinary& binary)
+{
+ DE_STATIC_ASSERT(SPIRV_VERSION_1_3 + 1 == SPIRV_VERSION_LAST);
+
+ if (binary.getFormat() != PROGRAM_FORMAT_SPIRV)
+ TCU_THROW(InternalError, "Binary is not in SPIR-V format");
+
+ if (!isSaneSpirVBinary(binary) || binary.getSize() < sizeof(SpirvBinaryHeader))
+ TCU_THROW(InternalError, "Invalid SPIR-V header format");
+
+ const deUint32 spirvBinaryVersion10 = 0x00010000;
+ const deUint32 spirvBinaryVersion11 = 0x00010100;
+ const deUint32 spirvBinaryVersion12 = 0x00010200;
+ const deUint32 spirvBinaryVersion13 = 0x00010300;
+ const SpirvBinaryHeader* header = reinterpret_cast<const SpirvBinaryHeader*>(binary.getBinary());
+ const deUint32 spirvVersion = isNativeSpirVBinaryEndianness()
+ ? header->version
+ : deReverseBytes32(header->version);
+ SpirvVersion result = SPIRV_VERSION_LAST;
+
+ switch (spirvVersion)
+ {
+ case spirvBinaryVersion10: result = SPIRV_VERSION_1_0; break; //!< SPIR-V 1.0
+ case spirvBinaryVersion11: result = SPIRV_VERSION_1_1; break; //!< SPIR-V 1.1
+ case spirvBinaryVersion12: result = SPIRV_VERSION_1_2; break; //!< SPIR-V 1.2
+ case spirvBinaryVersion13: result = SPIRV_VERSION_1_3; break; //!< SPIR-V 1.3
+ default: TCU_THROW(InternalError, "Unknown SPIR-V version detected in binary");
+ }
+
+ return result;
+}
+
+std::string getSpirvVersionName (const SpirvVersion spirvVersion)
+{
+ DE_STATIC_ASSERT(SPIRV_VERSION_1_3 + 1 == SPIRV_VERSION_LAST);
+ DE_ASSERT(spirvVersion < SPIRV_VERSION_LAST);
+
+ std::string result;
+
+ switch (spirvVersion)
+ {
+ case SPIRV_VERSION_1_0: result = "1.0"; break; //!< SPIR-V 1.0
+ case SPIRV_VERSION_1_1: result = "1.1"; break; //!< SPIR-V 1.1
+ case SPIRV_VERSION_1_2: result = "1.2"; break; //!< SPIR-V 1.2
+ case SPIRV_VERSION_1_3: result = "1.3"; break; //!< SPIR-V 1.3
+ default: result = "Unknown";
+ }
+
+ return result;
+}
+
+SpirvVersion& operator++(SpirvVersion& spirvVersion)
+{
+ if (spirvVersion == SPIRV_VERSION_LAST)
+ spirvVersion = SPIRV_VERSION_1_0;
+ else
+ spirvVersion = static_cast<SpirvVersion>(static_cast<deUint32>(spirvVersion) + 1);
+
+ return spirvVersion;
+}
+
} // vk
const std::vector<deUint8> m_binary;
};
-template<typename Program>
+struct BinaryBuildOptions
+{
+};
+
+template<typename Program, typename BuildOptions>
class ProgramCollection
{
public:
ProgramCollection (void);
+ ProgramCollection (const BuildOptions defaultBuildOptions);
~ProgramCollection (void);
void clear (void);
Program& add (const std::string& name);
+ Program& add (const std::string& name, const BuildOptions* buildOptions);
void add (const std::string& name, de::MovePtr<Program>& program);
bool contains (const std::string& name) const;
Iterator begin (void) const { return Iterator(m_programs.begin()); }
Iterator end (void) const { return Iterator(m_programs.end()); }
+ bool empty (void) const { return m_programs.empty(); }
+
private:
typedef std::map<std::string, Program*> ProgramMap;
ProgramMap m_programs;
+ BuildOptions m_defaultBuildOptions;
};
-template<typename Program>
-ProgramCollection<Program>::ProgramCollection (void)
+template<typename Program, typename BuildOptions>
+ProgramCollection<Program, BuildOptions>::ProgramCollection (void)
+{
+}
+
+template<typename Program, typename BuildOptions>
+ProgramCollection<Program, BuildOptions>::ProgramCollection (const BuildOptions defaultBuildOptions)
+ : m_programs()
+ , m_defaultBuildOptions(defaultBuildOptions)
{
}
-template<typename Program>
-ProgramCollection<Program>::~ProgramCollection (void)
+template<typename Program, typename BuildOptions>
+ProgramCollection<Program, BuildOptions>::~ProgramCollection (void)
{
clear();
}
-template<typename Program>
-void ProgramCollection<Program>::clear (void)
+template<typename Program, typename BuildOptions>
+void ProgramCollection<Program, BuildOptions>::clear (void)
{
for (typename ProgramMap::const_iterator i = m_programs.begin(); i != m_programs.end(); ++i)
delete i->second;
m_programs.clear();
}
-template<typename Program>
-Program& ProgramCollection<Program>::add (const std::string& name)
+template<typename Program, typename BuildOptions>
+Program& ProgramCollection<Program, BuildOptions>::add (const std::string& name)
{
DE_ASSERT(!contains(name));
de::MovePtr<Program> prog = de::newMovePtr<Program>();
+ prog->buildOptions = m_defaultBuildOptions;
m_programs[name] = prog.get();
prog.release();
return *m_programs[name];
}
-template<typename Program>
-void ProgramCollection<Program>::add (const std::string& name, de::MovePtr<Program>& program)
+template<typename Program, typename BuildOptions>
+Program& ProgramCollection<Program, BuildOptions>::add (const std::string& name, const BuildOptions* buildOptions)
+{
+ Program& program = add(name);
+
+ if (buildOptions != DE_NULL)
+ program << *buildOptions;
+
+ return program;
+}
+
+template<typename Program, typename BuildOptions>
+void ProgramCollection<Program, BuildOptions>::add (const std::string& name, de::MovePtr<Program>& program)
{
DE_ASSERT(!contains(name));
m_programs[name] = program.get();
program.release();
}
-template<typename Program>
-bool ProgramCollection<Program>::contains (const std::string& name) const
+template<typename Program, typename BuildOptions>
+bool ProgramCollection<Program, BuildOptions>::contains (const std::string& name) const
{
return de::contains(m_programs, name);
}
-template<typename Program>
-const Program& ProgramCollection<Program>::get (const std::string& name) const
+template<typename Program, typename BuildOptions>
+const Program& ProgramCollection<Program, BuildOptions>::get (const std::string& name) const
{
DE_ASSERT(contains(name));
return *m_programs.find(name)->second;
}
-typedef ProgramCollection<GlslSource> GlslSourceCollection;
-typedef ProgramCollection<HlslSource> HlslSourceCollection;
-typedef ProgramCollection<SpirVAsmSource> SpirVAsmCollection;
+typedef ProgramCollection<GlslSource, ShaderBuildOptions> GlslSourceCollection;
+typedef ProgramCollection<HlslSource, ShaderBuildOptions> HlslSourceCollection;
+typedef ProgramCollection<SpirVAsmSource, SpirVAsmBuildOptions> SpirVAsmCollection;
struct SourceCollections
{
+ SourceCollections (const deUint32 usedVulkanVersion_,
+ const ShaderBuildOptions& glslBuildOptions,
+ const ShaderBuildOptions& hlslBuildOptions,
+ const SpirVAsmBuildOptions& spirVAsmBuildOptions)
+ : usedVulkanVersion(usedVulkanVersion_)
+ , glslSources(glslBuildOptions)
+ , hlslSources(hlslBuildOptions)
+ , spirvAsmSources(spirVAsmBuildOptions)
+ {
+ }
+
+ deUint32 usedVulkanVersion;
GlslSourceCollection glslSources;
HlslSourceCollection hlslSources;
SpirVAsmCollection spirvAsmSources;
};
-typedef ProgramCollection<ProgramBinary> BinaryCollection;
+typedef ProgramCollection<ProgramBinary, BinaryBuildOptions> BinaryCollection;
ProgramBinary* buildProgram (const GlslSource& program, glu::ShaderProgramInfo* buildInfo);
ProgramBinary* buildProgram (const HlslSource& program, glu::ShaderProgramInfo* buildInfo);
ProgramBinary* assembleProgram (const vk::SpirVAsmSource& program, SpirVProgramInfo* buildInfo);
-void disassembleProgram (const ProgramBinary& program, std::ostream* dst);
-bool validateProgram (const ProgramBinary& program, std::ostream* dst);
+void disassembleProgram (const ProgramBinary& program, std::ostream* dst, SpirvVersion spirvVersion);
+bool validateProgram (const ProgramBinary& program, std::ostream* dst, SpirvVersion spirvVersion);
Move<VkShaderModule> createShaderModule (const DeviceInterface& deviceInterface, VkDevice device, const ProgramBinary& binary, VkShaderModuleCreateFlags flags);
glu::ShaderType getGluShaderType (VkShaderStageFlagBits shaderStage);
VkShaderStageFlagBits getVkShaderStage (glu::ShaderType shaderType);
+vk::SpirvVersion getSpirvVersionForAsm (const deUint32 vulkanVersion);
+vk::SpirvVersion getSpirvVersionForGlsl (const deUint32 vulkanVersion);
+SpirvVersion extractSpirvVersion (const ProgramBinary& binary);
+std::string getSpirvVersionName (const SpirvVersion spirvVersion);
+SpirvVersion& operator++ (SpirvVersion& spirvVersion);
+
} // vk
#endif // _VKPROGRAMS_HPP
TBuiltInResource builtinRes;
const EShMessages compileFlags = getCompileFlags(buildOptions, shaderLanguage);
- if (buildOptions.targetVersion != SPIRV_VERSION_1_0)
+ if (buildOptions.targetVersion >= SPIRV_VERSION_LAST)
TCU_THROW(InternalError, "Unsupported SPIR-V target version");
if (getNumShaderStages(sources) > 1)
glslang::TProgram glslangProgram;
shader.setStrings(srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs));
+
+ switch ( buildOptions.targetVersion )
+ {
+ case SPIRV_VERSION_1_0:
+ shader.setEnvTarget(glslang::EshTargetSpv, 0x10000);
+ break;
+ case SPIRV_VERSION_1_1:
+ shader.setEnvTarget(glslang::EshTargetSpv, 0x10100);
+ break;
+ case SPIRV_VERSION_1_2:
+ shader.setEnvTarget(glslang::EshTargetSpv, 0x10200);
+ break;
+ case SPIRV_VERSION_1_3:
+ shader.setEnvTarget(glslang::EshTargetSpv, 0x10300);
+ break;
+ }
+
glslangProgram.addShader(&shader);
if (shaderLanguage == SHADER_LANGUAGE_HLSL)
#if defined(DEQP_HAVE_SPIRV_TOOLS)
-static const spv_target_env s_defaultEnvironment = SPV_ENV_VULKAN_1_1;
+static spv_target_env mapTargetSpvEnvironment(SpirvVersion spirvVersion)
+{
+ spv_target_env result = SPV_ENV_UNIVERSAL_1_0;
+
+ switch (spirvVersion)
+ {
+ case SPIRV_VERSION_1_0: result = SPV_ENV_UNIVERSAL_1_0; break; //!< SPIR-V 1.0
+ case SPIRV_VERSION_1_1: result = SPV_ENV_UNIVERSAL_1_1; break; //!< SPIR-V 1.1
+ case SPIRV_VERSION_1_2: result = SPV_ENV_UNIVERSAL_1_2; break; //!< SPIR-V 1.2
+ case SPIRV_VERSION_1_3: result = SPV_ENV_UNIVERSAL_1_3; break; //!< SPIR-V 1.3
+ default: TCU_THROW(InternalError, "Unknown SPIR-V version");
+ }
+
+ return result;
+}
-bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo)
+bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo, SpirvVersion spirvVersion)
{
- const spv_context context = spvContextCreate(s_defaultEnvironment);
+ const spv_context context = spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
spv_binary binary = DE_NULL;
spv_diagnostic diagnostic = DE_NULL;
}
}
-void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst)
+void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst, SpirvVersion spirvVersion)
{
- const spv_context context = spvContextCreate(s_defaultEnvironment);
+ const spv_context context = spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
spv_text text = DE_NULL;
spv_diagnostic diagnostic = DE_NULL;
}
}
-bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog)
+bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog, SpirvVersion spirvVersion)
{
- const spv_context context = spvContextCreate(s_defaultEnvironment);
+ const spv_context context = spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
spv_diagnostic diagnostic = DE_NULL;
try
#else // defined(DEQP_HAVE_SPIRV_TOOLS)
-bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*)
+bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*, SpirvVersion)
{
TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}
-void disassembleSpirV (size_t, const deUint32*, std::ostream*)
+void disassembleSpirV (size_t, const deUint32*, std::ostream*, SpirvVersion)
{
TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}
-bool validateSpirV (size_t, const deUint32*, std::ostream*)
+bool validateSpirV (size_t, const deUint32*, std::ostream*, SpirvVersion)
{
TCU_THROW(NotSupportedError, "SPIR-V validation not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}
{
//! Assemble SPIR-V program. Will fail with NotSupportedError if compiler is not available.
-bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo);
+bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo, SpirvVersion spirvVersion);
//! Disassemble SPIR-V binary. Throws tcu::NotSupportedError if disassembler is not available
-void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst);
+void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst, SpirvVersion spirvVersion);
//! Validate SPIR-V binary, returning true if validation succeeds. Will fail with NotSupportedError if compiler is not available.
-bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog);
+bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog, SpirvVersion spirvVersion);
} // vk
namespace vk
{
+struct SpirVAsmBuildOptions
+{
+ SpirvVersion targetVersion;
+
+ SpirVAsmBuildOptions (SpirvVersion targetVersion_)
+ : targetVersion (targetVersion_)
+ {}
+
+ SpirVAsmBuildOptions (void)
+ : targetVersion (SPIRV_VERSION_1_0)
+ {}
+};
+
struct SpirVAsmSource
{
SpirVAsmSource (void)
{
}
- std::string source;
+ SpirVAsmSource& operator<< (const SpirVAsmBuildOptions& buildOptions_)
+ {
+ buildOptions = buildOptions_;
+ return *this;
+ };
+
+ SpirVAsmBuildOptions buildOptions;
+ std::string source;
};
struct SpirVProgramInfo
class Context
{
public:
- Context (const vk::InstanceInterface& vki,
- const vk::DeviceInterface& vkd,
- vk::VkPhysicalDevice physicalDevice,
- vk::VkDevice device,
- vk::VkQueue queue,
- deUint32 queueFamilyIndex,
- const vector<pair<deUint32, vk::VkQueue> >& queues,
- const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection)
+ Context (const vk::InstanceInterface& vki,
+ const vk::DeviceInterface& vkd,
+ vk::VkPhysicalDevice physicalDevice,
+ vk::VkDevice device,
+ vk::VkQueue queue,
+ deUint32 queueFamilyIndex,
+ const vector<pair<deUint32, vk::VkQueue> >& queues,
+ const vk::BinaryCollection& binaryCollection)
: m_vki (vki)
, m_vkd (vkd)
, m_physicalDevice (physicalDevice)
const vector<pair<deUint32, vk::VkQueue> >& getQueues (void) const { return m_queues; }
const vector<deUint32> getQueueFamilies (void) const { return m_queueFamilies; }
vk::VkCommandPool getCommandPool (void) const { return *m_commandPool; }
- const vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection (void) const { return m_binaryCollection; }
+ const vk::BinaryCollection& getBinaryCollection (void) const { return m_binaryCollection; }
private:
const vk::InstanceInterface& m_vki;
const deUint32 m_queueFamilyIndex;
const vector<pair<deUint32, vk::VkQueue> > m_queues;
const vk::Unique<vk::VkCommandPool> m_commandPool;
- const vk::ProgramCollection<vk::ProgramBinary>& m_binaryCollection;
+ const vk::BinaryCollection& m_binaryCollection;
vector<deUint32> m_queueFamilies;
};
const Memory& getMemory (void) const { return m_memory; }
const Context& getContext (void) const { return m_context; }
- const vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
+ const vk::BinaryCollection& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
void setBuffer (vk::Move<vk::VkBuffer> buffer,
vk::VkDeviceSize size)
{
}
- const Memory& getMemory (void) const { return m_context.getMemory(); }
- const Context& getContext (void) const { return m_context.getContext(); }
- const vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
+ const Memory& getMemory (void) const { return m_context.getMemory(); }
+ const Context& getContext (void) const { return m_context.getContext(); }
+ const vk::BinaryCollection& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
vk::VkBuffer getBuffer (void) const { return m_context.getBuffer(); }
vk::VkDeviceSize getBufferSize (void) const { return m_context.getBufferSize(); }
deUint32 getQueueFamilyIndex (void) const { return m_queueFamilyIndex; }
tcu::TestContext& getTestContext (void) const { return m_context.getTestContext(); }
- vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
+ vk::BinaryCollection& getBinaryCollection (void) const { return m_context.getBinaryCollection(); }
vk::Allocator& getDefaultAllocator (void) const { return *m_allocator; }
private:
return createPipelineLayout(vkd, device, &createInfo);
}
-Move<VkPipeline> createRenderPipeline (const DeviceInterface& vkd,
- VkDevice device,
- VkRenderPass renderPass,
- VkPipelineLayout pipelineLayout,
- const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection,
- deUint32 width,
- deUint32 height,
- deUint32 sampleCount)
+Move<VkPipeline> createRenderPipeline (const DeviceInterface& vkd,
+ VkDevice device,
+ VkRenderPass renderPass,
+ VkPipelineLayout pipelineLayout,
+ const vk::BinaryCollection& binaryCollection,
+ deUint32 width,
+ deUint32 height,
+ deUint32 sampleCount)
{
const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
return createPipelineLayout(vkd, device, &createInfo);
}
-Move<VkPipeline> createRenderPipeline (const DeviceInterface& vkd,
- VkDevice device,
- VkFormat srcFormat,
- VkRenderPass renderPass,
- VkPipelineLayout pipelineLayout,
- const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection,
- deUint32 width,
- deUint32 height,
- deUint32 sampleCount)
+Move<VkPipeline> createRenderPipeline (const DeviceInterface& vkd,
+ VkDevice device,
+ VkFormat srcFormat,
+ VkRenderPass renderPass,
+ VkPipelineLayout pipelineLayout,
+ const vk::BinaryCollection& binaryCollection,
+ deUint32 width,
+ deUint32 height,
+ deUint32 sampleCount)
{
const tcu::TextureFormat format (mapVkFormat(srcFormat));
const bool isDepthStencilFormat (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
return createPipelineLayout(vkd, device, &createInfo);
}
-Move<VkPipeline> createSplitPipeline (const DeviceInterface& vkd,
- VkDevice device,
- VkRenderPass renderPass,
- deUint32 subpassIndex,
- VkPipelineLayout pipelineLayout,
- const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection,
- deUint32 width,
- deUint32 height,
- deUint32 sampleCount)
+Move<VkPipeline> createSplitPipeline (const DeviceInterface& vkd,
+ VkDevice device,
+ VkRenderPass renderPass,
+ deUint32 subpassIndex,
+ VkPipelineLayout pipelineLayout,
+ const vk::BinaryCollection& binaryCollection,
+ deUint32 width,
+ deUint32 height,
+ deUint32 sampleCount)
{
const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u));
return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
}
-vector<VkPipelineSp> createSplitPipelines (const DeviceInterface& vkd,
- VkDevice device,
- VkRenderPass renderPass,
- VkPipelineLayout pipelineLayout,
- const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection,
- deUint32 width,
- deUint32 height,
- deUint32 sampleCount)
+vector<VkPipelineSp> createSplitPipelines (const DeviceInterface& vkd,
+ VkDevice device,
+ VkRenderPass renderPass,
+ VkPipelineLayout pipelineLayout,
+ const vk::BinaryCollection& binaryCollection,
+ deUint32 width,
+ deUint32 height,
+ deUint32 sampleCount)
{
std::vector<VkPipelineSp> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipelineSp)0u);
virtual void rendererDraw (const VkPipelineLayout pipelineLayout, const VkCommandBuffer cmdBuffer) const = 0;
};
- Renderer (const DeviceInterface& vk,
- const VkDevice device,
- Allocator& allocator,
- const deUint32 queueFamilyIndex,
- const VkDescriptorSetLayout descriptorSetLayout, //!< may be NULL, if no descriptors are used
- ProgramCollection<vk::ProgramBinary>& binaryCollection,
- const std::string& vertexName,
- const std::string& fragmentName,
- const VkBuffer colorBuffer,
- const IVec2& renderSize,
- const VkFormat colorFormat,
- const Vec4& clearColor,
- const VkPrimitiveTopology topology,
- SpecializationMap specMap = SpecializationMap())
+ Renderer (const DeviceInterface& vk,
+ const VkDevice device,
+ Allocator& allocator,
+ const deUint32 queueFamilyIndex,
+ const VkDescriptorSetLayout descriptorSetLayout, //!< may be NULL, if no descriptors are used
+ BinaryCollection& binaryCollection,
+ const std::string& vertexName,
+ const std::string& fragmentName,
+ const VkBuffer colorBuffer,
+ const IVec2& renderSize,
+ const VkFormat colorFormat,
+ const Vec4& clearColor,
+ const VkPrimitiveTopology topology,
+ SpecializationMap specMap = SpecializationMap())
: m_colorBuffer (colorBuffer)
, m_renderSize (renderSize)
, m_colorFormat (colorFormat)
vktSpvAsmUtils.hpp
vktSpvAsmVariablePointersTests.cpp
vktSpvAsmVariablePointersTests.hpp
+ vktSpvAsmSpirvVersionTests.cpp
+ vktSpvAsmSpirvVersionTests.hpp
+ vktSpvAsmLoopDepLenTests.cpp
+ vktSpvAsmLoopDepLenTests.hpp
+ vktSpvAsmLoopDepInfTests.cpp
+ vktSpvAsmLoopDepInfTests.hpp
)
set(DEQP_VK_SPIRV_ASSEMBLY_LIBS
namespace SpirVAssembly
{
-/*--------------------------------------------------------------------*//*!
- * \brief Test instance for compute pipeline
- *
- * The compute shader is specified in the format of SPIR-V assembly, which
- * is allowed to access MAX_NUM_INPUT_BUFFERS input storage buffers and
- * MAX_NUM_OUTPUT_BUFFERS output storage buffers maximally. The shader
- * source and input/output data are given in a ComputeShaderSpec object.
- *
- * This instance runs the given compute shader by feeding the data from input
- * buffers and compares the data in the output buffers with the expected.
- *//*--------------------------------------------------------------------*/
-class SpvAsmComputeShaderInstance : public TestInstance
-{
-public:
- SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec, const ComputeTestFeatures features);
- tcu::TestStatus iterate (void);
-
-private:
- const ComputeShaderSpec& m_shaderSpec;
- const ComputeTestFeatures m_features;
-};
-
// ComputeShaderTestCase implementations
SpvAsmComputeShaderCase::SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec, const ComputeTestFeatures features)
void SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection) const
{
- programCollection.spirvAsmSources.add("compute") << m_shaderSpec.assembly.c_str();
+ programCollection.spirvAsmSources.add("compute") << m_shaderSpec.assembly.c_str() << SpirVAsmBuildOptions(m_shaderSpec.spirvVersion);
}
TestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const
{
+ if (getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion) < ctx.getUsedApiVersion())
+ {
+ TCU_THROW(NotSupportedError, std::string("Vulkan higher than " + getVulkanName(ctx.getUsedApiVersion()) + " is required for this test to run").c_str());
+ }
return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec, m_features);
}
// Create compute shader and pipeline.
const ProgramBinary& binary = m_context.getBinaryCollection().get("compute");
+ if (m_shaderSpec.verifyBinary && !m_shaderSpec.verifyBinary(binary))
+ {
+ return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
+ }
Unique<VkShaderModule> module (createShaderModule(vkdi, device, binary, (VkShaderModuleCreateFlags)0u));
Unique<VkPipeline> computePipeline (createComputePipeline(vkdi, device, *pipelineLayout, *module, m_shaderSpec.entryPoint.c_str(), m_shaderSpec.specConstants));
COMPUTE_TEST_USES_INT16_INT64,
};
+/*--------------------------------------------------------------------*//*!
+ * \brief Test instance for compute pipeline
+ *
+ * The compute shader is specified in the format of SPIR-V assembly, which
+ * is allowed to access MAX_NUM_INPUT_BUFFERS input storage buffers and
+ * MAX_NUM_OUTPUT_BUFFERS output storage buffers maximally. The shader
+ * source and input/output data are given in a ComputeShaderSpec object.
+ *
+ * This instance runs the given compute shader by feeding the data from input
+ * buffers and compares the data in the output buffers with the expected.
+ *//*--------------------------------------------------------------------*/
+class SpvAsmComputeShaderInstance : public TestInstance
+{
+public:
+ SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec, const ComputeTestFeatures features);
+ tcu::TestStatus iterate (void);
+
+private:
+ const ComputeShaderSpec& m_shaderSpec;
+ const ComputeTestFeatures m_features;
+};
+
class SpvAsmComputeShaderCase : public TestCase
{
public:
const std::vector<BufferSp>& expectedOutputs,
tcu::TestLog& log);
+typedef bool (*ComputeVerifyBinaryFunc) (const ProgramBinary& binary);
+
/*--------------------------------------------------------------------*//*!
* \brief Specification for a compute shader.
*
// If true is returned, then the test case is assumed to have passed, if false is returned, then the test
// case is assumed to have failed. Exact meaning of failure can be customized with failResult.
ComputeVerifyIOFunc verifyIO;
+ ComputeVerifyBinaryFunc verifyBinary;
+ SpirvVersion spirvVersion;
ComputeShaderSpec (void)
: entryPoint ("main")
, failResult (QP_TEST_RESULT_FAIL)
, failMessage ("Output doesn't match with expected")
, verifyIO (DE_NULL)
+ , verifyBinary (DE_NULL)
+ , spirvVersion (SPIRV_VERSION_1_0)
{}
};
"OpName %BP_color \"color\"\n"
"OpName %BP_gl_VertexIndex \"gl_VertexIndex\"\n"
"OpName %BP_gl_InstanceIndex \"gl_InstanceIndex\"\n"
+ "${moduleprocessed:opt}\n"
"OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n"
"OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n"
"OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n"
"OpName %BP_gl_in \"gl_in\"\n"
"OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
"OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n"
+ "${moduleprocessed:opt}\n"
"OpDecorate %BP_out_color Location 1\n"
"OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n"
"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
"OpName %BP_gl_in \"gl_in\"\n"
"OpName %BP_out_color \"out_color\"\n"
"OpName %BP_in_color \"in_color\"\n"
+ "${moduleprocessed:opt}\n"
"OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n"
"OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n"
"OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n"
"OpName %BP_out_color \"out_color\"\n"
"OpName %BP_in_color \"in_color\"\n"
"OpName %test_code \"testfun(vf4;\"\n"
+ "${moduleprocessed:opt}\n"
"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
"OpDecorate %BP_out_gl_position BuiltIn Position\n"
"OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n"
"OpName %BP_fragColor \"fragColor\"\n"
"OpName %BP_vtxColor \"vtxColor\"\n"
"OpName %test_code \"testfun(vf4;\"\n"
+ "${moduleprocessed:opt}\n"
"OpDecorate %BP_fragColor Location 0\n"
"OpDecorate %BP_vtxColor Location 1\n"
"OpDecorate %BP_gl_FragCoord BuiltIn FragCoord\n"
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Vertex shader gets custom code from context, the rest are pass-through.
-void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context)
+void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
{
if (!context.interfaces.empty())
{
// Inject boilerplate code to wire up additional input/output variables between stages.
// Just copy the contents in input variable to output variable in all stages except
// the customized stage.
- dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(context.testCodeFragments);
- dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType()));
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
} else {
map<string, string> passthru = passthruFragments();
- dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments);
- dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
}
+void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext context)
+{
+ addShaderCodeCustomVertex(dst, context, DE_NULL);
+}
+
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Tessellation control shader gets custom code from context, the rest are
// pass-through.
-void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context)
+void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
{
if (!context.interfaces.empty())
{
// Inject boilerplate code to wire up additional input/output variables between stages.
// Just copy the contents in input variable to output variable in all stages except
// the customized stage.
- dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType()));
- dst.spirvAsmSources.add("tessc") << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(context.testCodeFragments);
- dst.spirvAsmSources.add("tesse") << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(passthruInterface(context.interfaces.getOutputType()));
- dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType()));
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
else
{
map<string, string> passthru = passthruFragments();
- dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
- dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments);
- dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
- dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
}
+void addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext context)
+{
+ addShaderCodeCustomTessControl(dst, context, DE_NULL);
+}
+
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Tessellation evaluation shader gets custom code from context, the rest are
// pass-through.
-void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context)
+void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
{
if (!context.interfaces.empty())
{
// Inject boilerplate code to wire up additional input/output variables between stages.
// Just copy the contents in input variable to output variable in all stages except
// the customized stage.
- dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType()));
- dst.spirvAsmSources.add("tessc") << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(passthruInterface(context.interfaces.getInputType()));
- dst.spirvAsmSources.add("tesse") << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments);
- dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType()));
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
else
{
map<string, string> passthru = passthruFragments();
- dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
- dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
- dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments);
- dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
}
+void addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext context)
+{
+ addShaderCodeCustomTessEval(dst, context, DE_NULL);
+}
+
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Geometry shader gets custom code from context, the rest are pass-through.
-void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context)
+void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
{
if (!context.interfaces.empty())
{
// Inject boilerplate code to wire up additional input/output variables between stages.
// Just copy the contents in input variable to output variable in all stages except
// the customized stage.
- dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType()));
- dst.spirvAsmSources.add("geom") << StringTemplate(makeGeometryShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments);
- dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType()));
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << StringTemplate(makeGeometryShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
else
{
map<string, string> passthru = passthruFragments();
- dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
- dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments);
- dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << makeGeometryShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
}
+void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext context)
+{
+ addShaderCodeCustomGeometry(dst, context, DE_NULL);
+}
+
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Fragment shader gets custom code from context, the rest are pass-through.
-void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context)
+void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
{
if (!context.interfaces.empty())
{
// Inject boilerplate code to wire up additional input/output variables between stages.
// Just copy the contents in input variable to output variable in all stages except
// the customized stage.
- dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType()));
- dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(context.testCodeFragments);
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
else
{
map<string, string> passthru = passthruFragments();
- dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
- dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments);
+ dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(context.resources.spirvVersion);
+ dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(context.resources.spirvVersion);
}
}
+void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext context)
+{
+ addShaderCodeCustomFragment(dst, context, DE_NULL);
+}
+
void createCombinedModule(vk::SourceCollections& dst, InstanceContext)
{
// \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional
TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
{
+ if (getMinRequiredVulkanVersion(instance.resources.spirvVersion) < context.getUsedApiVersion())
+ {
+ TCU_THROW(NotSupportedError, string("Vulkan higher than " + getVulkanName(context.getUsedApiVersion()) + " is required for this test to run").c_str());
+ }
+
const InstanceInterface& vkInstance = context.getInstanceInterface();
const VkPhysicalDevice vkPhysicalDevice = context.getPhysicalDevice();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
// We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline().
vector<vector<VkSpecializationMapEntry> > specConstantEntries;
vector<VkSpecializationInfo> specializationInfos;
+ if (DE_NULL != instance.resources.verifyBinary)
+ {
+ std::string shaderName;
+ switch(instance.customizedStages)
+ {
+ case VK_SHADER_STAGE_VERTEX_BIT:
+ shaderName= "vert";
+ break;
+ case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
+ shaderName= "tessc";
+ break;
+ case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
+ shaderName= "tesse";
+ break;
+ case VK_SHADER_STAGE_GEOMETRY_BIT:
+ shaderName= "geom";
+ break;
+ case VK_SHADER_STAGE_FRAGMENT_BIT:
+ shaderName= "frag";
+ break;
+ default:
+ DE_ASSERT(0);
+ break;
+ }
+ const ProgramBinary& binary = context.getBinaryCollection().get(shaderName);
+ if (!instance.resources.verifyBinary(binary))
+ return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
+
+ }
createPipelineShaderStages(vk, *vkDevice, instance, context, modules, shaderStageParams);
// And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents.
const std::vector<Resource>& expectedOutputs,
tcu::TestLog& log);
+typedef bool (*GraphicsVerifyBinaryFunc) (const ProgramBinary& binary);
+
// Resources used by graphics-pipeline-based tests.
struct GraphicsResources
{
// Resources used as inputs.
- std::vector<Resource> inputs;
+ std::vector<Resource> inputs;
// Resources used as outputs. The data supplied will be used as
// the expected outputs for the corresponding bindings by default.
// If other behaviors are needed, please provide a custom verifyIO.
- std::vector<Resource> outputs;
+ std::vector<Resource> outputs;
// If null, a default verification will be performed by comparing the
// memory pointed to by outputAllocations and the contents of
// expectedOutputs. Otherwise the function pointed to by verifyIO will
// be called. If true is returned, then the test case is assumed to
// have passed, if false is returned, then the test case is assumed
// to have failed.
- GraphicsVerifyIOFunc verifyIO;
+ GraphicsVerifyIOFunc verifyIO;
+ GraphicsVerifyBinaryFunc verifyBinary;
+ SpirvVersion spirvVersion;
GraphicsResources()
- : verifyIO (DE_NULL)
+ : verifyIO (DE_NULL)
+ , verifyBinary (DE_NULL)
+ , spirvVersion (SPIRV_VERSION_1_0)
{}
};
}
+void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
+void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
+void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
+void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
+void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
+
void createTestsForAllStages (const std::string& name,
const tcu::RGBA (&inputColors)[4],
const tcu::RGBA (&outputColors)[4],
#include "vktSpvAsmComputeShaderTestUtil.hpp"
#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
#include "vktSpvAsmVariablePointersTests.hpp"
+#include "vktSpvAsmSpirvVersionTests.hpp"
#include "vktTestCaseUtil.hpp"
+#include "vktSpvAsmLoopDepLenTests.hpp"
+#include "vktSpvAsmLoopDepInfTests.hpp"
#include <cmath>
#include <limits>
return group.release();
}
+bool veryfiBinaryShader (const ProgramBinary& binary)
+{
+ const size_t paternCount = 3u;
+ bool paternsCheck[paternCount] =
+ {
+ false, false, false
+ };
+ const string patersns[paternCount] =
+ {
+ "VULKAN CTS",
+ "Negative values",
+ "Date: 2017/09/21"
+ };
+ size_t paternNdx = 0u;
+
+ for (size_t ndx = 0u; ndx < binary.getSize(); ++ndx)
+ {
+ if (false == paternsCheck[paternNdx] &&
+ patersns[paternNdx][0] == static_cast<char>(binary.getBinary()[ndx]) &&
+ deMemoryEqual((const char*)&binary.getBinary()[ndx], &patersns[paternNdx][0], patersns[paternNdx].length()))
+ {
+ paternsCheck[paternNdx]= true;
+ paternNdx++;
+ if (paternNdx == paternCount)
+ break;
+ }
+ }
+
+ for (size_t ndx = 0u; ndx < paternCount; ++ndx)
+ {
+ if (!paternsCheck[ndx])
+ return false;
+ }
+
+ return true;
+}
+
+tcu::TestCaseGroup* createOpModuleProcessedGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opmoduleprocessed", "Test the OpModuleProcessed instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 10;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ spec.assembly =
+ string(getComputeAsmShaderPreamble()) +
+ "%fname = OpString \"negateInputs.comp\"\n"
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+ "OpModuleProcessed \"VULKAN CTS\"\n" //OpModuleProcessed;
+ "OpModuleProcessed \"Negative values\"\n"
+ "OpModuleProcessed \"Date: 2017/09/21\"\n"
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(getComputeAsmInputOutputBufferTraits())
+
+ + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
+
+ "OpLine %fname 0 1\n"
+
+ "OpLine %fname 1000 1\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%main = OpFunction %void None %voidf\n"
+
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.verifyBinary = veryfiBinaryShader;
+ spec.spirvVersion = SPIRV_VERSION_1_3;
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpModuleProcessed Tests", spec));
+
+ return group.release();
+}
+
tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnoline", "Test the OpNoLine instruction"));
group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
}
+ group->addChild(new SpvAsmLoopControlDependencyLengthCase(testCtx, "dependency_length", "dependency_length"));
+ group->addChild(new SpvAsmLoopControlDependencyInfiniteCase(testCtx, "dependency_infinite", "dependency_infinite"));
+
return group.release();
}
return opSourceTests.release();
}
-
tcu::TestCaseGroup* createOpNoLineTests(tcu::TestContext& testCtx)
{
RGBA defaultColors[4];
return opLineTests.release();
}
+tcu::TestCaseGroup* createOpModuleProcessedTests(tcu::TestContext& testCtx)
+{
+ RGBA defaultColors[4];
+ de::MovePtr<tcu::TestCaseGroup> opModuleProcessedTests (new tcu::TestCaseGroup(testCtx, "opmoduleprocessed", "OpModuleProcessed instruction"));
+ map<string, string> fragments;
+ std::vector<std::string> noExtensions;
+ GraphicsResources resources;
+
+ getDefaultColors(defaultColors);
+ resources.verifyBinary = veryfiBinaryShader;
+ resources.spirvVersion = SPIRV_VERSION_1_3;
+
+ fragments["moduleprocessed"] =
+ "OpModuleProcessed \"VULKAN CTS\"\n"
+ "OpModuleProcessed \"Negative values\"\n"
+ "OpModuleProcessed \"Date: 2017/09/21\"\n";
+
+ fragments["pre_main"] =
+ "%second_function = OpFunction %v4f32 None %v4f32_function\n"
+ "%second_param1 = OpFunctionParameter %v4f32\n"
+ "%label_secondfunction = OpLabel\n"
+ "OpReturnValue %second_param1\n"
+ "OpFunctionEnd\n";
+
+ fragments["testfun"] =
+ // A %test_code function that returns its argument unchanged.
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
+ "OpReturnValue %val1\n"
+ "OpFunctionEnd\n";
+
+ createTestsForAllStages ("opmoduleprocessed", defaultColors, defaultColors, fragments, resources, noExtensions, opModuleProcessedTests.get());
+
+ return opModuleProcessedTests.release();
+}
+
tcu::TestCaseGroup* createOpLineTests(tcu::TestContext& testCtx)
{
tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
{
+ const bool testComputePipeline = true;
+
de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute", "Compute Instructions with special opcodes/operands"));
de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics", "Graphics Instructions with special opcodes/operands"));
+ computeTests->addChild(createSpivVersionCheckTests(testCtx, testComputePipeline));
computeTests->addChild(createOpNopGroup(testCtx));
computeTests->addChild(createOpFUnordGroup(testCtx));
computeTests->addChild(createOpAtomicGroup(testCtx, false));
computeTests->addChild(createOpAtomicGroup(testCtx, true)); // Using new StorageBuffer decoration
computeTests->addChild(createOpLineGroup(testCtx));
+ computeTests->addChild(createOpModuleProcessedGroup(testCtx));
computeTests->addChild(createOpNoLineGroup(testCtx));
computeTests->addChild(createOpConstantNullGroup(testCtx));
computeTests->addChild(createOpConstantCompositeGroup(testCtx));
computeTests->addChild(createConditionalBranchComputeGroup(testCtx));
computeTests->addChild(createIndexingComputeGroup(testCtx));
computeTests->addChild(createVariablePointersComputeGroup(testCtx));
+ graphicsTests->addChild(createSpivVersionCheckTests(testCtx, !testComputePipeline));
graphicsTests->addChild(createOpNopTests(testCtx));
graphicsTests->addChild(createOpSourceTests(testCtx));
graphicsTests->addChild(createOpSourceContinuedTests(testCtx));
+ graphicsTests->addChild(createOpModuleProcessedTests(testCtx));
graphicsTests->addChild(createOpLineTests(testCtx));
graphicsTests->addChild(createOpNoLineTests(testCtx));
graphicsTests->addChild(createOpConstantNullTests(testCtx));
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Loop Control for DependencyInfinite qualifier tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vkApiVersion.hpp"
+
+#include "vktSpvAsmLoopDepInfTests.hpp"
+#include "vktTestCase.hpp"
+#include "vktSpvAsmComputeShaderCase.hpp"
+
+#include "deRandom.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+
+// Assembly code used for testing loop control with dependencies is based on GLSL source code:
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// void main() {
+// const uint n = 12;
+// float c[n];
+// uint x = gl_GlobalInvocationID.x;
+//
+// for (uint i = 0; i < n; ++i)
+// c[i] = float(i) * input_data.elements[x];
+//
+// output_data.elements[x] = 0.0f;
+// for (uint i = 0; i < n; ++i)
+// output_data.elements[x] += c[i];
+// }
+static void getComputeSourceCode (std::string& computeSourceCode)
+{
+ computeSourceCode =
+ string(getComputeAsmShaderPreamble()) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
+
+ "%u32ptr = OpTypePointer Function %u32\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%uzero = OpConstant %u32 0\n"
+ "%fzero = OpConstant %f32 0\n"
+ "%one = OpConstant %i32 1\n"
+ "%twelve = OpConstant %u32 12\n"
+ "%f32arr12_t = OpTypeArray %f32 %twelve\n"
+ "%f32arr12ptr_t = OpTypePointer Function %f32arr12_t\n"
+ "%f32funcptr = OpTypePointer Function %f32\n"
+ "%main = OpFunction %void None %voidf\n"
+ "%entry = OpLabel\n"
+
+ "%f32arr12 = OpVariable %f32arr12ptr_t Function\n"
+
+ "%i1 = OpVariable %u32ptr Function\n"
+ " OpStore %i1 %uzero\n"
+ "%i2 = OpVariable %u32ptr Function\n"
+ " OpStore %i2 %uzero\n"
+
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+
+ // for (uint i = 0; i < 12; ++i) c[i] = float(i) * input_data.elements[x];
+ " OpBranch %loop1_entry\n"
+ "%loop1_entry = OpLabel\n"
+ "%i1_val = OpLoad %u32 %i1\n"
+ "%cmp1_lt = OpULessThan %bool %i1_val %twelve\n"
+ " OpLoopMerge %loop1_merge %loop1_body DependencyInfinite\n"
+ " OpBranchConditional %cmp1_lt %loop1_body %loop1_merge\n"
+ "%loop1_body = OpLabel\n"
+ "%i1_valf32 = OpConvertUToF %f32 %i1_val\n"
+ "%mulf1 = OpFMul %f32 %i1_valf32 %inval\n"
+ "%outloc1 = OpAccessChain %f32funcptr %f32arr12 %i1_val\n"
+ " OpStore %outloc1 %mulf1\n"
+ "%new1_i = OpIAdd %u32 %i1_val %one\n"
+ " OpStore %i1 %new1_i\n"
+ " OpBranch %loop1_entry\n"
+ "%loop1_merge = OpLabel\n"
+
+ // output_data.elements[x] = 0.0f;
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %fzero\n"
+ " OpBranch %loop2_entry\n"
+
+ // for (uint i = 0; i < n; ++i) output_data.elements[x] += c[i];
+ "%loop2_entry = OpLabel\n"
+ "%i2_val = OpLoad %u32 %i2\n"
+ "%cmp2_lt = OpULessThan %bool %i2_val %twelve\n"
+ " OpLoopMerge %loop2_merge %loop2_body None\n"
+ " OpBranchConditional %cmp2_lt %loop2_body %loop2_merge\n"
+ "%loop2_body = OpLabel\n"
+ "%arr1_i2loc = OpAccessChain %f32funcptr %f32arr12 %i2_val\n"
+ "%arr1_i2val = OpLoad %f32 %arr1_i2loc\n"
+ "%outval = OpLoad %f32 %outloc\n"
+ "%addf1 = OpFAdd %f32 %outval %arr1_i2val\n"
+ " OpStore %outloc %addf1\n"
+ "%new_i2 = OpIAdd %u32 %i2_val %one\n"
+ " OpStore %i2 %new_i2\n"
+ " OpBranch %loop2_entry\n"
+ "%loop2_merge = OpLabel\n"
+
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+}
+
+static ComputeShaderSpec getComputeShaderSpec ()
+{
+ de::Random rnd (0xABC);
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+ ComputeShaderSpec spec;
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ inputFloats[ndx] = rnd.getFloat(1.0f, 100.0f);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ {
+ const deUint32 n = 12;
+ float c[n];
+ float result = 0.0f;
+
+ for (deUint32 i = 0; i < n; ++i)
+ c[i] = float(i) * inputFloats[ndx];
+
+ for (deUint32 i = 0; i < n; ++i)
+ result += c[i];
+
+ outputFloats[ndx] = result;
+ }
+
+ // Shader source code can be retrieved to complete definition of ComputeShaderSpec, though it is not required at this stage
+ // getComputeSourceCode (spec.assembly);
+
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = tcu::IVec3(numElements, 1, 1);
+
+ return spec;
+}
+
+
+class SpvAsmLoopControlDependencyInfiniteInstance : public ComputeShaderSpec, public SpvAsmComputeShaderInstance
+{
+public:
+ SpvAsmLoopControlDependencyInfiniteInstance (Context& ctx);
+};
+
+SpvAsmLoopControlDependencyInfiniteInstance::SpvAsmLoopControlDependencyInfiniteInstance (Context& ctx)
+ : ComputeShaderSpec(getComputeShaderSpec())
+ , SpvAsmComputeShaderInstance(ctx, *this, COMPUTE_TEST_USES_NONE)
+{
+}
+
+SpvAsmLoopControlDependencyInfiniteCase::SpvAsmLoopControlDependencyInfiniteCase (tcu::TestContext& testCtx, const char* name, const char* description)
+ : TestCase (testCtx, name, description)
+{
+}
+
+void SpvAsmLoopControlDependencyInfiniteCase::initPrograms (SourceCollections& programCollection) const
+{
+ std::string comp;
+
+ getComputeSourceCode(comp);
+
+ programCollection.spirvAsmSources.add("compute") << SpirVAsmBuildOptions(SPIRV_VERSION_1_3) << comp;
+}
+
+TestInstance* SpvAsmLoopControlDependencyInfiniteCase::createInstance (Context& context) const
+{
+ if (context.getUsedApiVersion() < VK_API_VERSION_1_1)
+ TCU_THROW(NotSupportedError, "SPIR-V higher than 1.3 is required for this test to run");
+
+ return new SpvAsmLoopControlDependencyInfiniteInstance(context);
+}
+
+} // SpirVAssembly
+} // vkt
--- /dev/null
+#ifndef _VKTSPVASMLOOPDEPINFTESTS_HPP
+#define _VKTSPVASMLOOPDEPINFTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Loop Control for DependencyInfinite qualifier tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vkPrograms.hpp"
+#include "vktTestCase.hpp"
+
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+class SpvAsmLoopControlDependencyInfiniteCase : public TestCase
+{
+public:
+ SpvAsmLoopControlDependencyInfiniteCase (tcu::TestContext& testCtx, const char* name, const char* description);
+ void initPrograms (vk::SourceCollections& programCollection) const;
+ TestInstance* createInstance (Context& context) const;
+};
+
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMLOOPDEPINFTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Loop Control for DependencyLength qualifier tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vkApiVersion.hpp"
+
+#include "vktSpvAsmLoopDepLenTests.hpp"
+#include "vktTestCase.hpp"
+#include "vktSpvAsmComputeShaderCase.hpp"
+
+#include "deRandom.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+
+// Assembly code used for testing loop control with dependencies is based on GLSL source code:
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// void main() {
+// const uint n = 12;
+// float c[n];
+// uint x = gl_GlobalInvocationID.x;
+//
+// for (uint i = 0; i < 6; ++i)
+// c[i] = float(i) * input_data.elements[x];
+//
+// for (uint i = 6; i < n; ++i)
+// c[i] = c[i - 4] + c[i - 5] + c[i - 6];
+//
+// output_data.elements[x] = c[n - 1];
+// }
+static void getComputeSourceCode (std::string& computeSourceCode)
+{
+ computeSourceCode =
+ string(getComputeAsmShaderPreamble()) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
+
+ "%u32ptr = OpTypePointer Function %u32\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%uzero = OpConstant %u32 0\n"
+ "%one = OpConstant %i32 1\n"
+
+ "%four = OpConstant %u32 4\n"
+ "%five = OpConstant %u32 5\n"
+ "%six = OpConstant %u32 6\n"
+ "%elleven = OpConstant %u32 11\n"
+ "%twelve = OpConstant %u32 12\n"
+
+ "%f32arr12_t = OpTypeArray %f32 %twelve\n"
+ "%f32arr12ptr_t = OpTypePointer Function %f32arr12_t\n"
+ "%f32funcptr = OpTypePointer Function %f32\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%entry = OpLabel\n"
+
+ "%f32arr12 = OpVariable %f32arr12ptr_t Function\n"
+
+ "%i1 = OpVariable %u32ptr Function\n"
+ " OpStore %i1 %uzero\n"
+ "%i2 = OpVariable %u32ptr Function\n"
+ " OpStore %i2 %six\n"
+
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+
+ // for (uint i = 0; i < 6; ++i) c[i] = float(i) * input_data.elements[x];
+ " OpBranch %loop1_entry\n"
+ "%loop1_entry = OpLabel\n"
+ "%i1_val = OpLoad %u32 %i1\n"
+ "%cmp1_lt = OpULessThan %bool %i1_val %six\n"
+ " OpLoopMerge %loop1_merge %loop1_body None\n"
+ " OpBranchConditional %cmp1_lt %loop1_body %loop1_merge\n"
+ "%loop1_body = OpLabel\n"
+ "%i1_valf32 = OpConvertUToF %f32 %i1_val\n"
+ "%mulf1 = OpFMul %f32 %i1_valf32 %inval\n"
+ "%outloc1 = OpAccessChain %f32funcptr %f32arr12 %i1_val\n"
+ " OpStore %outloc1 %mulf1\n"
+ "%new1_i = OpIAdd %u32 %i1_val %one\n"
+ " OpStore %i1 %new1_i\n"
+ " OpBranch %loop1_entry\n"
+ "%loop1_merge = OpLabel\n"
+
+ // for (uint i = 6; i < n; ++i) c[i] = c[i - 4] + c[i - 5] + c[i - 6];
+ " OpBranch %loop2_entry\n"
+ "%loop2_entry = OpLabel\n"
+ "%i2_val = OpLoad %u32 %i2\n"
+ "%cmp2_lt = OpULessThan %bool %i2_val %twelve\n"
+ " OpLoopMerge %loop2_merge %loop2_body DependencyLength 3\n"
+ " OpBranchConditional %cmp2_lt %loop2_body %loop2_merge\n"
+ "%loop2_body = OpLabel\n"
+ "%i2_m4 = OpISub %u32 %i2_val %four\n"
+ "%arr1_i2m4loc = OpAccessChain %f32funcptr %f32arr12 %i2_m4\n"
+ "%arr1_i2m4val = OpLoad %f32 %arr1_i2m4loc\n"
+ "%i2_m5 = OpISub %u32 %i2_val %five\n"
+ "%arr1_i2m5loc = OpAccessChain %f32funcptr %f32arr12 %i2_m5\n"
+ "%arr1_i2m5val = OpLoad %f32 %arr1_i2m5loc\n"
+ "%f32add1 = OpFAdd %f32 %arr1_i2m4val %arr1_i2m5val\n"
+ "%i2_m6 = OpISub %u32 %i2_val %six\n"
+ "%arr1_i2m6loc = OpAccessChain %f32funcptr %f32arr12 %i2_m6\n"
+ "%arr1_i2m6val = OpLoad %f32 %arr1_i2m6loc\n"
+ "%f32add2 = OpFAdd %f32 %f32add1 %arr1_i2m6val\n"
+ "%outloc2 = OpAccessChain %f32funcptr %f32arr12 %i2_val\n"
+ " OpStore %outloc2 %f32add2\n"
+ "%new_i2 = OpIAdd %u32 %i2_val %one\n"
+ " OpStore %i2 %new_i2\n"
+ " OpBranch %loop2_entry\n"
+ "%loop2_merge = OpLabel\n"
+
+ // output_data.elements[x] = c[n - 1];
+ "%arr1locq = OpAccessChain %f32funcptr %f32arr12 %elleven\n"
+ "%arr1valq = OpLoad %f32 %arr1locq\n"
+ "%outlocq = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outlocq %arr1valq\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+}
+
+static ComputeShaderSpec getComputeShaderSpec ()
+{
+ de::Random rnd (0xABC);
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+ ComputeShaderSpec spec;
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ inputFloats[ndx] = rnd.getFloat(1.0f, 100.0f);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ {
+ const deUint32 n = 12;
+ float c[n];
+
+ for (deUint32 i = 0; i < 6; ++i)
+ c[i] = float(i) * inputFloats[ndx];
+
+ for (deUint32 i = 6; i < n; ++i)
+ c[i] = c[i - 4] + c[i - 5] + c[i - 6];
+
+ outputFloats[ndx] = c[n - 1];
+ }
+
+ // Shader source code can be retrieved to complete definition of ComputeShaderSpec, though it is not required at this stage
+ // getComputeSourceCode (spec.assembly);
+
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = tcu::IVec3(numElements, 1, 1);
+
+ return spec;
+}
+
+
+class SpvAsmLoopControlDependencyLengthInstance : public ComputeShaderSpec, public SpvAsmComputeShaderInstance
+{
+public:
+ SpvAsmLoopControlDependencyLengthInstance (Context& ctx);
+};
+
+SpvAsmLoopControlDependencyLengthInstance::SpvAsmLoopControlDependencyLengthInstance (Context& ctx)
+ : ComputeShaderSpec(getComputeShaderSpec())
+ , SpvAsmComputeShaderInstance(ctx, *this, COMPUTE_TEST_USES_NONE)
+{
+}
+
+SpvAsmLoopControlDependencyLengthCase::SpvAsmLoopControlDependencyLengthCase (tcu::TestContext& testCtx, const char* name, const char* description)
+ : TestCase (testCtx, name, description)
+{
+}
+
+void SpvAsmLoopControlDependencyLengthCase::initPrograms (SourceCollections& programCollection) const
+{
+ std::string comp;
+
+ getComputeSourceCode(comp);
+
+ programCollection.spirvAsmSources.add("compute") << SpirVAsmBuildOptions(SPIRV_VERSION_1_3) << comp;
+}
+
+TestInstance* SpvAsmLoopControlDependencyLengthCase::createInstance (Context& context) const
+{
+ if (context.getUsedApiVersion() < VK_API_VERSION_1_1)
+ TCU_THROW(NotSupportedError, "SPIR-V higher than 1.3 is required for this test to run");
+
+ return new SpvAsmLoopControlDependencyLengthInstance(context);
+}
+
+} // SpirVAssembly
+} // vkt
--- /dev/null
+#ifndef _VKTSPVASMLOOPDEPLENTESTS_HPP
+#define _VKTSPVASMLOOPDEPLENTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Loop Control for DependencyLength qualifier tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vkPrograms.hpp"
+#include "vktTestCase.hpp"
+
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+class SpvAsmLoopControlDependencyLengthCase : public TestCase
+{
+public:
+ SpvAsmLoopControlDependencyLengthCase (tcu::TestContext& testCtx, const char* name, const char* description);
+ void initPrograms (vk::SourceCollections& programCollection) const;
+ TestInstance* createInstance (Context& context) const;
+};
+
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMLOOPDEPLENTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Versions check cases
+ *//*--------------------------------------------------------------------*/
+
+#include "vkApiVersion.hpp"
+
+#include "vktSpvAsmSpirvVersionTests.hpp"
+#include "vktTestCase.hpp"
+#include "vktSpvAsmComputeShaderCase.hpp"
+#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+using tcu::RGBA;
+
+enum Operation
+{
+ OPERATION_COMPUTE = 0,
+ OPERATION_GRAPHICS_VERTEX,
+ OPERATION_GRAPHICS_TESSELATION_EVALUATION,
+ OPERATION_GRAPHICS_TESSELATION_CONTROL,
+ OPERATION_GRAPHICS_GEOMETRY,
+ OPERATION_GRAPHICS_FRAGMENT,
+ OPERATION_LAST
+};
+
+Operation& operator++ (Operation& operation)
+{
+ if (operation == OPERATION_LAST)
+ operation = OPERATION_COMPUTE;
+ else
+ operation = static_cast<Operation>(static_cast<deUint32>(operation) + 1);
+
+ return operation;
+}
+
+struct TestParameters
+{
+ Operation operation;
+ SpirvVersion spirvVersion;
+};
+
+static InstanceContext initGraphicsInstanceContext (const TestParameters& testParameters)
+{
+ static const ShaderElement vertFragPipelineStages[] =
+ {
+ ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
+ };
+ static const ShaderElement tessPipelineStages[] =
+ {
+ ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+ ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+ ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
+ };
+ static const ShaderElement geomPipelineStages[] =
+ {
+ ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+ ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
+ };
+ map<string, string> opSimpleTest;
+
+ opSimpleTest["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%b = OpFAdd %f32 %a %a\n"
+ "%c = OpFSub %f32 %b %a\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n";
+
+ switch (testParameters.operation)
+ {
+ case OPERATION_GRAPHICS_VERTEX: return createInstanceContext(vertFragPipelineStages, opSimpleTest);
+ case OPERATION_GRAPHICS_TESSELATION_EVALUATION: return createInstanceContext(tessPipelineStages, opSimpleTest);
+ case OPERATION_GRAPHICS_TESSELATION_CONTROL: return createInstanceContext(tessPipelineStages, opSimpleTest);
+ case OPERATION_GRAPHICS_GEOMETRY: return createInstanceContext(geomPipelineStages, opSimpleTest);
+ case OPERATION_GRAPHICS_FRAGMENT: return createInstanceContext(vertFragPipelineStages, opSimpleTest);
+ default: TCU_THROW(InternalError, "Invalid operation specified");
+ }
+}
+
+static void getComputeSourceCode (std::string& computeSourceCode)
+{
+ computeSourceCode =
+ string(getComputeAsmShaderPreamble()) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n" +
+
+ string(getComputeAsmInputOutputBufferTraits()) +
+ string(getComputeAsmCommonTypes()) +
+ string(getComputeAsmInputOutputBuffer()) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+
+ " OpNop\n" // Inside a function body
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+}
+
+static ComputeShaderSpec getComputeShaderSpec (const TestParameters& testParameters)
+{
+ ComputeShaderSpec spec;
+ const deUint32 seed = (static_cast<deUint32>(testParameters.operation)<<16) ^ static_cast<deUint32>(testParameters.spirvVersion);
+ de::Random rnd (seed);
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ {
+ positiveFloats[ndx] = rnd.getFloat(1.0f, 100.0f);
+ negativeFloats[ndx] = -positiveFloats[ndx];
+ }
+
+ // Shader source code can be retrieved to complete definition of ComputeShaderSpec, though it is not required at this stage
+ // getComputeSourceCode (spec.assembly);
+
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = tcu::IVec3(numElements, 1, 1);
+
+ return spec;
+}
+
+static bool isSpirVersionsAsRequested (const BinaryCollection& binaryCollection, SpirvVersion requestedSpirvVersion)
+{
+ bool result = true;
+
+ DE_ASSERT(!binaryCollection.empty());
+
+ for (vk::BinaryCollection::Iterator binaryIt = binaryCollection.begin(); binaryIt != binaryCollection.end(); ++binaryIt)
+ {
+ SpirvVersion binarySpirvVersion = extractSpirvVersion (binaryIt.getProgram());
+
+ if (binarySpirvVersion != requestedSpirvVersion)
+ result = false;
+ }
+
+ return result;
+}
+
+class SpvAsmGraphicsSpirvVersionsInstance : public TestInstance
+{
+public:
+ SpvAsmGraphicsSpirvVersionsInstance (Context& ctx, const TestParameters& testParameters);
+ tcu::TestStatus iterate (void);
+
+private:
+ TestParameters m_testParameters;
+};
+
+SpvAsmGraphicsSpirvVersionsInstance::SpvAsmGraphicsSpirvVersionsInstance (Context& ctx, const TestParameters& testParameters)
+ : TestInstance (ctx)
+ , m_testParameters (testParameters)
+{
+}
+
+tcu::TestStatus SpvAsmGraphicsSpirvVersionsInstance::iterate (void)
+{
+ InstanceContext instanceContext = initGraphicsInstanceContext(m_testParameters);
+
+ if (!isSpirVersionsAsRequested(m_context.getBinaryCollection(), m_testParameters.spirvVersion))
+ return tcu::TestStatus::fail("Binary SPIR-V version is different from requested");
+
+ return runAndVerifyDefaultPipeline(m_context, instanceContext);
+}
+
+
+class SpvAsmComputeSpirvVersionsInstance : public ComputeShaderSpec, public SpvAsmComputeShaderInstance
+{
+public:
+ SpvAsmComputeSpirvVersionsInstance (Context& ctx, const TestParameters& testParameters);
+ tcu::TestStatus iterate (void);
+
+private:
+ TestParameters m_testParameters;
+};
+
+SpvAsmComputeSpirvVersionsInstance::SpvAsmComputeSpirvVersionsInstance (Context& ctx, const TestParameters& testParameters)
+ : ComputeShaderSpec(getComputeShaderSpec(testParameters))
+ , SpvAsmComputeShaderInstance(ctx, *this, COMPUTE_TEST_USES_NONE)
+ , m_testParameters(testParameters)
+{
+ if (m_testParameters.operation != OPERATION_COMPUTE)
+ TCU_THROW(InternalError, "Invalid operation specified");
+}
+
+tcu::TestStatus SpvAsmComputeSpirvVersionsInstance::iterate (void)
+{
+ if (!isSpirVersionsAsRequested(m_context.getBinaryCollection(), m_testParameters.spirvVersion))
+ return tcu::TestStatus::fail("Binary SPIR-V version is different from requested");
+
+ return SpvAsmComputeShaderInstance::iterate();
+}
+
+
+class SpvAsmSpirvVersionsCase : public TestCase
+{
+public:
+ SpvAsmSpirvVersionsCase (tcu::TestContext& testCtx, const char* name, const char* description, const TestParameters& testParameters);
+ void initPrograms (vk::SourceCollections& programCollection) const;
+ TestInstance* createInstance (Context& context) const;
+
+private:
+ const TestParameters m_testParameters;
+};
+
+SpvAsmSpirvVersionsCase::SpvAsmSpirvVersionsCase (tcu::TestContext& testCtx, const char* name, const char* description, const TestParameters& testParameters)
+ : TestCase (testCtx, name, description)
+ , m_testParameters (testParameters)
+{
+}
+
+void validateVulkanVersion (const deUint32 usedVulkanVersion, const SpirvVersion testedSpirvVersion)
+{
+ const SpirvVersion usedSpirvVersionForAsm = getSpirvVersionForAsm(usedVulkanVersion);
+
+ if (testedSpirvVersion > usedSpirvVersionForAsm)
+ TCU_THROW(NotSupportedError, "Specified SPIR-V version is not supported by the device/instance");
+}
+
+void SpvAsmSpirvVersionsCase::initPrograms (SourceCollections& programCollection) const
+{
+ const SpirVAsmBuildOptions spirVAsmBuildOptions (m_testParameters.spirvVersion);
+
+ validateVulkanVersion(programCollection.usedVulkanVersion, m_testParameters.spirvVersion);
+
+ switch (m_testParameters.operation)
+ {
+ case OPERATION_COMPUTE:
+ {
+ std::string comp;
+
+ getComputeSourceCode(comp);
+
+ programCollection.spirvAsmSources.add("compute", &spirVAsmBuildOptions) << comp;
+
+ break;
+ }
+
+ case OPERATION_GRAPHICS_VERTEX:
+ {
+ InstanceContext instanceContext = initGraphicsInstanceContext(m_testParameters);
+
+ addShaderCodeCustomVertex(programCollection, instanceContext, &spirVAsmBuildOptions);
+
+ break;
+ }
+
+ case OPERATION_GRAPHICS_TESSELATION_EVALUATION:
+ {
+ InstanceContext instanceContext = initGraphicsInstanceContext(m_testParameters);
+
+ addShaderCodeCustomTessEval(programCollection, instanceContext, &spirVAsmBuildOptions);
+
+ break;
+ }
+
+ case OPERATION_GRAPHICS_TESSELATION_CONTROL:
+ {
+ InstanceContext instanceContext = initGraphicsInstanceContext(m_testParameters);
+
+ addShaderCodeCustomTessControl(programCollection, instanceContext, &spirVAsmBuildOptions);
+
+ break;
+ }
+
+ case OPERATION_GRAPHICS_GEOMETRY:
+ {
+ InstanceContext instanceContext = initGraphicsInstanceContext(m_testParameters);
+
+ addShaderCodeCustomGeometry(programCollection, instanceContext, &spirVAsmBuildOptions);
+
+ break;
+ }
+
+ case OPERATION_GRAPHICS_FRAGMENT:
+ {
+ InstanceContext instanceContext = initGraphicsInstanceContext(m_testParameters);
+
+ addShaderCodeCustomFragment(programCollection, instanceContext, &spirVAsmBuildOptions);
+
+ break;
+ }
+
+ default:
+ TCU_THROW(InternalError, "Invalid operation specified");
+ }
+}
+
+TestInstance* SpvAsmSpirvVersionsCase::createInstance (Context& context) const
+{
+ validateVulkanVersion(context.getUsedApiVersion(), m_testParameters.spirvVersion);
+
+ switch (m_testParameters.operation)
+ {
+ case OPERATION_COMPUTE:
+ return new SpvAsmComputeSpirvVersionsInstance(context, m_testParameters);
+
+ case OPERATION_GRAPHICS_VERTEX:
+ case OPERATION_GRAPHICS_TESSELATION_EVALUATION:
+ case OPERATION_GRAPHICS_TESSELATION_CONTROL:
+ case OPERATION_GRAPHICS_GEOMETRY:
+ case OPERATION_GRAPHICS_FRAGMENT:
+ return new SpvAsmGraphicsSpirvVersionsInstance(context, m_testParameters);
+
+ default:
+ TCU_THROW(InternalError, "Invalid operation specified");
+ }
+}
+
+tcu::TestCaseGroup* createSpivVersionCheckTests (tcu::TestContext& testCtx, const bool compute)
+{
+ const char* operationNames[OPERATION_LAST] =
+ {
+ "compute",
+ "vertex",
+ "tesselation_evaluation",
+ "tesselation_control",
+ "geometry",
+ "fragment",
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "spirv_version", "Test SPIR-V version is supported"));
+
+ for (SpirvVersion spirvVersion = SPIRV_VERSION_1_0; spirvVersion < SPIRV_VERSION_LAST; ++spirvVersion)
+ {
+ std::string spirvVersionName = getSpirvVersionName(spirvVersion);
+
+ std::replace(spirvVersionName.begin(), spirvVersionName.end(), '.', '_');
+
+ for (Operation operation = OPERATION_COMPUTE; operation < OPERATION_LAST; ++operation)
+ {
+ if ((compute && operation == OPERATION_COMPUTE) || (!compute && operation != OPERATION_COMPUTE))
+ {
+ const std::string testName = spirvVersionName + "_" + operationNames[static_cast<deUint32>(operation)];
+ const TestParameters testParameters =
+ {
+ operation,
+ spirvVersion
+ };
+
+ group->addChild(new SpvAsmSpirvVersionsCase(testCtx, testName.c_str(), "", testParameters));
+ }
+ }
+ }
+
+ return group.release();
+}
+
+} // SpirVAssembly
+} // vkt
--- /dev/null
+#ifndef _VKTSPVASMSPIRVVERSIONTESTS_HPP
+#define _VKTSPVASMSPIRVVERSIONTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Versions check cases
+ *//*--------------------------------------------------------------------*/
+
+#include "vkPrograms.hpp"
+#include "vktTestCase.hpp"
+
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup* createSpivVersionCheckTests(tcu::TestContext& testCtx, const bool compute);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMSPIRVVERSIONTESTS_HPP
return new SimpleAllocator(deviceInterface, device, memoryProperties);
}
+deUint32 getMinRequiredVulkanVersion (const SpirvVersion version)
+{
+ switch(version)
+ {
+ case SPIRV_VERSION_1_0:
+ return VK_API_VERSION_1_0;
+ case SPIRV_VERSION_1_1:
+ case SPIRV_VERSION_1_2:
+ case SPIRV_VERSION_1_3:
+ return VK_API_VERSION_1_1;
+ default:
+ DE_ASSERT(0);
+ }
+ return 0u;
+}
+
+std::string getVulkanName (const deUint32 version)
+{
+ return std::string(version == VK_API_VERSION_1_1 ? "1.1" : "1.0");
+}
+
} // SpirVAssembly
} // vkt
const vk::DeviceInterface& deviceInterface,
const vk::VkDevice device);
+deUint32 getMinRequiredVulkanVersion (const vk::SpirvVersion version);
+
+std::string getVulkanName (const deUint32 version);
+
} // SpirVAssembly
} // vkt
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);;
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str())<< vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
programCollection.glslSources.add("vert")
- << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage));
+ << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
std::ostringstream frag;
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
programCollection.glslSources.add("vert")
- << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage));
+ << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
std::ostringstream src;
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
programCollection.glslSources.add("vert")
- << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage));
+ << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
programCollection.glslSources.add("tesc")
<< glu::TessellationControlSource("#version 450\nlayout(vertices=1) out;\nvoid main (void) { for(uint i = 0; i < 4; i++) { gl_TessLevelOuter[i] = 1.0f; } }\n");
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
<< "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
<< "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
bool vkt::subgroups::isSubgroupSupported(Context& context)
{
- VkPhysicalDeviceProperties properties;
- context.getInstanceInterface().getPhysicalDeviceProperties(context.getPhysicalDevice(), &properties);
- return (properties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) ? false : true;
+ return context.getUsedApiVersion() < VK_API_VERSION_1_1 ? false : true;
}
bool vkt::subgroups::areSubgroupOperationsSupportedForStage(
src << "}\n";
programCollection.glslSources.add("comp")
- << glu::ComputeSource(src.str());
+ << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
{
frag << "}\n";
programCollection.glslSources.add("frag")
- << glu::FragmentSource(frag.str());
+ << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
{
src << "}\n";
programCollection.glslSources.add("vert")
- << glu::VertexSource(src.str());
+ << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
{
src << "}\n";
programCollection.glslSources.add("geom")
- << glu::GeometrySource(src.str());
+ << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
{
src << "}\n";
programCollection.glslSources.add("tesc")
- << glu::TessellationControlSource(src.str());
+ << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
{
src << "}\n";
programCollection.glslSources.add("tese")
- << glu::TessellationEvaluationSource(src.str());
+ << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
}
else
{
{
}
-OperationContext::OperationContext (const deUint32 apiVersion,
- const vk::InstanceInterface& vki,
- const vk::DeviceInterface& vkd,
- vk::VkPhysicalDevice physicalDevice,
- vk::VkDevice device,
- vk::Allocator& allocator,
- const std::vector<std::string>& deviceExtensions,
- vk::ProgramCollection<vk::ProgramBinary>& programCollection,
- PipelineCacheData& pipelineCacheData)
+OperationContext::OperationContext (const deUint32 apiVersion,
+ const vk::InstanceInterface& vki,
+ const vk::DeviceInterface& vkd,
+ vk::VkPhysicalDevice physicalDevice,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ const std::vector<std::string>& deviceExtensions,
+ vk::BinaryCollection& programCollection,
+ PipelineCacheData& pipelineCacheData)
: m_vki (vki)
, m_vk (vkd)
, m_physicalDevice (physicalDevice)
class OperationContext
{
public:
- OperationContext (Context& context,
- PipelineCacheData& pipelineCacheData);
+ OperationContext (Context& context,
+ PipelineCacheData& pipelineCacheData);
- OperationContext (Context& context,
- PipelineCacheData& pipelineCacheData,
- const vk::DeviceInterface& vk,
- const vk::VkDevice device,
- vk::Allocator& allocator);
+ OperationContext (Context& context,
+ PipelineCacheData& pipelineCacheData,
+ const vk::DeviceInterface& vk,
+ const vk::VkDevice device,
+ vk::Allocator& allocator);
- OperationContext (const deUint32 apiVersion,
- const vk::InstanceInterface& vki,
- const vk::DeviceInterface& vkd,
- vk::VkPhysicalDevice physicalDevice,
- vk::VkDevice device,
- vk::Allocator& allocator,
- const std::vector<std::string>& deviceExtensions,
- vk::ProgramCollection<vk::ProgramBinary>& programCollection,
- PipelineCacheData& pipelineCacheData);
+ OperationContext (const deUint32 apiVersion,
+ const vk::InstanceInterface& vki,
+ const vk::DeviceInterface& vkd,
+ vk::VkPhysicalDevice physicalDevice,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ const std::vector<std::string>& deviceExtensions,
+ vk::BinaryCollection& programCollection,
+ PipelineCacheData& pipelineCacheData);
+
+ const vk::InstanceInterface& getInstanceInterface (void) const { return m_vki; }
+ const vk::DeviceInterface& getDeviceInterface (void) const { return m_vk; }
+ vk::VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
+ vk::VkDevice getDevice (void) const { return m_device; }
+ vk::Allocator& getAllocator (void) const { return m_allocator; }
+ vk::BinaryCollection& getBinaryCollection (void) const { return m_progCollection; }
+ PipelineCacheData& getPipelineCacheData (void) const { return m_pipelineCacheData; }
+ const std::vector<std::string>& getDeviceExtensions (void) const { return m_deviceExtensions;}
+ deUint32 getUsedApiVersion (void) const { return m_usedApiVersion; }
- const vk::InstanceInterface& getInstanceInterface (void) const { return m_vki; }
- const vk::DeviceInterface& getDeviceInterface (void) const { return m_vk; }
- vk::VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
- vk::VkDevice getDevice (void) const { return m_device; }
- vk::Allocator& getAllocator (void) const { return m_allocator; }
- vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection (void) const { return m_progCollection; }
- PipelineCacheData& getPipelineCacheData (void) const { return m_pipelineCacheData; }
- const std::vector<std::string>& getDeviceExtensions (void) const { return m_deviceExtensions;}
- deUint32 getUsedApiVersion (void) const { return m_usedApiVersion; }
private:
- const vk::InstanceInterface& m_vki;
- const vk::DeviceInterface& m_vk;
- const vk::VkPhysicalDevice m_physicalDevice;
- const vk::VkDevice m_device;
- vk::Allocator& m_allocator;
- vk::ProgramCollection<vk::ProgramBinary>& m_progCollection;
- PipelineCacheData& m_pipelineCacheData;
- const std::vector<std::string>& m_deviceExtensions;
- const deUint32 m_usedApiVersion;
+ const vk::InstanceInterface& m_vki;
+ const vk::DeviceInterface& m_vk;
+ const vk::VkPhysicalDevice m_physicalDevice;
+ const vk::VkDevice m_device;
+ vk::Allocator& m_allocator;
+ vk::BinaryCollection& m_progCollection;
+ PipelineCacheData& m_pipelineCacheData;
+ const std::vector<std::string>& m_deviceExtensions;
+ const deUint32 m_usedApiVersion;
// Disabled
- OperationContext (const OperationContext&);
- OperationContext& operator= (const OperationContext&);
+ OperationContext (const OperationContext&);
+ OperationContext& operator= (const OperationContext&);
};
// Common interface to images and buffers used by operations.
Status validationStatus;
std::string validationLog;
- explicit Program (const vk::ProgramIdentifier& id_)
+ vk::SpirvVersion spirvVersion;
+
+ explicit Program (const vk::ProgramIdentifier& id_, const vk::SpirvVersion spirvVersion_)
: id (id_)
, buildStatus (STATUS_NOT_COMPLETED)
, validationStatus (STATUS_NOT_COMPLETED)
+ , spirvVersion (spirvVersion_)
{}
Program (void)
: id ("", "")
, buildStatus (STATUS_NOT_COMPLETED)
, validationStatus (STATUS_NOT_COMPLETED)
+ , spirvVersion (vk::SPIRV_VERSION_LAST)
{}
};
try
{
+ DE_ASSERT(m_source.buildOptions.targetVersion < vk::SPIRV_VERSION_LAST);
+
m_program->binary = ProgramBinarySp(vk::buildProgram(m_source, &buildInfo));
m_program->buildStatus = Program::STATUS_PASSED;
}
m_program->buildStatus = Program::STATUS_FAILED;
m_program->buildLog = log.str();
-
}
}
try
{
+ DE_ASSERT(m_source.buildOptions.targetVersion < vk::SPIRV_VERSION_LAST);
+
m_program->binary = ProgramBinarySp(vk::assembleProgram(m_source, &buildInfo));
m_program->buildStatus = Program::STATUS_PASSED;
}
void execute (void)
{
DE_ASSERT(m_program->buildStatus == Program::STATUS_PASSED);
+ DE_ASSERT(m_program->binary->getFormat() == vk::PROGRAM_FORMAT_SPIRV);
- std::ostringstream validationLog;
+ std::ostringstream validationLog;
+ const vk::ProgramBinary& programBinary = *(m_program->binary);
+ const vk::SpirvVersion spirvVersion = vk::extractSpirvVersion(programBinary);
- if (vk::validateProgram(*m_program->binary, &validationLog))
+ if (vk::validateProgram(*m_program->binary, &validationLog, spirvVersion))
m_program->validationStatus = Program::STATUS_PASSED;
else
m_program->validationStatus = Program::STATUS_FAILED;
{
int numSucceeded;
int numFailed;
+ int notSupported;
BuildStats (void)
: numSucceeded (0)
, numFailed (0)
+ , notSupported (0)
{
}
};
-BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath, bool validateBinaries)
+BuildStats buildPrograms (tcu::TestContext& testCtx,
+ const std::string& dstPath,
+ const bool validateBinaries,
+ const deUint32 usedVulkanVersion,
+ const vk::SpirvVersion spirvVersionForGlsl,
+ const vk::SpirvVersion spirvVersionForAsm)
{
const deUint32 numThreads = deGetNumAvailableLogicalCores();
// de::PoolArray<> is faster to build than std::vector
de::MemPool programPool;
de::PoolArray<Program> programs (&programPool);
+ int notSupported = 0;
{
de::MemPool tmpPool;
if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
{
- const TestCase* const testCase = dynamic_cast<TestCase*>(iterator.getNode());
- const string casePath = iterator.getNodePath();
- vk::SourceCollections sourcePrograms;
-
- testCase->initPrograms(sourcePrograms);
+ const TestCase* const testCase = dynamic_cast<TestCase*>(iterator.getNode());
+ const string casePath = iterator.getNodePath();
+ vk::ShaderBuildOptions defaultGlslBuildOptions (spirvVersionForGlsl, 0u);
+ vk::ShaderBuildOptions defaultHlslBuildOptions (spirvVersionForGlsl, 0u);
+ vk::SpirVAsmBuildOptions defaultSpirvAsmBuildOptions (spirvVersionForAsm);
+ vk::SourceCollections sourcePrograms (usedVulkanVersion, defaultGlslBuildOptions, defaultGlslBuildOptions, defaultSpirvAsmBuildOptions);
+
+ try
+ {
+ testCase->initPrograms(sourcePrograms);
+ }
+ catch (const tcu::NotSupportedError& )
+ {
+ notSupported++;
+ iterator.next();
+ continue;
+ }
for (vk::GlslSourceCollection::Iterator progIter = sourcePrograms.glslSources.begin();
progIter != sourcePrograms.glslSources.end();
++progIter)
{
- programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName())));
+ // Source program requires higher SPIR-V version than available: skip it to avoid fail
+ if (progIter.getProgram().buildOptions.targetVersion > spirvVersionForGlsl)
+ continue;
+
+ programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName()), progIter.getProgram().buildOptions.targetVersion));
buildGlslTasks.pushBack(BuildGlslTask(progIter.getProgram(), &programs.back()));
executor.submit(&buildGlslTasks.back());
}
progIter != sourcePrograms.spirvAsmSources.end();
++progIter)
{
- programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName())));
+ // Source program requires higher SPIR-V version than available: skip it to avoid fail
+ if (progIter.getProgram().buildOptions.targetVersion > spirvVersionForAsm)
+ continue;
+
+ programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName()), progIter.getProgram().buildOptions.targetVersion));
buildSpirvAsmTasks.pushBack(BuildSpirVAsmTask(progIter.getProgram(), &programs.back()));
executor.submit(&buildSpirvAsmTasks.back());
}
{
BuildStats stats;
-
+ stats.notSupported = notSupported;
for (de::PoolArray<Program>::iterator progIter = programs.begin(); progIter != programs.end(); ++progIter)
{
const bool buildOk = progIter->buildStatus == Program::STATUS_PASSED;
namespace opt
{
-DE_DECLARE_COMMAND_LINE_OPT(DstPath, std::string);
-DE_DECLARE_COMMAND_LINE_OPT(Cases, std::string);
-DE_DECLARE_COMMAND_LINE_OPT(Validate, bool);
-
-} // opt
+DE_DECLARE_COMMAND_LINE_OPT(DstPath, std::string);
+DE_DECLARE_COMMAND_LINE_OPT(Cases, std::string);
+DE_DECLARE_COMMAND_LINE_OPT(Validate, bool);
+DE_DECLARE_COMMAND_LINE_OPT(VulkanVersion, deUint32);
void registerOptions (de::cmdline::Parser& parser)
{
using de::cmdline::Option;
+ using de::cmdline::NamedValue;
+
+ static const NamedValue<deUint32> s_vulkanVersion[] =
+ {
+ { "1.0", VK_MAKE_VERSION(1, 0, 0) },
+ { "1.1", VK_MAKE_VERSION(1, 1, 0) },
+ };
- parser << Option<opt::DstPath> ("d", "dst-path", "Destination path", "out")
- << Option<opt::Cases> ("n", "deqp-case", "Case path filter (works as in test binaries)")
- << Option<opt::Validate> ("v", "validate-spv", "Validate generated SPIR-V binaries");
+ DE_STATIC_ASSERT(vk::SPIRV_VERSION_1_3 + 1 == vk::SPIRV_VERSION_LAST);
+
+ parser << Option<opt::DstPath> ("d", "dst-path", "Destination path", "out")
+ << Option<opt::Cases> ("n", "deqp-case", "Case path filter (works as in test binaries)")
+ << Option<opt::Validate> ("v", "validate-spv", "Validate generated SPIR-V binaries")
+ << Option<opt::VulkanVersion> ("t", "target-vulkan-version", "Target Vulkan version", s_vulkanVersion, "1.1");
}
+} // opt
+
int main (int argc, const char* argv[])
{
de::cmdline::CommandLine cmdLine;
{
de::cmdline::Parser parser;
- registerOptions(parser);
+ opt::registerOptions(parser);
if (!parser.parse(argc, argv, &cmdLine, std::cerr))
{
parser.help(std::cout);
try
{
- tcu::DirArchive archive (".");
- tcu::TestLog log (deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
+ tcu::DirArchive archive (".");
+ tcu::TestLog log (deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
tcu::Platform platform;
- tcu::TestContext testCtx (platform, archive, log, deqpCmdLine, DE_NULL);
-
- const vkt::BuildStats stats = vkt::buildPrograms(testCtx,
- cmdLine.getOption<opt::DstPath>(),
- cmdLine.getOption<opt::Validate>());
-
- tcu::print("DONE: %d passed, %d failed\n", stats.numSucceeded, stats.numFailed);
+ tcu::TestContext testCtx (platform, archive, log, deqpCmdLine, DE_NULL);
+ vk::SpirvVersion spirvVersionForGlsl = vk::getSpirvVersionForGlsl(cmdLine.getOption<opt::VulkanVersion>());
+ vk::SpirvVersion spirvVersionForAsm = vk::getSpirvVersionForAsm(cmdLine.getOption<opt::VulkanVersion>());
+
+ tcu::print("SPIR-V versions: for GLSL sources: %s, for SPIR-V asm sources: %s\n",
+ getSpirvVersionName(spirvVersionForGlsl).c_str(),
+ getSpirvVersionName(spirvVersionForAsm).c_str());
+
+ const vkt::BuildStats stats = vkt::buildPrograms(testCtx,
+ cmdLine.getOption<opt::DstPath>(),
+ cmdLine.getOption<opt::Validate>(),
+ cmdLine.getOption<opt::VulkanVersion>(),
+ spirvVersionForGlsl,
+ spirvVersionForAsm);
+
+ tcu::print("DONE: %d passed, %d failed, %d not supported\n", stats.numSucceeded, stats.numFailed, stats.notSupported);
return stats.numFailed == 0 ? 0 : -1;
}
// Context
-Context::Context (tcu::TestContext& testCtx,
- const vk::PlatformInterface& platformInterface,
- vk::ProgramCollection<vk::ProgramBinary>& progCollection)
+Context::Context (tcu::TestContext& testCtx,
+ const vk::PlatformInterface& platformInterface,
+ vk::BinaryCollection& progCollection)
: m_testCtx (testCtx)
, m_platformInterface (platformInterface)
, m_progCollection (progCollection)
#include "tcuTestCase.hpp"
#include "vkDefs.hpp"
#include "deUniquePtr.hpp"
+#include "vkPrograms.hpp"
namespace glu
{
namespace vk
{
class PlatformInterface;
-class ProgramBinary;
-template<typename Program> class ProgramCollection;
class Allocator;
struct SourceCollections;
}
class Context
{
public:
- Context (tcu::TestContext& testCtx,
- const vk::PlatformInterface& platformInterface,
- vk::ProgramCollection<vk::ProgramBinary>& progCollection);
+ Context (tcu::TestContext& testCtx,
+ const vk::PlatformInterface& platformInterface,
+ vk::BinaryCollection& progCollection);
~Context (void);
tcu::TestContext& getTestContext (void) const { return m_testCtx; }
const vk::PlatformInterface& getPlatformInterface (void) const { return m_platformInterface; }
- vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection (void) const { return m_progCollection; }
+ vk::BinaryCollection& getBinaryCollection (void) const { return m_progCollection; }
// Default instance & device, selected with --deqp-vk-device-id=N
deUint32 getInstanceVersion (void) const;
protected:
tcu::TestContext& m_testCtx;
const vk::PlatformInterface& m_platformInterface;
- vk::ProgramCollection<vk::ProgramBinary>& m_progCollection;
+ vk::BinaryCollection& m_progCollection;
const de::UniquePtr<DefaultDevice> m_device;
const de::UniquePtr<vk::Allocator> m_allocator;
#include "vkShaderToSpirV.hpp"
#include "vkDebugReportUtil.hpp"
#include "vkQueryUtil.hpp"
+#include "vkApiVersion.hpp"
#include "deUniquePtr.hpp"
void TestCaseExecutor::init (tcu::TestCase* testCase, const std::string& casePath)
{
- const TestCase* vktCase = dynamic_cast<TestCase*>(testCase);
- tcu::TestLog& log = m_context.getTestContext().getLog();
- vk::SourceCollections sourceProgs;
+ const TestCase* vktCase = dynamic_cast<TestCase*>(testCase);
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const deUint32 usedVulkanVersion = m_context.getUsedApiVersion();
+ const vk::SpirvVersion spirvVersionForGlsl = vk::getSpirvVersionForGlsl(usedVulkanVersion);
+ const vk::SpirvVersion spirvVersionForAsm = vk::getSpirvVersionForAsm(usedVulkanVersion);
+ vk::ShaderBuildOptions defaultGlslBuildOptions (spirvVersionForGlsl, 0u);
+ vk::ShaderBuildOptions defaultHlslBuildOptions (spirvVersionForGlsl, 0u);
+ vk::SpirVAsmBuildOptions defaultSpirvAsmBuildOptions (spirvVersionForAsm);
+ vk::SourceCollections sourceProgs (usedVulkanVersion, defaultGlslBuildOptions, defaultHlslBuildOptions, defaultSpirvAsmBuildOptions);
DE_UNREF(casePath); // \todo [2015-03-13 pyry] Use this to identify ProgramCollection storage path
for (vk::GlslSourceCollection::Iterator progIter = sourceProgs.glslSources.begin(); progIter != sourceProgs.glslSources.end(); ++progIter)
{
+ if (progIter.getProgram().buildOptions.targetVersion > vk::getSpirvVersionForGlsl(m_context.getUsedApiVersion()))
+ TCU_THROW(NotSupportedError, "Shader requires SPIR-V higher than available");
+
const vk::ProgramBinary* const binProg = buildProgram<glu::ShaderProgramInfo, vk::GlslSourceCollection::Iterator>(casePath, progIter, m_prebuiltBinRegistry, log, &m_progCollection);
try
{
std::ostringstream disasm;
- vk::disassembleProgram(*binProg, &disasm);
+ vk::disassembleProgram(*binProg, &disasm, spirvVersionForGlsl);
log << vk::SpirVAsmSource(disasm.str());
}
for (vk::HlslSourceCollection::Iterator progIter = sourceProgs.hlslSources.begin(); progIter != sourceProgs.hlslSources.end(); ++progIter)
{
+ if (progIter.getProgram().buildOptions.targetVersion > vk::getSpirvVersionForGlsl(m_context.getUsedApiVersion()))
+ TCU_THROW(NotSupportedError, "Shader requires SPIR-V higher than available");
+
const vk::ProgramBinary* const binProg = buildProgram<glu::ShaderProgramInfo, vk::HlslSourceCollection::Iterator>(casePath, progIter, m_prebuiltBinRegistry, log, &m_progCollection);
try
{
std::ostringstream disasm;
- vk::disassembleProgram(*binProg, &disasm);
+ vk::disassembleProgram(*binProg, &disasm, spirvVersionForGlsl);
log << vk::SpirVAsmSource(disasm.str());
}
for (vk::SpirVAsmCollection::Iterator asmIterator = sourceProgs.spirvAsmSources.begin(); asmIterator != sourceProgs.spirvAsmSources.end(); ++asmIterator)
{
+ if (asmIterator.getProgram().buildOptions.targetVersion > vk::getSpirvVersionForAsm(m_context.getUsedApiVersion()))
+ TCU_THROW(NotSupportedError, "Shader requires SPIR-V higher than available");
+
buildProgram<vk::SpirVProgramInfo, vk::SpirVAsmCollection::Iterator>(casePath, asmIterator, m_prebuiltBinRegistry, log, &m_progCollection);
}
dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.multiple_arbitrary_descriptors.offset_view_nonzero
dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_zero
dEQP-VK.binding_model.shader_access.secondary_cmd_buf.with_push_template.storage_buffer.vertex_fragment.descriptor_array.offset_view_nonzero
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_0_compute
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_1_compute
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_2_compute
+dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_3_compute
dEQP-VK.spirv_assembly.instruction.compute.opnop.literal_localsize
dEQP-VK.spirv_assembly.instruction.compute.opnop.literal_and_specid_localsize
dEQP-VK.spirv_assembly.instruction.compute.opnop.specid_localsize
dEQP-VK.spirv_assembly.instruction.compute.opatomic_storage_buffer.store
dEQP-VK.spirv_assembly.instruction.compute.opatomic_storage_buffer.compex
dEQP-VK.spirv_assembly.instruction.compute.opline.all
+dEQP-VK.spirv_assembly.instruction.compute.opmoduleprocessed.all
dEQP-VK.spirv_assembly.instruction.compute.opnoline.all
dEQP-VK.spirv_assembly.instruction.compute.opconstantnull.bool
dEQP-VK.spirv_assembly.instruction.compute.opconstantnull.sint32
dEQP-VK.spirv_assembly.instruction.compute.loop_control.unroll
dEQP-VK.spirv_assembly.instruction.compute.loop_control.dont_unroll
dEQP-VK.spirv_assembly.instruction.compute.loop_control.unroll_dont_unroll
+dEQP-VK.spirv_assembly.instruction.compute.loop_control.dependency_length
+dEQP-VK.spirv_assembly.instruction.compute.loop_control.dependency_infinite
dEQP-VK.spirv_assembly.instruction.compute.function_control.none
dEQP-VK.spirv_assembly.instruction.compute.function_control.inline
dEQP-VK.spirv_assembly.instruction.compute.function_control.dont_inline
dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compute.opptraccesschain_float_single_buffer_first_input
dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opvariable_initialized_null
dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opselect_null_or_valid_ptr
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_0_fragment
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_1_fragment
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_2_fragment
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_vertex
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_tesselation_evaluation
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_tesselation_control
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_geometry
+dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_3_fragment
dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_vert
dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_tessc
dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_tesse
dEQP-VK.spirv_assembly.instruction.graphics.opsourcecontinued.long_tesse
dEQP-VK.spirv_assembly.instruction.graphics.opsourcecontinued.long_geom
dEQP-VK.spirv_assembly.instruction.graphics.opsourcecontinued.long_frag
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_vert
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_geom
+dEQP-VK.spirv_assembly.instruction.graphics.opmoduleprocessed.opmoduleprocessed_frag
dEQP-VK.spirv_assembly.instruction.graphics.opline.opline_empty_name_vert
dEQP-VK.spirv_assembly.instruction.graphics.opline.opline_empty_name_tessc
dEQP-VK.spirv_assembly.instruction.graphics.opline.opline_empty_name_tesse
DEFAULT_BUILD_DIR = os.path.join(tempfile.gettempdir(), "spirv-binaries", "{targetName}-{buildType}")
DEFAULT_TARGET = "null"
DEFAULT_DST_DIR = os.path.join(DEQP_DIR, "external", "vulkancts", "data", "vulkan", "prebuilt")
+DEFAULT_VULKAN_VERSION = "1.1"
def getBuildConfig (buildPathPtrn, targetName, buildType):
buildPath = buildPathPtrn.format(
print "Removing %s" % os.path.join(dstPath, binFile)
os.remove(os.path.join(dstPath, binFile))
-def execBuildPrograms (buildCfg, generator, module, dstPath):
+def execBuildPrograms (buildCfg, generator, module, dstPath, vulkanVersion):
fullDstPath = os.path.realpath(dstPath)
workDir = os.path.join(buildCfg.getBuildDir(), "modules", module.dirName)
try:
binPath = generator.getBinaryPath(buildCfg.getBuildType(), os.path.join(".", "vk-build-programs"))
- execute([binPath, "--validate-spv", "--dst-path", fullDstPath])
+ execute([binPath, "--validate-spv", "--dst-path", fullDstPath, "--target-vulkan-version", vulkanVersion])
finally:
popWorkingDir()
dest="dstPath",
default=DEFAULT_DST_DIR,
help="Destination path")
+ parser.add_argument("-u",
+ "--target-vulkan-version",
+ dest="vulkanVersion",
+ default=DEFAULT_VULKAN_VERSION,
+ help="Target Vulkan version")
return parser.parse_args()
if __name__ == "__main__":
if not os.path.exists(args.dstPath):
os.makedirs(args.dstPath)
- execBuildPrograms(buildCfg, generator, module, args.dstPath)
+ execBuildPrograms(buildCfg, generator, module, args.dstPath, args.vulkanVersion)