blob: e3e25fae534edcaba6cfa186ba9eaf697a171310 [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan CTS Framework
* --------------------
*
* Copyright (c) 2015 Google 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 Vulkan platform abstraction.
*//*--------------------------------------------------------------------*/
#include "vkPlatform.hpp"
#include "tcuFunctionLibrary.hpp"
#ifdef CTS_USES_VULKANSC
#include "vkQueryUtil.hpp"
#include "vkSafetyCriticalUtil.hpp"
#endif // CTS_USES_VULKANSC
namespace vk
{
PlatformDriver::PlatformDriver(const tcu::FunctionLibrary &library)
{
m_vk.getInstanceProcAddr = (GetInstanceProcAddrFunc)library.getFunction("vkGetInstanceProcAddr");
#define GET_PROC_ADDR(NAME) m_vk.getInstanceProcAddr(DE_NULL, NAME)
#include "vkInitPlatformFunctionPointers.inl"
#undef GET_PROC_ADDR
}
PlatformDriver::~PlatformDriver(void)
{
}
InstanceDriver::InstanceDriver(const PlatformInterface &platformInterface, VkInstance instance)
{
loadFunctions(platformInterface, instance);
}
void InstanceDriver::loadFunctions(const PlatformInterface &platformInterface, VkInstance instance){
#define GET_PROC_ADDR(NAME) platformInterface.getInstanceProcAddr(instance, NAME)
#include "vkInitInstanceFunctionPointers.inl"
#undef GET_PROC_ADDR
}
InstanceDriver::~InstanceDriver(void)
{
}
#ifdef CTS_USES_VULKANSC
InstanceDriverSC::InstanceDriverSC(const PlatformInterface &platformInterface, VkInstance instance,
const tcu::CommandLine &cmdLine,
de::SharedPtr<vk::ResourceInterface> resourceInterface)
: InstanceDriver(platformInterface, instance)
, m_normalMode(cmdLine.isSubProcess())
, m_resourceInterface(resourceInterface)
{
}
std::pair<void **, void *> prepareDeviceGroupPatch(const VkDeviceCreateInfo *pCreateInfo)
{
struct StructureBase
{
VkStructureType sType;
const StructureBase *pNext;
};
const StructureBase *prev = DE_NULL;
const StructureBase *curr = reinterpret_cast<const StructureBase *>(pCreateInfo);
while (curr)
{
if (curr->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO)
{
if (prev != DE_NULL)
return std::pair<void **, void *>((void **)&prev->pNext, (void *)curr);
}
prev = curr;
curr = reinterpret_cast<const StructureBase *>(curr->pNext);
}
return std::pair<void **, void *>(DE_NULL, DE_NULL);
}
VkResult InstanceDriverSC::createDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) const
{
std::pair<void *, void *> patch = prepareDeviceGroupPatch(pCreateInfo);
const bool patchNeeded = patch.first != DE_NULL;
// Structure restored from JSON does not contain valid physicalDevice.
// Workaround: set to delivered physicalDevice argument.
if (patchNeeded && m_normalMode)
{
VkDeviceGroupDeviceCreateInfo *p = (VkDeviceGroupDeviceCreateInfo *)patch.second;
DE_ASSERT(p->physicalDeviceCount == 1);
if (p->physicalDeviceCount == 1 && p->pPhysicalDevices[0] == DE_NULL)
{
VkPhysicalDevice *v = const_cast<VkPhysicalDevice *>(p->pPhysicalDevices);
v[0] = physicalDevice;
}
}
VkResult result = InstanceDriver::createDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
// Vulkan loader destroys pNext value when VkDeviceGroupDeviceCreateInfo is present in the chain.
// Workaround: Set pNext value to VkDeviceGroupDeviceCreateInfo structure back.
if (patchNeeded)
{
void **addr = (void **)patch.first;
*addr = patch.second;
}
if (result == VK_SUCCESS && !m_normalMode)
{
m_resourceInterface->registerDeviceFeatures(*pDevice, pCreateInfo);
}
return result;
}
#endif // CTS_USES_VULKANSC
DeviceDriver::DeviceDriver(const PlatformInterface &platformInterface, VkInstance instance, VkDevice device)
{
m_vk.getDeviceProcAddr =
(GetDeviceProcAddrFunc)platformInterface.getInstanceProcAddr(instance, "vkGetDeviceProcAddr");
#define GET_PROC_ADDR(NAME) m_vk.getDeviceProcAddr(device, NAME)
#include "vkInitDeviceFunctionPointers.inl"
#undef GET_PROC_ADDR
}
DeviceDriver::~DeviceDriver(void)
{
}
#ifdef CTS_USES_VULKANSC
VkResult DeviceDriver::createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) const
{
// this should not be called - Vulkan SC implementation uses DeviceDriverSC instead
DE_UNREF(device);
DE_UNREF(pCreateInfo);
DE_UNREF(pAllocator);
DE_UNREF(pShaderModule);
TCU_THROW(InternalError, "Wrong DeviceDriver called in VulkanSC");
}
#endif
#ifdef CTS_USES_VULKANSC
DeviceDriverSC::DeviceDriverSC(const PlatformInterface &platformInterface, VkInstance instance, VkDevice device,
const tcu::CommandLine &cmdLine, de::SharedPtr<vk::ResourceInterface> resourceInterface,
const VkPhysicalDeviceVulkanSC10Properties &physicalDeviceVulkanSC10Properties)
: DeviceDriver(platformInterface, instance, device)
, m_normalMode(cmdLine.isSubProcess())
, m_resourceInterface(resourceInterface)
, m_physicalDeviceVulkanSC10Properties(physicalDeviceVulkanSC10Properties)
, m_commandDefaultSize((VkDeviceSize)cmdLine.getCommandDefaultSize())
, m_commandBufferMinimumSize(
de::max((VkDeviceSize)cmdLine.getCommandDefaultSize(), (VkDeviceSize)cmdLine.getCommandBufferMinSize()))
, m_commandPoolMinimumSize((VkDeviceSize)cmdLine.getCommandPoolMinSize())
{
if (!cmdLine.isSubProcess())
m_falseMemory.resize(64u * 1024u * 1024u, 0u);
m_resourceInterface->initDevice(*this, device);
}
DeviceDriverSC::~DeviceDriverSC(void)
{
}
void DeviceDriverSC::destroyDeviceHandler(VkDevice device, const VkAllocationCallbacks *pAllocator) const
{
DE_UNREF(pAllocator);
m_resourceInterface->unregisterDeviceFeatures(device);
}
VkResult DeviceDriverSC::createDescriptorSetLayoutHandlerNorm(VkDevice device,
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorSetLayout *pSetLayout) const
{
DDSTAT_LOCK();
VkResult result = m_vk.createDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
m_resourceInterface->registerObjectHash(
pSetLayout->getInternal(),
calculateDescriptorSetLayoutHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
return result;
}
void DeviceDriverSC::createDescriptorSetLayoutHandlerStat(VkDevice device,
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorSetLayout *pSetLayout) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(descriptorSetLayoutRequestCount, 1);
DDSTAT_HANDLE_CREATE(descriptorSetLayoutBindingRequestCount, pCreateInfo->bindingCount);
uint32_t immutableSamplersCount = 0u;
for (uint32_t i = 0; i < pCreateInfo->bindingCount; ++i)
{
m_resourceInterface->getStatMax().descriptorSetLayoutBindingLimit = de::max(
m_resourceInterface->getStatMax().descriptorSetLayoutBindingLimit, pCreateInfo->pBindings[i].binding + 1);
if ((pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
pCreateInfo->pBindings[i].pImmutableSamplers != DE_NULL)
immutableSamplersCount += pCreateInfo->pBindings[i].descriptorCount;
}
m_resourceInterface->getStatMax().maxImmutableSamplersPerDescriptorSetLayout =
de::max(m_resourceInterface->getStatMax().maxImmutableSamplersPerDescriptorSetLayout, immutableSamplersCount);
*pSetLayout = VkDescriptorSetLayout(m_resourceInterface->incResourceCounter());
m_descriptorSetLayouts.insert({*pSetLayout, *pCreateInfo});
m_resourceInterface->registerObjectHash(
pSetLayout->getInternal(),
calculateDescriptorSetLayoutHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
m_resourceInterface->createDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
}
void DeviceDriverSC::destroyDescriptorSetLayoutHandler(VkDevice device, VkDescriptorSetLayout descriptorSetLayout,
const VkAllocationCallbacks *pAllocator) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
auto it = m_descriptorSetLayouts.find(descriptorSetLayout);
if (it != end(m_descriptorSetLayouts))
{
DDSTAT_HANDLE_DESTROY(descriptorSetLayoutRequestCount, 1);
DDSTAT_HANDLE_DESTROY(descriptorSetLayoutBindingRequestCount, it->second.bindingCount);
m_descriptorSetLayouts.erase(it);
}
}
void DeviceDriverSC::allocateDescriptorSetsHandlerStat(VkDevice device,
const VkDescriptorSetAllocateInfo *pAllocateInfo,
VkDescriptorSet *pDescriptorSets) const
{
DE_UNREF(device);
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(descriptorSetRequestCount, pAllocateInfo->descriptorSetCount);
for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i)
pDescriptorSets[i] = Handle<HANDLE_TYPE_DESCRIPTOR_SET>(m_resourceInterface->incResourceCounter());
for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i)
m_descriptorSetsInPool[pDescriptorSets[i]] = pAllocateInfo->descriptorPool;
}
void DeviceDriverSC::freeDescriptorSetsHandlerStat(VkDevice device, VkDescriptorPool descriptorPool,
uint32_t descriptorSetCount,
const VkDescriptorSet *pDescriptorSets) const
{
DE_UNREF(device);
DE_UNREF(descriptorPool);
DDSTAT_LOCK();
for (uint32_t i = 0; i < descriptorSetCount; ++i)
DDSTAT_HANDLE_DESTROY_IF(pDescriptorSets[i], descriptorSetRequestCount, 1);
for (uint32_t i = 0; i < descriptorSetCount; ++i)
m_descriptorSetsInPool.erase(pDescriptorSets[i]);
}
void DeviceDriverSC::resetDescriptorPoolHandlerStat(VkDevice device, VkDescriptorPool descriptorPool,
VkDescriptorPoolResetFlags flags) const
{
DE_UNREF(device);
DE_UNREF(flags);
DDSTAT_LOCK();
uint32_t removedCount = 0u;
for (auto it = begin(m_descriptorSetsInPool); it != end(m_descriptorSetsInPool);)
{
if (it->second.getInternal() == descriptorPool.getInternal())
{
m_descriptorSetsInPool.erase(it++);
removedCount++;
}
else
++it;
}
DDSTAT_HANDLE_DESTROY(descriptorSetRequestCount, removedCount);
}
void DeviceDriverSC::createImageViewHandler(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkImageView *pView) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(imageViewRequestCount, 1);
if (pCreateInfo->subresourceRange.layerCount > 1)
DDSTAT_HANDLE_CREATE(layeredImageViewRequestCount, 1);
m_resourceInterface->getStatMax().maxImageViewMipLevels =
de::max(m_resourceInterface->getStatMax().maxImageViewMipLevels, pCreateInfo->subresourceRange.levelCount);
m_resourceInterface->getStatMax().maxImageViewArrayLayers =
de::max(m_resourceInterface->getStatMax().maxImageViewArrayLayers, pCreateInfo->subresourceRange.layerCount);
if (pCreateInfo->subresourceRange.layerCount > 1)
m_resourceInterface->getStatMax().maxLayeredImageViewMipLevels = de::max(
m_resourceInterface->getStatMax().maxLayeredImageViewMipLevels, pCreateInfo->subresourceRange.levelCount);
*pView = VkImageView(m_resourceInterface->incResourceCounter());
m_imageViews.insert({*pView, *pCreateInfo});
}
void DeviceDriverSC::destroyImageViewHandler(VkDevice device, VkImageView imageView,
const VkAllocationCallbacks *pAllocator) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
auto it = m_imageViews.find(imageView);
if (it != end(m_imageViews))
{
DDSTAT_HANDLE_DESTROY(imageViewRequestCount, 1);
if (it->second.subresourceRange.layerCount > 1)
DDSTAT_HANDLE_DESTROY(layeredImageViewRequestCount, 1);
m_imageViews.erase(it);
}
}
void DeviceDriverSC::createQueryPoolHandler(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(queryPoolRequestCount, 1);
switch (pCreateInfo->queryType)
{
case VK_QUERY_TYPE_OCCLUSION:
m_resourceInterface->getStatMax().maxOcclusionQueriesPerPool =
de::max(m_resourceInterface->getStatMax().maxOcclusionQueriesPerPool, pCreateInfo->queryCount);
break;
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
m_resourceInterface->getStatMax().maxPipelineStatisticsQueriesPerPool =
de::max(m_resourceInterface->getStatMax().maxPipelineStatisticsQueriesPerPool, pCreateInfo->queryCount);
break;
case VK_QUERY_TYPE_TIMESTAMP:
m_resourceInterface->getStatMax().maxTimestampQueriesPerPool =
de::max(m_resourceInterface->getStatMax().maxTimestampQueriesPerPool, pCreateInfo->queryCount);
break;
default:
break;
}
// We don't have to track queryPool resources as we do with image views because they're not removed from memory in Vulkan SC.
*pQueryPool = VkQueryPool(m_resourceInterface->incResourceCounter());
}
VkResult DeviceDriverSC::createPipelineLayoutHandlerNorm(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineLayout *pPipelineLayout) const
{
DDSTAT_LOCK();
VkResult result = m_vk.createPipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
m_resourceInterface->registerObjectHash(
pPipelineLayout->getInternal(),
calculatePipelineLayoutHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
return result;
}
void DeviceDriverSC::createPipelineLayoutHandlerStat(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineLayout *pPipelineLayout) const
{
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(pipelineLayoutRequestCount, 1);
*pPipelineLayout = VkPipelineLayout(m_resourceInterface->incResourceCounter());
m_resourceInterface->registerObjectHash(
pPipelineLayout->getInternal(),
calculatePipelineLayoutHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
m_resourceInterface->createPipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
}
VkResult DeviceDriverSC::createGraphicsPipelinesHandlerNorm(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines) const
{
DDSTAT_LOCK();
return m_resourceInterface->createGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos,
pAllocator, pPipelines, m_normalMode);
}
void DeviceDriverSC::createGraphicsPipelinesHandlerStat(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines) const
{
DE_UNREF(device);
DE_UNREF(pipelineCache);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(graphicsPipelineRequestCount, createInfoCount);
for (uint32_t i = 0; i < createInfoCount; ++i)
{
pPipelines[i] = VkPipeline(m_resourceInterface->incResourceCounter());
m_graphicsPipelines.insert({pPipelines[i], pCreateInfos[i]});
}
m_resourceInterface->createGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
pPipelines, m_normalMode);
}
VkResult DeviceDriverSC::createComputePipelinesHandlerNorm(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkComputePipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines) const
{
DDSTAT_LOCK();
return m_resourceInterface->createComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
pPipelines, m_normalMode);
}
void DeviceDriverSC::createComputePipelinesHandlerStat(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkComputePipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines) const
{
DE_UNREF(device);
DE_UNREF(pipelineCache);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(computePipelineRequestCount, createInfoCount);
for (uint32_t i = 0; i < createInfoCount; ++i)
{
pPipelines[i] = VkPipeline(m_resourceInterface->incResourceCounter());
m_computePipelines.insert({pPipelines[i], pCreateInfos[i]});
}
m_resourceInterface->createComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
pPipelines, m_normalMode);
}
void DeviceDriverSC::destroyPipelineHandler(VkDevice device, VkPipeline pipeline,
const VkAllocationCallbacks *pAllocator) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
auto it = m_graphicsPipelines.find(pipeline);
if (it != end(m_graphicsPipelines))
{
DDSTAT_HANDLE_DESTROY(graphicsPipelineRequestCount, 1);
m_graphicsPipelines.erase(it);
m_resourceInterface->destroyPipeline(device, pipeline, pAllocator);
return;
}
auto it2 = m_computePipelines.find(pipeline);
if (it2 != end(m_computePipelines))
{
DDSTAT_HANDLE_DESTROY(computePipelineRequestCount, 1);
m_resourceInterface->destroyPipeline(device, pipeline, pAllocator);
m_computePipelines.erase(it2);
}
}
VkResult DeviceDriverSC::createFramebufferHandlerNorm(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkFramebuffer *pFramebuffer) const
{
DDSTAT_LOCK();
checkFramebufferSupport(pCreateInfo);
const VkResult result = m_vk.createFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
return result;
}
void DeviceDriverSC::createFramebufferHandlerStat(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkFramebuffer *pFramebuffer) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
checkFramebufferSupport(pCreateInfo);
DDSTAT_HANDLE_CREATE(framebufferRequestCount, 1);
*pFramebuffer = Handle<HANDLE_TYPE_FRAMEBUFFER>(m_resourceInterface->incResourceCounter());
}
VkResult DeviceDriverSC::createRenderPassHandlerNorm(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass) const
{
DDSTAT_LOCK();
checkRenderPassSupport(pCreateInfo->attachmentCount, pCreateInfo->subpassCount, pCreateInfo->dependencyCount);
for (uint32_t subpassNdx = 0; subpassNdx < pCreateInfo->subpassCount; ++subpassNdx)
checkSubpassSupport(pCreateInfo->pSubpasses[subpassNdx].inputAttachmentCount,
pCreateInfo->pSubpasses[subpassNdx].preserveAttachmentCount);
VkResult result = m_vk.createRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
m_resourceInterface->registerObjectHash(
pRenderPass->getInternal(), calculateRenderPassHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
return result;
}
void DeviceDriverSC::createRenderPassHandlerStat(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
checkRenderPassSupport(pCreateInfo->attachmentCount, pCreateInfo->subpassCount, pCreateInfo->dependencyCount);
for (uint32_t subpassNdx = 0; subpassNdx < pCreateInfo->subpassCount; ++subpassNdx)
checkSubpassSupport(pCreateInfo->pSubpasses[subpassNdx].inputAttachmentCount,
pCreateInfo->pSubpasses[subpassNdx].preserveAttachmentCount);
DDSTAT_HANDLE_CREATE(renderPassRequestCount, 1);
DDSTAT_HANDLE_CREATE(subpassDescriptionRequestCount, pCreateInfo->subpassCount);
DDSTAT_HANDLE_CREATE(attachmentDescriptionRequestCount, pCreateInfo->attachmentCount);
*pRenderPass = VkRenderPass(m_resourceInterface->incResourceCounter());
m_renderPasses.insert({*pRenderPass, *pCreateInfo});
m_resourceInterface->registerObjectHash(
pRenderPass->getInternal(), calculateRenderPassHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
m_resourceInterface->createRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
}
VkResult DeviceDriverSC::createRenderPass2HandlerNorm(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass) const
{
DDSTAT_LOCK();
checkRenderPassSupport(pCreateInfo->attachmentCount, pCreateInfo->subpassCount, pCreateInfo->dependencyCount);
for (uint32_t subpassNdx = 0; subpassNdx < pCreateInfo->subpassCount; ++subpassNdx)
checkSubpassSupport(pCreateInfo->pSubpasses[subpassNdx].inputAttachmentCount,
pCreateInfo->pSubpasses[subpassNdx].preserveAttachmentCount);
VkResult result = m_vk.createRenderPass2(device, pCreateInfo, pAllocator, pRenderPass);
m_resourceInterface->registerObjectHash(
pRenderPass->getInternal(), calculateRenderPass2Hash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
return result;
}
void DeviceDriverSC::createRenderPass2HandlerStat(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
checkRenderPassSupport(pCreateInfo->attachmentCount, pCreateInfo->subpassCount, pCreateInfo->dependencyCount);
for (uint32_t subpassNdx = 0; subpassNdx < pCreateInfo->subpassCount; ++subpassNdx)
checkSubpassSupport(pCreateInfo->pSubpasses[subpassNdx].inputAttachmentCount,
pCreateInfo->pSubpasses[subpassNdx].preserveAttachmentCount);
DDSTAT_HANDLE_CREATE(renderPassRequestCount, 1);
DDSTAT_HANDLE_CREATE(subpassDescriptionRequestCount, pCreateInfo->subpassCount);
DDSTAT_HANDLE_CREATE(attachmentDescriptionRequestCount, pCreateInfo->attachmentCount);
*pRenderPass = VkRenderPass(m_resourceInterface->incResourceCounter());
m_renderPasses2.insert({*pRenderPass, *pCreateInfo});
m_resourceInterface->registerObjectHash(
pRenderPass->getInternal(), calculateRenderPass2Hash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
m_resourceInterface->createRenderPass2(device, pCreateInfo, pAllocator, pRenderPass);
}
void DeviceDriverSC::destroyRenderPassHandler(VkDevice device, VkRenderPass renderPass,
const VkAllocationCallbacks *pAllocator) const
{
DE_UNREF(device);
DE_UNREF(pAllocator);
DDSTAT_LOCK();
auto it = m_renderPasses.find(renderPass);
if (it != end(m_renderPasses))
{
DDSTAT_HANDLE_DESTROY(renderPassRequestCount, 1);
DDSTAT_HANDLE_DESTROY(subpassDescriptionRequestCount, it->second.subpassCount);
DDSTAT_HANDLE_DESTROY(attachmentDescriptionRequestCount, it->second.attachmentCount);
m_renderPasses.erase(it);
return;
}
auto it2 = m_renderPasses2.find(renderPass);
if (it2 != end(m_renderPasses2))
{
DDSTAT_HANDLE_DESTROY(renderPassRequestCount, 1);
DDSTAT_HANDLE_DESTROY(subpassDescriptionRequestCount, it2->second.subpassCount);
DDSTAT_HANDLE_DESTROY(attachmentDescriptionRequestCount, it2->second.attachmentCount);
m_renderPasses2.erase(it2);
}
}
VkResult DeviceDriverSC::createSamplerHandlerNorm(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) const
{
DDSTAT_LOCK();
VkResult result = m_vk.createSampler(device, pCreateInfo, pAllocator, pSampler);
m_resourceInterface->registerObjectHash(pSampler->getInternal(),
calculateSamplerHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
return result;
}
void DeviceDriverSC::createSamplerHandlerStat(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) const
{
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(samplerRequestCount, 1);
*pSampler = VkSampler(m_resourceInterface->incResourceCounter());
m_resourceInterface->registerObjectHash(pSampler->getInternal(),
calculateSamplerHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
m_resourceInterface->createSampler(device, pCreateInfo, pAllocator, pSampler);
}
VkResult DeviceDriverSC::createSamplerYcbcrConversionHandlerNorm(VkDevice device,
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSamplerYcbcrConversion *pYcbcrConversion) const
{
DDSTAT_LOCK();
VkResult result = m_vk.createSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
m_resourceInterface->registerObjectHash(
pYcbcrConversion->getInternal(),
calculateSamplerYcbcrConversionHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
return result;
}
void DeviceDriverSC::createSamplerYcbcrConversionHandlerStat(VkDevice device,
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSamplerYcbcrConversion *pYcbcrConversion) const
{
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(samplerYcbcrConversionRequestCount, 1);
*pYcbcrConversion = VkSamplerYcbcrConversion(m_resourceInterface->incResourceCounter());
m_resourceInterface->registerObjectHash(
pYcbcrConversion->getInternal(),
calculateSamplerYcbcrConversionHash(*pCreateInfo, m_resourceInterface->getObjectHashes()));
m_resourceInterface->createSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
}
void DeviceDriverSC::getDescriptorSetLayoutSupportHandler(VkDevice device,
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
VkDescriptorSetLayoutSupport *pSupport) const
{
DE_UNREF(device);
DDSTAT_LOCK();
for (uint32_t i = 0; i < pCreateInfo->bindingCount; ++i)
m_resourceInterface->getStatMax().descriptorSetLayoutBindingLimit = de::max(
m_resourceInterface->getStatMax().descriptorSetLayoutBindingLimit, pCreateInfo->pBindings[i].binding + 1);
pSupport->supported = VK_TRUE;
}
VkResult DeviceDriverSC::createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkShaderModule *pShaderModule) const
{
DDSTAT_LOCK();
return m_resourceInterface->createShaderModule(device, pCreateInfo, pAllocator, pShaderModule, m_normalMode);
}
VkResult DeviceDriverSC::createCommandPoolHandlerNorm(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkCommandPool *pCommandPool) const
{
DDSTAT_LOCK();
VkCommandPoolMemoryReservationCreateInfo *chainedMemoryReservation =
(VkCommandPoolMemoryReservationCreateInfo *)findStructureInChain(
pCreateInfo->pNext, VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_RESERVATION_CREATE_INFO);
// even if we deliver our own VkCommandPoolMemoryReservationCreateInfo - we have to call ResourceInterface::getNextCommandPoolSize() and ignore its results
vksc_server::VulkanCommandMemoryConsumption memC = m_resourceInterface->getNextCommandPoolSize();
VkCommandPoolCreateInfo pCreateInfoCopy = *pCreateInfo;
VkCommandPoolMemoryReservationCreateInfo cpMemReservationCI;
if (chainedMemoryReservation == DE_NULL)
{
VkDeviceSize cmdPoolSize = de::max(memC.maxCommandPoolReservedSize, m_commandPoolMinimumSize);
cmdPoolSize = de::max(cmdPoolSize, memC.commandBufferCount * m_commandBufferMinimumSize);
cpMemReservationCI = {
VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_RESERVATION_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
de::max(cmdPoolSize, m_commandBufferMinimumSize), // VkDeviceSize commandPoolReservedSize
de::max(memC.commandBufferCount, 1u) // uint32_t commandPoolMaxCommandBuffers
};
cpMemReservationCI.pNext = pCreateInfoCopy.pNext;
pCreateInfoCopy.pNext = &cpMemReservationCI;
}
return m_vk.createCommandPool(device, &pCreateInfoCopy, pAllocator, pCommandPool);
}
VkResult DeviceDriverSC::resetCommandPoolHandlerNorm(VkDevice device, VkCommandPool commandPool,
VkCommandPoolResetFlags flags) const
{
return m_vk.resetCommandPool(device, commandPool, flags);
}
void DeviceDriverSC::createCommandPoolHandlerStat(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkCommandPool *pCommandPool) const
{
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(commandPoolRequestCount, 1);
// Ensure that this VUID is satisfied: VUID-VkCommandPoolMemoryReservationCreateInfo-commandPoolMaxCommandBuffers-05074
m_resourceInterface->getStatMax().commandBufferRequestCount =
de::max(m_resourceInterface->getStatMax().commandBufferRequestCount,
m_resourceInterface->getStatMax().commandPoolRequestCount);
// Increase maximum value of commandBufferRequestCount in case of VkCommandPoolMemoryReservationCreateInfo presence in pNext chain.
// ( some of the dEQP-VKSC.sc.command_pool_memory_reservation.memory_consumption.*.reserved_size tests use VkCommandPoolMemoryReservationCreateInfo without really creating command buffers and as
// a result - commandBufferRequestCount was too low )
VkCommandPoolMemoryReservationCreateInfo *chainedMemoryReservation =
(VkCommandPoolMemoryReservationCreateInfo *)findStructureInChain(
pCreateInfo->pNext, VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_RESERVATION_CREATE_INFO);
if (chainedMemoryReservation != DE_NULL)
DDSTAT_HANDLE_CREATE(commandBufferRequestCount, chainedMemoryReservation->commandPoolMaxCommandBuffers);
else
DDSTAT_HANDLE_CREATE(commandBufferRequestCount, 1);
*pCommandPool = Handle<HANDLE_TYPE_COMMAND_POOL>(m_resourceInterface->incResourceCounter());
m_resourceInterface->createCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
}
void DeviceDriverSC::resetCommandPoolHandlerStat(VkDevice device, VkCommandPool commandPool,
VkCommandPoolResetFlags flags) const
{
m_resourceInterface->resetCommandPool(device, commandPool, flags);
}
void DeviceDriverSC::allocateCommandBuffersHandler(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
VkCommandBuffer *pCommandBuffers) const
{
DDSTAT_LOCK();
DDSTAT_HANDLE_CREATE(commandBufferRequestCount, pAllocateInfo->commandBufferCount);
for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; ++i)
pCommandBuffers[i] = (VkCommandBuffer)m_resourceInterface->incResourceCounter();
m_resourceInterface->allocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
}
void DeviceDriverSC::freeCommandBuffersHandler(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
const VkCommandBuffer *pCommandBuffers) const
{
DE_UNREF(device);
DE_UNREF(commandPool);
DE_UNREF(commandBufferCount);
DE_UNREF(pCommandBuffers);
}
void DeviceDriverSC::increaseCommandBufferSize(VkCommandBuffer commandBuffer, VkDeviceSize commandSize) const
{
DDSTAT_LOCK();
VkDeviceSize finalSize = de::max(commandSize, m_commandDefaultSize);
m_resourceInterface->increaseCommandBufferSize(commandBuffer, finalSize);
}
void DeviceDriverSC::checkFramebufferSupport(const VkFramebufferCreateInfo *pCreateInfo) const
{
if (m_resourceInterface->isVulkanSC())
{
if (pCreateInfo->attachmentCount > m_physicalDeviceVulkanSC10Properties.maxFramebufferAttachments)
{
const std::string msg = "Requested framebuffer attachment count (" +
de::toString(pCreateInfo->attachmentCount) +
") is greater than VulkanSC limits allow (" +
de::toString(m_physicalDeviceVulkanSC10Properties.maxFramebufferAttachments) + ")";
TCU_THROW(NotSupportedError, msg);
}
}
}
void DeviceDriverSC::checkRenderPassSupport(uint32_t attachmentCount, uint32_t subpassCount,
uint32_t dependencyCount) const
{
if (m_resourceInterface->isVulkanSC())
{
if (attachmentCount > m_physicalDeviceVulkanSC10Properties.maxFramebufferAttachments)
{
const std::string msg = "Requested render pass attachment count (" + de::toString(attachmentCount) +
") is greater than VulkanSC limits allow (" +
de::toString(m_physicalDeviceVulkanSC10Properties.maxFramebufferAttachments) + ")";
TCU_THROW(NotSupportedError, msg);
}
if (subpassCount > m_physicalDeviceVulkanSC10Properties.maxRenderPassSubpasses)
{
const std::string msg = "Requested subpassCount (" + de::toString(subpassCount) +
") is greater than VulkanSC limits allow (" +
de::toString(m_physicalDeviceVulkanSC10Properties.maxRenderPassSubpasses) + ")";
TCU_THROW(NotSupportedError, msg);
}
if (dependencyCount > m_physicalDeviceVulkanSC10Properties.maxRenderPassDependencies)
{
const std::string msg = "Requested dependencyCount (" + de::toString(dependencyCount) +
") is greater than VulkanSC limits allow (" +
de::toString(m_physicalDeviceVulkanSC10Properties.maxRenderPassDependencies) + ")";
TCU_THROW(NotSupportedError, msg);
}
}
}
void DeviceDriverSC::checkSubpassSupport(uint32_t inputAttachmentCount, uint32_t preserveAttachmentCount) const
{
if (m_resourceInterface->isVulkanSC())
{
if (inputAttachmentCount > m_physicalDeviceVulkanSC10Properties.maxSubpassInputAttachments)
{
const std::string msg = "Requested inputAttachmentCount (" + de::toString(inputAttachmentCount) +
") is greater than VulkanSC limits allow (" +
de::toString(m_physicalDeviceVulkanSC10Properties.maxSubpassInputAttachments) + ")";
TCU_THROW(NotSupportedError, msg);
}
if (preserveAttachmentCount > m_physicalDeviceVulkanSC10Properties.maxSubpassPreserveAttachments)
{
const std::string msg = "Requested preserveAttachmentCount (" + de::toString(preserveAttachmentCount) +
") is greater than VulkanSC limits allow (" +
de::toString(m_physicalDeviceVulkanSC10Properties.maxSubpassPreserveAttachments) +
")";
TCU_THROW(NotSupportedError, msg);
}
}
}
de::SharedPtr<ResourceInterface> DeviceDriverSC::gerResourceInterface() const
{
return m_resourceInterface;
}
void DeviceDriverSC::reset() const
{
// these objects should be empty when function is invoked, but we will clear it anyway
m_imageViews.clear();
m_renderPasses.clear();
m_renderPasses2.clear();
m_graphicsPipelines.clear();
m_computePipelines.clear();
}
#endif // CTS_USES_VULKANSC
#include "vkPlatformDriverImpl.inl"
#include "vkInstanceDriverImpl.inl"
#include "vkDeviceDriverImpl.inl"
#ifdef CTS_USES_VULKANSC
#include "vkDeviceDriverSCImpl.inl"
#endif // CTS_USES_VULKANSC
wsi::Display *Platform::createWsiDisplay(wsi::Type) const
{
TCU_THROW(NotSupportedError, "WSI not supported");
}
bool Platform::hasDisplay(wsi::Type) const
{
return false;
}
void Platform::describePlatform(std::ostream &dst) const
{
dst << "vk::Platform::describePlatform() not implemented";
}
} // namespace vk