blob: df948b4655534d483617f97b2026e3b8e3df67b9 [file] [log] [blame]
#ifndef _VKRESOURCEINTERFACE_HPP
#define _VKRESOURCEINTERFACE_HPP
/*-------------------------------------------------------------------------
* Vulkan CTS Framework
* --------------------
*
* Copyright (c) 2021 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 Defines class for handling resources ( programs, pipelines, files, etc. )
*//*--------------------------------------------------------------------*/
#include "vkDefs.hpp"
#include "tcuTestLog.hpp"
#include "tcuTestContext.hpp"
#include "vkPrograms.hpp"
#include "vkBinaryRegistry.hpp"
#include "deSharedPtr.hpp"
#include "deDefs.hpp"
#include <map>
#ifdef CTS_USES_VULKANSC
#include "vksClient.hpp"
#include "tcuMaybe.hpp"
// #include "vksStructsVKSC.hpp"
#endif // CTS_USES_VULKANSC
namespace vk
{
class ResourceInterface
{
public:
ResourceInterface(tcu::TestContext &testCtx);
virtual ~ResourceInterface();
virtual void initDevice(DeviceInterface &deviceInterface, VkDevice device) = 0;
// use deinitDevice when your DeviceDriverSC is created and removed inside TestInstance
virtual void deinitDevice(VkDevice device) = 0;
virtual void initTestCase(const std::string &casePath);
const std::string &getCasePath() const;
// buildProgram
template <typename InfoType, typename IteratorType>
vk::ProgramBinary *buildProgram(const std::string &casePath, IteratorType iter,
const vk::BinaryRegistryReader &prebuiltBinRegistry,
vk::BinaryCollection *progCollection);
#ifdef CTS_USES_VULKANSC
void initApiVersion(const uint32_t version);
bool isVulkanSC(void) const;
template <typename VkObject>
VkObject incResourceCounter() const
{
uint64_t value = ++m_resourceCounter;
return VkObject(reinterpret_cast<void *>(value));
}
std::mutex &getStatMutex();
VkDeviceObjectReservationCreateInfo &getStatCurrent();
VkDeviceObjectReservationCreateInfo &getStatMax();
const VkDeviceObjectReservationCreateInfo &getStatMax() const;
void setHandleDestroy(bool value);
bool isEnabledHandleDestroy() const;
virtual void registerDeviceFeatures(VkDevice device, const VkDeviceCreateInfo *pCreateInfo) const = 0;
virtual void unregisterDeviceFeatures(VkDevice device) const = 0;
virtual VkResult createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
bool normalMode) const = 0;
virtual VkResult createGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
bool normalMode) const = 0;
virtual VkResult createComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
const VkComputePipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
bool normalMode) const = 0;
virtual void destroyPipeline(VkDevice device, VkPipeline pipeline,
const VkAllocationCallbacks *pAllocator) const = 0;
virtual void createRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const = 0;
virtual void createRenderPass2(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const = 0;
virtual void createPipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineLayout *pPipelineLayout) const = 0;
virtual void createDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorSetLayout *pSetLayout) const = 0;
virtual void createSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) const = 0;
virtual void createSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSamplerYcbcrConversion *pYcbcrConversion) const = 0;
virtual void createCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) const = 0;
virtual void allocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
VkCommandBuffer *pCommandBuffers) const = 0;
virtual void increaseCommandBufferSize(VkCommandBuffer commandBuffer, VkDeviceSize commandSize) const = 0;
virtual void resetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) const = 0;
void removeRedundantObjects();
void finalizeCommandBuffers();
std::vector<uint8_t> exportData() const;
void importData(std::vector<uint8_t> &importText) const;
virtual void importPipelineCacheData(const PlatformInterface &vkp, VkInstance instance,
const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
uint32_t queueIndex) = 0;
void registerObjectHash(uint64_t handle, std::size_t hashValue) const;
const std::map<uint64_t, std::size_t> &getObjectHashes() const;
void preparePipelinePoolSizes();
std::vector<VkPipelinePoolSize> getPipelinePoolSizes() const;
void fillPoolEntrySize(vk::VkPipelineOfflineCreateInfo &pipelineIdentifier) const;
vksc_server::VulkanCommandMemoryConsumption getNextCommandPoolSize();
std::size_t getCacheDataSize() const;
const uint8_t *getCacheData() const;
VkPipelineCache getPipelineCache(VkDevice device) const;
virtual void resetObjects() = 0;
virtual void resetPipelineCaches() = 0;
#endif // CTS_USES_VULKANSC
protected:
virtual vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::GlslSource &source,
glu::ShaderProgramInfo *buildInfo,
const tcu::CommandLine &commandLine) = 0;
virtual vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::HlslSource &source,
glu::ShaderProgramInfo *buildInfo,
const tcu::CommandLine &commandLine) = 0;
virtual vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::SpirVAsmSource &source,
vk::SpirVProgramInfo *buildInfo, const tcu::CommandLine &commandLine) = 0;
tcu::TestContext &m_testCtx;
std::string m_currentTestPath;
#ifdef CTS_USES_VULKANSC
mutable vksc_server::VulkanPipelineCacheInput m_pipelineInput;
mutable std::map<uint64_t, std::size_t> m_objectHashes;
mutable std::vector<vksc_server::VulkanCommandMemoryConsumption> m_commandPoolMemoryConsumption;
mutable uint32_t m_commandPoolIndex;
mutable std::map<VkCommandBuffer, vksc_server::VulkanCommandMemoryConsumption> m_commandBufferMemoryConsumption;
mutable std::map<VkDevice, std::string> m_deviceFeatures;
mutable std::map<VkDevice, std::vector<std::string>> m_deviceExtensions;
std::map<VkDevice, de::SharedPtr<Move<VkPipelineCache>>> m_pipelineCache;
mutable std::mutex m_mutex;
mutable uint64_t m_resourceCounter;
mutable VkDeviceObjectReservationCreateInfo m_statCurrent;
mutable VkDeviceObjectReservationCreateInfo m_statMax;
std::vector<uint8_t> m_cacheData;
mutable std::map<VkPipeline, VkPipelineOfflineCreateInfo> m_pipelineIdentifiers;
mutable std::vector<vksc_server::VulkanPipelineSize> m_pipelineSizes;
std::vector<VkPipelinePoolSize> m_pipelinePoolSizes;
tcu::Maybe<uint32_t> m_version;
tcu::Maybe<bool> m_vulkanSC;
bool m_enabledHandleDestroy;
#endif // CTS_USES_VULKANSC
};
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateSamplerYcbcrConversionFunc)(
VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
VkSamplerYcbcrConversion *pYcbcrConversion);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroySamplerYcbcrConversionFunc)(VkDevice device,
VkSamplerYcbcrConversion ycbcrConversion,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateSamplerFunc)(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSampler *pSampler);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroySamplerFunc)(VkDevice device, VkSampler sampler,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateShaderModuleFunc)(VkDevice device,
const VkShaderModuleCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkShaderModule *pShaderModule);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroyShaderModuleFunc)(VkDevice device, VkShaderModule shaderModule,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateRenderPassFunc)(VkDevice device,
const VkRenderPassCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateRenderPass2Func)(VkDevice device,
const VkRenderPassCreateInfo2 *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroyRenderPassFunc)(VkDevice device, VkRenderPass renderPass,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateDescriptorSetLayoutFunc)(
VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
VkDescriptorSetLayout *pSetLayout);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroyDescriptorSetLayoutFunc)(VkDevice device,
VkDescriptorSetLayout descriptorSetLayout,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreatePipelineLayoutFunc)(VkDevice device,
const VkPipelineLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineLayout *pPipelineLayout);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroyPipelineLayoutFunc)(VkDevice device, VkPipelineLayout pipelineLayout,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateGraphicsPipelinesFunc)(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateComputePipelinesFunc)(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkComputePipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroyPipelineFunc)(VkDevice device, VkPipeline pipeline,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreatePipelineCacheFunc)(VkDevice device,
const VkPipelineCacheCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineCache *pPipelineCache);
typedef VKAPI_ATTR void(VKAPI_CALL *DestroyPipelineCacheFunc)(VkDevice device, VkPipelineCache pipelineCache,
const VkAllocationCallbacks *pAllocator);
typedef VKAPI_ATTR VkResult(VKAPI_CALL *GetPipelineCacheDataFunc)(VkDevice device, VkPipelineCache pipelineCache,
uintptr_t *pDataSize, void *pData);
#ifdef CTS_USES_VULKANSC
typedef VKAPI_ATTR void(VKAPI_CALL *GetCommandPoolMemoryConsumptionFunc)(VkDevice device, VkCommandPool commandPool,
VkCommandBuffer commandBuffer,
VkCommandPoolMemoryConsumption *pConsumption);
#endif // CTS_USES_VULKANSC
class ResourceInterfaceStandard : public ResourceInterface
{
public:
ResourceInterfaceStandard(tcu::TestContext &testCtx);
void initDevice(DeviceInterface &deviceInterface, VkDevice device) override;
void deinitDevice(VkDevice device) override;
#ifdef CTS_USES_VULKANSC
void registerDeviceFeatures(VkDevice device, const VkDeviceCreateInfo *pCreateInfo) const override;
void unregisterDeviceFeatures(VkDevice device) const override;
VkResult createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
bool normalMode) const override;
VkResult createGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
bool normalMode) const override;
VkResult createComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
const VkComputePipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
bool normalMode) const override;
void destroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) const override;
void createRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const override;
void createRenderPass2(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const override;
void createPipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineLayout *pPipelineLayout) const override;
void createDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorSetLayout *pSetLayout) const override;
void createSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
VkSampler *pSampler) const override;
void createSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSamplerYcbcrConversion *pYcbcrConversion) const override;
void createCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) const override;
void allocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
VkCommandBuffer *pCommandBuffers) const override;
void increaseCommandBufferSize(VkCommandBuffer commandBuffer, VkDeviceSize commandSize) const override;
void resetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) const override;
void importPipelineCacheData(const PlatformInterface &vkp, VkInstance instance, const InstanceInterface &vki,
VkPhysicalDevice physicalDevice, uint32_t queueIndex) override;
void resetObjects() override;
void resetPipelineCaches() override;
#endif // CTS_USES_VULKANSC
protected:
vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::GlslSource &source,
glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::HlslSource &source,
glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::SpirVAsmSource &source,
vk::SpirVProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
std::map<VkDevice, CreateShaderModuleFunc> m_createShaderModuleFunc;
std::map<VkDevice, CreateGraphicsPipelinesFunc> m_createGraphicsPipelinesFunc;
std::map<VkDevice, CreateComputePipelinesFunc> m_createComputePipelinesFunc;
};
#ifdef CTS_USES_VULKANSC
class ResourceInterfaceVKSC : public ResourceInterfaceStandard
{
public:
ResourceInterfaceVKSC(tcu::TestContext &testCtx);
VkResult createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
bool normalMode) const override;
void importPipelineCacheData(const PlatformInterface &vkp, VkInstance instance, const InstanceInterface &vki,
VkPhysicalDevice physicalDevice, uint32_t queueIndex) override;
protected:
vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::GlslSource &source,
glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::HlslSource &source,
glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::SpirVAsmSource &source,
vk::SpirVProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
private:
vksc_server::Server *getServer();
bool noServer() const;
std::string m_address;
std::shared_ptr<vksc_server::Server> m_server;
};
class MultithreadedDestroyGuard
{
public:
MultithreadedDestroyGuard(de::SharedPtr<vk::ResourceInterface> resourceInterface);
~MultithreadedDestroyGuard();
private:
de::SharedPtr<vk::ResourceInterface> m_resourceInterface;
};
#endif // CTS_USES_VULKANSC
template <typename InfoType, typename IteratorType>
vk::ProgramBinary *ResourceInterface::buildProgram(const std::string &casePath, IteratorType iter,
const vk::BinaryRegistryReader &prebuiltBinRegistry,
vk::BinaryCollection *progCollection)
{
const vk::ProgramIdentifier progId(casePath, iter.getName());
tcu::TestLog &log = m_testCtx.getLog();
const tcu::CommandLine &commandLine = m_testCtx.getCommandLine();
const tcu::ScopedLogSection progSection(log, iter.getName(), "Program: " + iter.getName());
de::MovePtr<vk::ProgramBinary> binProg;
InfoType buildInfo;
try
{
binProg = de::MovePtr<vk::ProgramBinary>(compileProgram(progId, iter.getProgram(), &buildInfo, commandLine));
log << buildInfo;
}
catch (const tcu::NotSupportedError &err)
{
// Try to load from cache
log << err << tcu::TestLog::Message << "Building from source not supported, loading stored binary instead"
<< tcu::TestLog::EndMessage;
binProg = de::MovePtr<vk::ProgramBinary>(prebuiltBinRegistry.loadProgram(progId));
log << iter.getProgram();
}
catch (const tcu::Exception &)
{
// Build failed for other reason
log << buildInfo;
throw;
}
TCU_CHECK_INTERNAL(binProg);
{
vk::ProgramBinary *const returnBinary = binProg.get();
progCollection->add(progId.programName, binProg);
return returnBinary;
}
}
} // namespace vk
#endif // _VKRESOURCEINTERFACE_HPP