blob: bba7a52047c05fec83df27b5f98952909af92d41 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2018 The Khronos Group Inc.
* Copyright (c) 2018 Google Inc.
* Copyright (c) 2018 ARM Limited.
*
* 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 Push Descriptor Tests
*//*--------------------------------------------------------------------*/
#include "vktPipelinePushDescriptorTests.hpp"
#include "vktPipelineClearUtil.hpp"
#include "vktPipelineImageUtil.hpp"
#include "vktPipelineVertexUtil.hpp"
#include "vktPipelineReferenceRenderer.hpp"
#include "vktTestCase.hpp"
#include "vkImageUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkPrograms.hpp"
#include "vkQueryUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "tcuImageCompare.hpp"
#include "deMemory.h"
#include "deUniquePtr.hpp"
#include "tcuTestLog.hpp"
#include "tcuCommandLine.hpp"
#include <vector>
namespace vkt
{
namespace pipeline
{
using namespace vk;
using namespace std;
namespace
{
typedef vector<VkExtensionProperties> Extensions;
typedef de::SharedPtr<Unique<VkBuffer> > VkBufferSp;
typedef de::SharedPtr<Unique<VkImage> > VkImageSp;
typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp;
typedef de::SharedPtr<Unique<VkBufferView> > VkBufferViewSp;
typedef de::SharedPtr<Allocation> AllocationSp;
typedef de::SharedPtr<Unique<VkRenderPass> > VkRenderPassSp;
typedef de::SharedPtr<Unique<VkFramebuffer> > VkFramebufferSp;
typedef de::SharedPtr<Unique<VkPipeline> > VkPipelineSp;
struct TestParams
{
VkDescriptorType descriptorType;
deUint32 binding;
deUint32 numCalls; // Number of draw or dispatch calls
};
void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
{
for (auto& requiredExtName : requiredExtensions)
{
if (!isExtensionSupported(supportedExtensions, RequiredExtension(requiredExtName)))
TCU_THROW(NotSupportedError, (requiredExtName + " is not supported").c_str());
}
}
Move<VkInstance> createInstanceWithGetPhysicalDeviceProperties2 (const Context& context,
const PlatformInterface& vkp,
const Extensions& supportedExtensions)
{
vector<string> requiredExtensions = { "VK_KHR_get_physical_device_properties2" };
checkAllSupported(supportedExtensions, requiredExtensions);
vector<string> enabledLayers;
if (context.getTestContext().getCommandLine().isValidationEnabled())
{
enabledLayers = vkt::getValidationLayers(vkp);
}
return createDefaultInstance(vkp, context.getUsedApiVersion(), enabledLayers, requiredExtensions);
}
const char *innerCString(const string &str)
{
return str.c_str();
}
Move<VkDevice> createDeviceWithPushDescriptor (const Context& context,
const PlatformInterface& vkp,
VkInstance instance,
const InstanceInterface& vki,
VkPhysicalDevice physicalDevice,
const Extensions& supportedExtensions,
const deUint32 queueFamilyIndex)
{
const float queuePriority = 1.0f;
const VkDeviceQueueCreateInfo queueInfo =
{
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
DE_NULL,
(VkDeviceQueueCreateFlags)0,
queueFamilyIndex,
1u,
&queuePriority
};
VkPhysicalDeviceFeatures features;
deMemset(&features, 0, sizeof(features));
vector<string> requiredExtensionsStr = { "VK_KHR_push_descriptor" };
vector<const char *> requiredExtensions;
checkAllSupported(supportedExtensions, requiredExtensionsStr);
// We need the contents of requiredExtensionsStr as a vector<const char*> in VkDeviceCreateInfo.
transform(begin(requiredExtensionsStr), end(requiredExtensionsStr), back_inserter(requiredExtensions), innerCString);
// Enable validation layers on this device if validation has been requested from the command line.
vector<string> enabledLayersStr;
vector<const char*> enabledLayers;
if (context.getTestContext().getCommandLine().isValidationEnabled())
{
// We need the contents of enabledLayersStr as a vector<const char*> in VkDeviceCreateInfo.
enabledLayersStr = vkt::getValidationLayers(vki, physicalDevice);
transform(begin(enabledLayersStr), end(enabledLayersStr), back_inserter(enabledLayers), innerCString);
}
const VkDeviceCreateInfo deviceParams =
{
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
DE_NULL,
(VkDeviceCreateFlags)0,
1u,
&queueInfo,
static_cast<deUint32>(enabledLayers.size()),
(enabledLayers.empty() ? DE_NULL : enabledLayers.data()),
static_cast<deUint32>(requiredExtensions.size()),
(requiredExtensions.empty() ? DE_NULL : requiredExtensions.data()),
&features
};
return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, DE_NULL);
}
deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
{
const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
{
if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
return (deUint32)queueNdx;
}
TCU_THROW(NotSupportedError, "No matching queue found");
}
vector<Vertex4RGBA> createQuads (deUint32 numQuads, float size)
{
vector<Vertex4RGBA> vertices;
for (deUint32 quadNdx = 0; quadNdx < numQuads; quadNdx++)
{
const float xOffset = -0.5f + (float)quadNdx;
const tcu::Vec4 color (0.0f);
const Vertex4RGBA lowerLeftVertex = {tcu::Vec4(-size + xOffset, -size, 0.0f, 1.0f), color};
const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size + xOffset, -size, 0.0f, 1.0f), color};
const Vertex4RGBA UpperLeftVertex = {tcu::Vec4(-size + xOffset, size, 0.0f, 1.0f), color};
const Vertex4RGBA UpperRightVertex = {tcu::Vec4(size + xOffset, size, 0.0f, 1.0f), color};
vertices.push_back(lowerLeftVertex);
vertices.push_back(lowerRightVertex);
vertices.push_back(UpperLeftVertex);
vertices.push_back(UpperLeftVertex);
vertices.push_back(lowerRightVertex);
vertices.push_back(UpperRightVertex);
}
return vertices;
}
vector<Vertex4Tex4> createTexQuads (deUint32 numQuads, float size)
{
vector<Vertex4Tex4> vertices;
for (deUint32 quadNdx = 0; quadNdx < numQuads; quadNdx++)
{
const float xOffset = -0.5f + (float)quadNdx;
const Vertex4Tex4 lowerLeftVertex = {tcu::Vec4(-size + xOffset, -size, 0.0f, 1.0f), tcu::Vec4(-0.2f, -0.2f, 0.0f, 0.0f)};
const Vertex4Tex4 lowerRightVertex = {tcu::Vec4(size + xOffset, -size, 0.0f, 1.0f), tcu::Vec4(1.2f, -0.2f, 0.0f, 0.0f)};
const Vertex4Tex4 UpperLeftVertex = {tcu::Vec4(-size + xOffset, size, 0.0f, 1.0f), tcu::Vec4(-0.2f, 1.2f, 0.0f, 0.0f)};
const Vertex4Tex4 UpperRightVertex = {tcu::Vec4(size + xOffset, size, 0.0f, 1.0f), tcu::Vec4(1.2f, 1.2f, 0.0f, 0.0f)};
vertices.push_back(lowerLeftVertex);
vertices.push_back(lowerRightVertex);
vertices.push_back(UpperLeftVertex);
vertices.push_back(UpperLeftVertex);
vertices.push_back(lowerRightVertex);
vertices.push_back(UpperRightVertex);
}
return vertices;
}
static const tcu::Vec4 defaultTestColors[] =
{
tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)
};
class PushDescriptorBufferGraphicsTestInstance : public vkt::TestInstance
{
public:
PushDescriptorBufferGraphicsTestInstance (Context& context, const TestParams& params);
virtual ~PushDescriptorBufferGraphicsTestInstance (void);
void init (void);
virtual tcu::TestStatus iterate (void);
tcu::TestStatus verifyImage (void);
private:
const TestParams m_params;
const PlatformInterface& m_vkp;
const Extensions m_instanceExtensions;
const Unique<VkInstance> m_instance;
const InstanceDriver m_vki;
const VkPhysicalDevice m_physicalDevice;
const deUint32 m_queueFamilyIndex;
const Extensions m_deviceExtensions;
const Unique<VkDevice> m_device;
const DeviceDriver m_vkd;
const VkQueue m_queue;
SimpleAllocator m_allocator;
const tcu::UVec2 m_renderSize;
const VkFormat m_colorFormat;
Move<VkImage> m_colorImage;
de::MovePtr<Allocation> m_colorImageAlloc;
Move<VkImageView> m_colorAttachmentView;
Move<VkRenderPass> m_renderPass;
Move<VkFramebuffer> m_framebuffer;
Move<VkShaderModule> m_vertexShaderModule;
Move<VkShaderModule> m_fragmentShaderModule;
Move<VkBuffer> m_vertexBuffer;
de::MovePtr<Allocation> m_vertexBufferAlloc;
vector<VkBufferSp> m_buffers;
vector<AllocationSp> m_bufferAllocs;
Move<VkDescriptorSetLayout> m_descriptorSetLayout;
Move<VkPipelineLayout> m_pipelineLayout;
Move<VkPipeline> m_graphicsPipelines;
Move<VkCommandPool> m_cmdPool;
Move<VkCommandBuffer> m_cmdBuffer;
vector<Vertex4RGBA> m_vertices;
};
PushDescriptorBufferGraphicsTestInstance::PushDescriptorBufferGraphicsTestInstance (Context& context, const TestParams& params)
: vkt::TestInstance (context)
, m_params (params)
, m_vkp (context.getPlatformInterface())
, m_instanceExtensions (enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
, m_instance (createInstanceWithGetPhysicalDeviceProperties2(context, m_vkp, m_instanceExtensions))
, m_vki (m_vkp, *m_instance)
, m_physicalDevice (chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
, m_queueFamilyIndex (findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
, m_deviceExtensions (enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
, m_device (createDeviceWithPushDescriptor(context, m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex))
, m_vkd (m_vkp, *m_instance, *m_device)
, m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
, m_allocator (m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
, m_renderSize (32, 32)
, m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
, m_vertices (createQuads(params.numCalls, 0.25f))
{
}
void PushDescriptorBufferGraphicsTestInstance::init (void)
{
const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
// Create color image
{
const VkImageCreateInfo colorImageParams =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_colorFormat, // VkFormat format;
{ m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&m_queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
m_colorImage = createImage(m_vkd, *m_device, &colorImageParams);
// Allocate and bind color image memory
m_colorImageAlloc = m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
}
// Create color attachment view
{
const VkImageViewCreateInfo colorAttachmentViewParams =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
*m_colorImage, // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
m_colorFormat, // VkFormat format;
componentMappingRGBA, // VkChannelMapping channels;
{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
};
m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
}
// Create render pass
m_renderPass = makeRenderPass(m_vkd, *m_device, m_colorFormat);
// Create framebuffer
{
const VkImageView attachmentBindInfos[] =
{
*m_colorAttachmentView
};
const VkFramebufferCreateInfo framebufferParams =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkFramebufferCreateFlags flags;
*m_renderPass, // VkRenderPass renderPass;
1u, // deUint32 attachmentCount;
attachmentBindInfos, // const VkImageView* pAttachments;
(deUint32)m_renderSize.x(), // deUint32 width;
(deUint32)m_renderSize.y(), // deUint32 height;
1u // deUint32 layers;
};
m_framebuffer = createFramebuffer(m_vkd, *m_device, &framebufferParams);
}
// Create pipeline layout
{
// Create descriptor set layout
const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
{
m_params.binding, // uint32_t binding;
m_params.descriptorType, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
1u, // uint32_t bindingCount;
&descriptorSetLayoutBinding // const VkDescriptorSetLayoutBinding* pBindings;
};
m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
// Create pipeline layout
const VkPipelineLayoutCreateInfo pipelineLayoutParams =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineLayoutCreateFlags flags;
1u, // deUint32 descriptorSetCount;
&(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
0u, // deUint32 pushConstantRangeCount;
DE_NULL // const VkPushDescriptorRange* pPushDescriptorRanges;
};
m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
}
// Create buffers. One color value in each buffer.
{
for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
{
const VkBufferUsageFlags usageFlags = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
const VkBufferCreateInfo bufferCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags
16u, // VkDeviceSize size;
usageFlags, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&m_queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
m_bufferAllocs.push_back(AllocationSp(m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]), MemoryRequirement::HostVisible).release()));
VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(), m_bufferAllocs[bufIdx]->getOffset()));
deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx], 16u);
flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
}
}
// Create shaders
{
m_vertexShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
m_fragmentShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
}
// Create pipeline
{
const VkVertexInputBindingDescription vertexInputBindingDescription =
{
0u, // deUint32 binding;
sizeof(Vertex4RGBA), // deUint32 strideInBytes;
VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
};
const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
{
{
0u, // deUint32 location;
0u, // deUint32 binding;
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
0u // deUint32 offsetInBytes;
},
{
1u, // deUint32 location;
0u, // deUint32 binding;
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset;
}
};
const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // vkPipelineVertexInputStateCreateFlags flags;
1u, // deUint32 bindingCount;
&vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2u, // deUint32 attributeCount;
vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
};
const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
const vector<VkViewport> viewports (1, makeViewport(m_renderSize));
const vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
m_graphicsPipelines = makeGraphicsPipeline(m_vkd, // const DeviceInterface& vk
*m_device, // const VkDevice device
*m_pipelineLayout, // const VkPipelineLayout pipelineLayout
*m_vertexShaderModule, // const VkShaderModule vertexShaderModule
DE_NULL, // const VkShaderModule tessellationControlShaderModule
DE_NULL, // const VkShaderModule tessellationEvalShaderModule
DE_NULL, // const VkShaderModule geometryShaderModule
*m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
*m_renderPass, // const VkRenderPass renderPass
viewports, // const std::vector<VkViewport>& viewports
scissors, // const std::vector<VkRect2D>& scissors
topology, // const VkPrimitiveTopology topology
0u, // const deUint32 subpass
0u, // const deUint32 patchControlPoints
&vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
}
// Create vertex buffer
{
const VkBufferCreateInfo vertexBufferParams =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags;
(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&m_queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_vertexBuffer = createBuffer(m_vkd, *m_device, &vertexBufferParams);
m_vertexBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
// Load vertices into vertex buffer
deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
}
// Create command pool
m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
// Create command buffer
{
const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
const VkDeviceSize vertexBufferOffset = 0;
m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
beginRenderPass(m_vkd, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
// Draw quads. Switch input buffer which contains the quad color for each draw call.
for (deUint32 quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
{
VkDescriptorBufferInfo descriptorBufferInfo =
{
**m_buffers[quadNdx], // VkBuffer buffer;
0u, // VkDeviceSize offset;
16u // VkDeviceSize range;
};
VkWriteDescriptorSet writeDescriptorSet =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkDescriptorSet dstSet;
m_params.binding, // uint32_t dstBinding;
0u, // uint32_t dstArrayElement;
1u, // uint32_t descriptorCount;
m_params.descriptorType, // VkDescriptorType descriptorType;
DE_NULL, // const VkDescriptorImageInfo* pImageInfo;
&descriptorBufferInfo, // const VkDescriptorBufferInfo* pBufferInfo;
DE_NULL // const VkBufferView* pTexelBufferView;
};
m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &writeDescriptorSet);
m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
}
endRenderPass(m_vkd, *m_cmdBuffer);
endCommandBuffer(m_vkd, *m_cmdBuffer);
}
}
PushDescriptorBufferGraphicsTestInstance::~PushDescriptorBufferGraphicsTestInstance (void)
{
}
tcu::TestStatus PushDescriptorBufferGraphicsTestInstance::iterate (void)
{
init();
submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
return verifyImage();
}
tcu::TestStatus PushDescriptorBufferGraphicsTestInstance::verifyImage (void)
{
const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
const ColorVertexShader vertexShader;
const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat);
const rr::Program program (&vertexShader, &fragmentShader);
ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
bool compareOk = false;
// Render reference image
{
for (deUint32 quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
for (deUint32 vertexIdx = 0; vertexIdx < 6; vertexIdx++)
m_vertices[quadIdx * 6 + vertexIdx].color.xyzw() = defaultTestColors[quadIdx];
refRenderer.draw(rr::RenderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits),
rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
}
// Compare result with reference image
{
de::MovePtr<tcu::TextureLevel> result = readColorAttachment(m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
"IntImageCompare",
"Image comparison",
refRenderer.getAccess(),
result->getAccess(),
tcu::UVec4(2, 2, 2, 2),
tcu::IVec3(1, 1, 0),
true,
tcu::COMPARE_LOG_RESULT);
}
if (compareOk)
return tcu::TestStatus::pass("Result image matches reference");
else
return tcu::TestStatus::fail("Image mismatch");
}
class PushDescriptorBufferGraphicsTest : public vkt::TestCase
{
public:
PushDescriptorBufferGraphicsTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params);
~PushDescriptorBufferGraphicsTest (void);
void initPrograms (SourceCollections& sourceCollections) const;
TestInstance* createInstance (Context& context) const;
protected:
const TestParams m_params;
};
PushDescriptorBufferGraphicsTest::PushDescriptorBufferGraphicsTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params)
: vkt::TestCase (testContext, name, description)
, m_params (params)
{
}
PushDescriptorBufferGraphicsTest::~PushDescriptorBufferGraphicsTest (void)
{
}
TestInstance* PushDescriptorBufferGraphicsTest::createInstance (Context& context) const
{
return new PushDescriptorBufferGraphicsTestInstance(context, m_params);
}
void PushDescriptorBufferGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
{
const string bufferType = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? "uniform" : "readonly buffer";
const string vertexSrc =
"#version 450\n"
"layout(location = 0) in highp vec4 position;\n"
"layout(location = 1) in highp vec4 color;\n"
"layout(location = 0) out highp vec4 vtxColor;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") " + bufferType + " Block\n"
"{\n"
" vec4 color;\n"
"} inputData;\n"
"\n"
"out gl_PerVertex { vec4 gl_Position; };\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
" vtxColor = inputData.color;\n"
"}\n";
const string fragmentSrc =
"#version 450\n"
"layout(location = 0) in highp vec4 vtxColor;\n"
"layout(location = 0) out highp vec4 fragColor;\n"
"\n"
"void main (void)\n"
"{\n"
" fragColor = vtxColor;\n"
"}\n";
sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
}
class PushDescriptorBufferComputeTestInstance : public vkt::TestInstance
{
public:
PushDescriptorBufferComputeTestInstance (Context& context, const TestParams& params);
virtual ~PushDescriptorBufferComputeTestInstance (void);
void init (void);
virtual tcu::TestStatus iterate (void);
tcu::TestStatus verifyOutput (void);
private:
const TestParams m_params;
const PlatformInterface& m_vkp;
const Extensions m_instanceExtensions;
const Unique<VkInstance> m_instance;
const InstanceDriver m_vki;
const VkPhysicalDevice m_physicalDevice;
const deUint32 m_queueFamilyIndex;
const Extensions m_deviceExtensions;
const Unique<VkDevice> m_device;
const DeviceDriver m_vkd;
const VkQueue m_queue;
SimpleAllocator m_allocator;
Move<VkShaderModule> m_computeShaderModule;
vector<VkBufferSp> m_buffers;
vector<AllocationSp> m_bufferAllocs;
Move<VkBuffer> m_outputBuffer;
de::MovePtr<Allocation> m_outputBufferAlloc;
Move<VkDescriptorSetLayout> m_descriptorSetLayout;
Move<VkPipelineLayout> m_pipelineLayout;
Move<VkPipeline> m_computePipeline;
Move<VkCommandPool> m_cmdPool;
Move<VkCommandBuffer> m_cmdBuffer;
std::vector<tcu::Vec4> m_testColors;
};
PushDescriptorBufferComputeTestInstance::PushDescriptorBufferComputeTestInstance (Context& context, const TestParams& params)
: vkt::TestInstance (context)
, m_params (params)
, m_vkp (context.getPlatformInterface())
, m_instanceExtensions (enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
, m_instance (createInstanceWithGetPhysicalDeviceProperties2(context, m_vkp, m_instanceExtensions))
, m_vki (m_vkp, *m_instance)
, m_physicalDevice (chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
, m_queueFamilyIndex (findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT))
, m_deviceExtensions (enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
, m_device (createDeviceWithPushDescriptor(context, m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex))
, m_vkd (m_vkp, *m_instance, *m_device)
, m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
, m_allocator (m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
{
}
void PushDescriptorBufferComputeTestInstance::init (void)
{
// Create pipeline layout
{
// Create descriptor set layout
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[] =
{
{
m_params.binding, // uint32_t binding;
m_params.descriptorType, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
},
{
m_params.binding + 1, // uint32_t binding;
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
}
};
const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
2u, // uint32_t bindingCount;
descriptorSetLayoutBindings // const VkDescriptorSetLayoutBinding* pBindings;
};
m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
// Create pipeline layout
const VkPipelineLayoutCreateInfo pipelineLayoutParams =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineLayoutCreateFlags flags;
1u, // deUint32 descriptorSetCount;
&(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
0u, // deUint32 pushConstantRangeCount;
DE_NULL // const VkPushDescriptorRange* pPushDescriptorRanges;
};
m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
}
// Fill the test colors table
m_testColors.resize(m_params.numCalls);
for (deUint32 colorIdx = 0; colorIdx < m_params.numCalls; colorIdx++)
{
if (colorIdx < DE_LENGTH_OF_ARRAY(defaultTestColors))
m_testColors[colorIdx] = defaultTestColors[colorIdx];
else
{
const float mix = static_cast<float>(colorIdx) / static_cast<float>(m_params.numCalls - 1);
// interpolate between first and last color, require these colors to be different
DE_ASSERT(defaultTestColors[0] != defaultTestColors[DE_LENGTH_OF_ARRAY(defaultTestColors) - 1]);
m_testColors[colorIdx] = defaultTestColors[0] * mix + defaultTestColors[DE_LENGTH_OF_ARRAY(defaultTestColors) - 1] * (1.0f - mix);
}
}
// Create buffers. One color value in each buffer.
{
for (deUint32 bufIdx = 0; bufIdx < m_params.numCalls; bufIdx++)
{
const VkBufferUsageFlags usageFlags = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
const VkBufferCreateInfo bufferCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags
16u, // VkDeviceSize size;
usageFlags, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&m_queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
m_bufferAllocs.push_back(AllocationSp(m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]), MemoryRequirement::HostVisible).release()));
VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(), m_bufferAllocs[bufIdx]->getOffset()));
deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &m_testColors[bufIdx], 16u);
flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
}
}
// Create output buffer
{
const VkBufferCreateInfo bufferCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags
16u * m_params.numCalls, // VkDeviceSize size;
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&m_queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_outputBuffer = createBuffer(m_vkd, *m_device, &bufferCreateInfo);
m_outputBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer), MemoryRequirement::HostVisible);
VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(), m_outputBufferAlloc->getOffset()));
}
// Create shader
{
m_computeShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
}
// Create pipeline
{
const VkPipelineShaderStageCreateInfo stageCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineShaderStageCreateFlags flags;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
*m_computeShaderModule, // VkShaderModule module;
"main", // const char* pName;
DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
};
const VkComputePipelineCreateInfo createInfo =
{
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineCreateFlags flags;
stageCreateInfo, // VkPipelineShaderStageCreateInfo stage;
*m_pipelineLayout, // VkPipelineLayout layout;
(VkPipeline)0, // VkPipeline basePipelineHandle;
0u, // int32_t basePipelineIndex;
};
m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
}
// Create command pool
m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
// Create command buffer
{
m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
// Dispatch: Each dispatch switches the input buffer.
// Output buffer is exposed as a vec4 sized window.
for (deUint32 dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
{
VkDescriptorBufferInfo descriptorBufferInfoUbo =
{
**m_buffers[dispatchNdx], // VkBuffer buffer;
0u, // VkDeviceSize offset;
16u // VkDeviceSize range;
};
VkDescriptorBufferInfo descriptorBufferInfoOutput =
{
*m_outputBuffer, // VkBuffer buffer;
16u * dispatchNdx, // VkDeviceSize offset;
16u // VkDeviceSize range;
};
VkWriteDescriptorSet writeDescriptorSets[] =
{
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkDescriptorSet dstSet;
m_params.binding, // uint32_t dstBinding;
0u, // uint32_t dstArrayElement;
1u, // uint32_t descriptorCount;
m_params.descriptorType, // VkDescriptorType descriptorType;
DE_NULL, // const VkDescriptorImageInfo* pImageInfo;
&descriptorBufferInfoUbo, // const VkDescriptorBufferInfo* pBufferInfo;
DE_NULL // const VkBufferView* pTexelBufferView;
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkDescriptorSet dstSet;
m_params.binding + 1, // uint32_t dstBinding;
0u, // uint32_t dstArrayElement;
1u, // uint32_t descriptorCount;
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
DE_NULL, // const VkDescriptorImageInfo* pImageInfo;
&descriptorBufferInfoOutput, // const VkDescriptorBufferInfo* pBufferInfo;
DE_NULL // const VkBufferView* pTexelBufferView;
}
};
m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 2, writeDescriptorSets);
m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
}
endCommandBuffer(m_vkd, *m_cmdBuffer);
}
}
PushDescriptorBufferComputeTestInstance::~PushDescriptorBufferComputeTestInstance (void)
{
}
tcu::TestStatus PushDescriptorBufferComputeTestInstance::iterate (void)
{
init();
submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
return verifyOutput();
}
tcu::TestStatus PushDescriptorBufferComputeTestInstance::verifyOutput (void)
{
invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
// Verify result
if (deMemCmp((void*)&m_testColors[0], m_outputBufferAlloc->getHostPtr(), (size_t)(16u * m_params.numCalls)))
{
return tcu::TestStatus::fail("Output mismatch");
}
return tcu::TestStatus::pass("Output matches expected values");
}
class PushDescriptorBufferComputeTest : public vkt::TestCase
{
public:
PushDescriptorBufferComputeTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params);
~PushDescriptorBufferComputeTest (void);
void initPrograms (SourceCollections& sourceCollections) const;
TestInstance* createInstance (Context& context) const;
protected:
const TestParams m_params;
};
PushDescriptorBufferComputeTest::PushDescriptorBufferComputeTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params)
: vkt::TestCase (testContext, name, description)
, m_params (params)
{
}
PushDescriptorBufferComputeTest::~PushDescriptorBufferComputeTest (void)
{
}
TestInstance* PushDescriptorBufferComputeTest::createInstance (Context& context) const
{
return new PushDescriptorBufferComputeTestInstance(context, m_params);
}
void PushDescriptorBufferComputeTest::initPrograms (SourceCollections& sourceCollections) const
{
const string bufferType = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? "uniform" : "buffer";
const string computeSrc =
"#version 450\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") " + bufferType + " Block\n"
"{\n"
" vec4 color;\n"
"} inputData;\n"
"\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
"{\n"
" vec4 color;\n"
"} outData;\n"
"\n"
"void main()\n"
"{\n"
" outData.color = inputData.color;\n"
"}\n";
sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
}
class PushDescriptorImageGraphicsTestInstance : public vkt::TestInstance
{
public:
PushDescriptorImageGraphicsTestInstance (Context& context, const TestParams& params);
virtual ~PushDescriptorImageGraphicsTestInstance (void);
void init (void);
virtual tcu::TestStatus iterate (void);
tcu::TestStatus verifyImage (void);
private:
const TestParams m_params;
const PlatformInterface& m_vkp;
const Extensions m_instanceExtensions;
const Unique<VkInstance> m_instance;
const InstanceDriver m_vki;
const VkPhysicalDevice m_physicalDevice;
const deUint32 m_queueFamilyIndex;
const Extensions m_deviceExtensions;
const Unique<VkDevice> m_device;
const DeviceDriver m_vkd;
const VkQueue m_queue;
SimpleAllocator m_allocator;
const tcu::UVec2 m_renderSize;
const tcu::UVec2 m_textureSize;
const VkFormat m_colorFormat;
Move<VkImage> m_colorImage;
de::MovePtr<Allocation> m_colorImageAlloc;
Move<VkImageView> m_colorAttachmentView;
vector<VkImageSp> m_textureImages;
vector<AllocationSp> m_textureImageAllocs;
vector<VkImageViewSp> m_textureViews;
Move<VkSampler> m_whiteBorderSampler;
Move<VkSampler> m_blackBorderSampler;
Move<VkRenderPass> m_renderPass;
Move<VkFramebuffer> m_framebuffer;
Move<VkShaderModule> m_vertexShaderModule;
Move<VkShaderModule> m_fragmentShaderModule;
Move<VkBuffer> m_vertexBuffer;
de::MovePtr<Allocation> m_vertexBufferAlloc;
Move<VkDescriptorSetLayout> m_descriptorSetLayout;
Move<VkPipelineLayout> m_pipelineLayout;
Move<VkPipeline> m_graphicsPipelines;
Move<VkCommandPool> m_cmdPool;
Move<VkCommandBuffer> m_cmdBuffer;
vector<Vertex4Tex4> m_vertices;
};
PushDescriptorImageGraphicsTestInstance::PushDescriptorImageGraphicsTestInstance (Context& context, const TestParams& params)
: vkt::TestInstance (context)
, m_params (params)
, m_vkp (context.getPlatformInterface())
, m_instanceExtensions (enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
, m_instance (createInstanceWithGetPhysicalDeviceProperties2(context, m_vkp, m_instanceExtensions))
, m_vki (m_vkp, *m_instance)
, m_physicalDevice (chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
, m_queueFamilyIndex (findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
, m_deviceExtensions (enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
, m_device (createDeviceWithPushDescriptor(context, m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex))
, m_vkd (m_vkp, *m_instance, *m_device)
, m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
, m_allocator (m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
, m_renderSize (32, 32)
, m_textureSize (32, 32)
, m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
, m_vertices (createTexQuads(params.numCalls, 0.25f))
{
}
void PushDescriptorImageGraphicsTestInstance::init (void)
{
const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
// Create color image
{
const VkImageCreateInfo colorImageParams =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_colorFormat, // VkFormat format;
{ m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&m_queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
m_colorImage = createImage(m_vkd, *m_device, &colorImageParams);
// Allocate and bind color image memory
m_colorImageAlloc = m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
}
// Create color attachment view
{
const VkImageViewCreateInfo colorAttachmentViewParams =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
*m_colorImage, // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
m_colorFormat, // VkFormat format;
componentMappingRGBA, // VkChannelMapping channels;
{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
};
m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
}
// Create texture images
for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
{
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
const VkImageCreateInfo textureImageParams =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_colorFormat, // VkFormat format;
{ m_textureSize.x(), m_textureSize.y(), 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
usageFlags, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&m_queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
m_textureImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &textureImageParams))));
// Allocate and bind texture image memory
m_textureImageAllocs.push_back(AllocationSp(m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_textureImages.back()), MemoryRequirement::Any).release()));
VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_textureImages.back(), m_textureImageAllocs.back()->getMemory(), m_textureImageAllocs.back()->getOffset()));
}
// Create texture image views
for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
{
const VkImageViewCreateInfo textureViewParams =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
**m_textureImages[texIdx], // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
m_colorFormat, // VkFormat format;
componentMappingRGBA, // VkChannelMapping channels;
{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
};
m_textureViews.push_back(VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
}
VkClearValue clearValues[2];
clearValues[0].color.float32[0] = 0.0f;
clearValues[0].color.float32[1] = 1.0f;
clearValues[0].color.float32[2] = 0.0f;
clearValues[0].color.float32[3] = 1.0f;
clearValues[1].color.float32[0] = 1.0f;
clearValues[1].color.float32[1] = 0.0f;
clearValues[1].color.float32[2] = 0.0f;
clearValues[1].color.float32[3] = 1.0f;
const VkImageLayout textureImageLayout = (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
// Clear textures
for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
{
const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Move<VkCommandPool> cmdPool;
Move<VkCommandBuffer> cmdBuffer;
cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
const VkImageMemoryBarrier preImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkAccessFlags srcAccessMask;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
**m_textureImages[texIdx], // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
aspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
const VkImageMemoryBarrier postImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
textureImageLayout, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
**m_textureImages[texIdx], // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
aspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
const VkImageSubresourceRange clearRange =
{
aspectMask, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
1u, // deUint32 levelCount;
0u, // deUint32 baseArrayLayer;
1u // deUint32 layerCount;
};
beginCommandBuffer(m_vkd, *cmdBuffer);
m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
m_vkd.cmdClearColorImage(*cmdBuffer, **m_textureImages[texIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValues[texIdx].color, 1, &clearRange);
m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
endCommandBuffer(m_vkd, *cmdBuffer);
submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
}
// Create samplers: one with white and one with black border color to have a visible effect on switching the sampler
{
VkSamplerCreateInfo samplerParams =
{
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkSamplerCreateFlags flags;
VK_FILTER_NEAREST, // VkFilter magFilter;
VK_FILTER_NEAREST, // VkFilter minFilter;
VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeU;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeV;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeW;
0.0f, // float mipLodBias;
VK_FALSE, // VkBool32 anisotropyEnable;
0.0f, // float maxAnisotropy;
VK_FALSE, // VkBool32 compareEnable;
VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
0.0f, // float minLod;
0.0f, // float maxLod;
VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, // VkBorderColor borderColor;
VK_FALSE // VkBool32 unnormalizedCoordinates;
};
m_whiteBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
samplerParams.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
m_blackBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
}
// Create render pass
{
const VkAttachmentDescription attachmentDescription =
{
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
};
const VkAttachmentReference resultAttachmentRef =
{
0u, // deUint32 attachment
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
};
const VkSubpassDescription subpassDescription =
{
(VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
0u, // deUint32 inputAttachmentCount
DE_NULL, // const VkAttachmentReference* pInputAttachments
1u, // deUint32 colorAttachmentCount
&resultAttachmentRef, // const VkAttachmentReference* pColorAttachments
DE_NULL, // const VkAttachmentReference* pResolveAttachments
DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
0u, // deUint32 preserveAttachmentCount
DE_NULL // const deUint32* pPreserveAttachments
};
const VkRenderPassCreateInfo renderPassInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureTypei sType
DE_NULL, // const void* pNext
(VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
1u, // deUint32 attachmentCount
&attachmentDescription, // const VkAttachmentDescription* pAttachments
1u, // deUint32 subpassCount
&subpassDescription, // const VkSubpassDescription* pSubpasses
0u, // deUint32 dependencyCount
DE_NULL // const VkSubpassDependency* pDependencies
};
m_renderPass = createRenderPass(m_vkd, *m_device, &renderPassInfo);
}
// Create framebuffer
{
const VkImageView attachmentBindInfos[] =
{
*m_colorAttachmentView
};
const VkFramebufferCreateInfo framebufferParams =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkFramebufferCreateFlags flags;
*m_renderPass, // VkRenderPass renderPass;
1u, // deUint32 attachmentCount;
attachmentBindInfos, // const VkImageView* pAttachments;
(deUint32)m_renderSize.x(), // deUint32 width;
(deUint32)m_renderSize.y(), // deUint32 height;
1u // deUint32 layers;
};
m_framebuffer = createFramebuffer(m_vkd, *m_device, &framebufferParams);
}
// Create pipeline layout
{
// Create descriptor set layout
vector<VkDescriptorSetLayoutBinding> layoutBindings;
switch(m_params.descriptorType)
{
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBinding);
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLER:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex =
{
m_params.binding + 1, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBindingSampler);
layoutBindings.push_back(descriptorSetLayoutBindingTex);
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler =
{
m_params.binding + 1, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBindingSampler);
layoutBindings.push_back(descriptorSetLayoutBindingTex);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBinding);
}
break;
default:
DE_FATAL("unexpected descriptor type");
break;
};
const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
(deUint32)layoutBindings.size(), // uint32_t bindingCount;
layoutBindings.data() // const VkDescriptorSetLayoutBinding* pBindings;
};
m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
// Create pipeline layout
const VkPipelineLayoutCreateInfo pipelineLayoutParams =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineLayoutCreateFlags flags;
1u, // deUint32 descriptorSetCount;
&(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
0u, // deUint32 pushConstantRangeCount;
DE_NULL // const VkPushDescriptorRange* pPushDescriptorRanges;
};
m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
}
// Create shaders
{
m_vertexShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("vert"), 0u);
m_fragmentShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("frag"), 0u);
}
// Create pipeline
{
const VkVertexInputBindingDescription vertexInputBindingDescription =
{
0u, // deUint32 binding;
sizeof(Vertex4Tex4), // deUint32 strideInBytes;
VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
};
const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
{
{
0u, // deUint32 location;
0u, // deUint32 binding;
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
0u // deUint32 offsetInBytes;
},
{
1u, // deUint32 location;
0u, // deUint32 binding;
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
DE_OFFSET_OF(Vertex4Tex4, texCoord), // deUint32 offset;
}
};
const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // vkPipelineVertexInputStateCreateFlags flags;
1u, // deUint32 bindingCount;
&vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2u, // deUint32 attributeCount;
vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
};
const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
const vector<VkViewport> viewports (1, makeViewport(m_renderSize));
const vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
m_graphicsPipelines = makeGraphicsPipeline(m_vkd, // const DeviceInterface& vk
*m_device, // const VkDevice device
*m_pipelineLayout, // const VkPipelineLayout pipelineLayout
*m_vertexShaderModule, // const VkShaderModule vertexShaderModule
DE_NULL, // const VkShaderModule tessellationControlShaderModule
DE_NULL, // const VkShaderModule tessellationEvalShaderModule
DE_NULL, // const VkShaderModule geometryShaderModule
*m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
*m_renderPass, // const VkRenderPass renderPass
viewports, // const std::vector<VkViewport>& viewports
scissors, // const std::vector<VkRect2D>& scissors
topology, // const VkPrimitiveTopology topology
0u, // const deUint32 subpass
0u, // const deUint32 patchControlPoints
&vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
}
// Create vertex buffer
{
const VkBufferCreateInfo vertexBufferParams =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags;
(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&m_queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_vertexBuffer = createBuffer(m_vkd, *m_device, &vertexBufferParams);
m_vertexBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
// Load vertices into vertex buffer
deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4Tex4));
flushAlloc(m_vkd, *m_device, *m_vertexBufferAlloc);
}
// Create command pool
m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
// Create command buffer
{
const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
const VkDeviceSize vertexBufferOffset = 0;
m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
beginRenderPass(m_vkd, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
m_vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
// Draw quads. Switch sampler or image view depending on the test.
vector<VkSampler> samplers;
vector<VkImageView> imageViews;
samplers.push_back(*m_whiteBorderSampler);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
{
// Vary sampler between draws
samplers.push_back(*m_blackBorderSampler);
}
else
{
// Usa a single sampler
samplers.push_back(*m_whiteBorderSampler);
}
imageViews.push_back(**m_textureViews[0]);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
{
// Vary image view between draws
imageViews.push_back(**m_textureViews[1]);
}
else
{
// Usa a single image view
imageViews.push_back(**m_textureViews[0]);
}
for (deUint32 quadNdx = 0; quadNdx < m_params.numCalls; quadNdx++)
{
VkDescriptorImageInfo descriptorImageInfo =
{
samplers[quadNdx], // VkSampler sampler;
imageViews[quadNdx], // VkImageView imageView;
textureImageLayout // VkImageLayout imageLayout;
};
VkWriteDescriptorSet writeDescriptorSet =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkDescriptorSet dstSet;
m_params.binding, // uint32_t dstBinding;
0u, // uint32_t dstArrayElement;
1u, // uint32_t descriptorCount;
m_params.descriptorType, // VkDescriptorType descriptorType;
&descriptorImageInfo, // const VkDescriptorImageInfo* pImageInfo;
DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo;
DE_NULL // const VkBufferView* pTexelBufferView;
};
vector<VkWriteDescriptorSet> writeDescriptorSets;
writeDescriptorSets.push_back(writeDescriptorSet);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
{
// Sampler also needs an image.
writeDescriptorSet.dstBinding++;
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
writeDescriptorSets.push_back(writeDescriptorSet);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
{
// Image also needs a sampler.
writeDescriptorSet.dstBinding++;
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
writeDescriptorSets.push_back(writeDescriptorSet);
}
m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, (deUint32)writeDescriptorSets.size(), writeDescriptorSets.data());
m_vkd.cmdDraw(*m_cmdBuffer, 6, 1, 6 * quadNdx, 0);
}
endRenderPass(m_vkd, *m_cmdBuffer);
endCommandBuffer(m_vkd, *m_cmdBuffer);
}
}
PushDescriptorImageGraphicsTestInstance::~PushDescriptorImageGraphicsTestInstance (void)
{
}
tcu::TestStatus PushDescriptorImageGraphicsTestInstance::iterate (void)
{
init();
submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
return verifyImage();
}
tcu::TestStatus PushDescriptorImageGraphicsTestInstance::verifyImage (void)
{
const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
const ColorVertexShader vertexShader;
const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat);
const rr::Program program (&vertexShader, &fragmentShader);
ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
bool compareOk = false;
// Render reference image
{
vector<Vertex4RGBA> refQuadsOuter = createQuads(m_params.numCalls, 0.25f);
vector<Vertex4RGBA> refQuadsInner = createQuads(m_params.numCalls, 0.25f * 0.8f);
tcu::Vec4 outerColor[2];
tcu::Vec4 innerColor[2];
const bool hasBorder = m_params.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
if (hasBorder)
{
outerColor[0] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
innerColor[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
outerColor[1] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
else
outerColor[1] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
innerColor[1] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
else
innerColor[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
else
{
outerColor[0] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
outerColor[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
for (deUint32 quadIdx = 0; quadIdx < m_params.numCalls; quadIdx++)
for (deUint32 vertexIdx = 0; vertexIdx < 6; vertexIdx++)
{
const deUint32 idx = quadIdx * 6 + vertexIdx;
refQuadsOuter[idx].color.xyzw() = outerColor[quadIdx];
refQuadsInner[idx].color.xyzw() = innerColor[quadIdx];
}
if (hasBorder)
refQuadsOuter.insert(refQuadsOuter.end(), refQuadsInner.begin(), refQuadsInner.end());
refRenderer.draw(rr::RenderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits),
rr::PRIMITIVETYPE_TRIANGLES, refQuadsOuter);
}
// Compare result with reference image
{
de::MovePtr<tcu::TextureLevel> result = readColorAttachment(m_vkd, *m_device, m_queue, m_queueFamilyIndex, m_allocator, *m_colorImage, m_colorFormat, m_renderSize);
compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
"IntImageCompare",
"Image comparison",
refRenderer.getAccess(),
result->getAccess(),
tcu::UVec4(2, 2, 2, 2),
tcu::IVec3(1, 1, 0),
true,
tcu::COMPARE_LOG_RESULT);
}
if (compareOk)
return tcu::TestStatus::pass("Result image matches reference");
else
return tcu::TestStatus::fail("Image mismatch");
}
class PushDescriptorImageGraphicsTest : public vkt::TestCase
{
public:
PushDescriptorImageGraphicsTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params);
~PushDescriptorImageGraphicsTest (void);
void initPrograms (SourceCollections& sourceCollections) const;
TestInstance* createInstance (Context& context) const;
protected:
const TestParams m_params;
};
PushDescriptorImageGraphicsTest::PushDescriptorImageGraphicsTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params)
: vkt::TestCase (testContext, name, description)
, m_params (params)
{
}
PushDescriptorImageGraphicsTest::~PushDescriptorImageGraphicsTest (void)
{
}
TestInstance* PushDescriptorImageGraphicsTest::createInstance (Context& context) const
{
return new PushDescriptorImageGraphicsTestInstance(context, m_params);
}
void PushDescriptorImageGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
{
const string vertexSrc =
"#version 450\n"
"layout(location = 0) in highp vec4 position;\n"
"layout(location = 1) in highp vec4 texcoordVtx;\n"
"layout(location = 0) out highp vec2 texcoordFrag;\n"
"\n"
"out gl_PerVertex { vec4 gl_Position; };\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
" texcoordFrag = texcoordVtx.xy;\n"
"}\n";
sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
{
const string fragmentSrc =
"#version 450\n"
"layout(location = 0) in highp vec2 texcoordFrag;\n"
"layout(location = 0) out highp vec4 fragColor;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler2D combinedSampler;\n"
"\n"
"void main (void)\n"
"{\n"
" fragColor = texture(combinedSampler, texcoordFrag);\n"
"}\n";
sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
{
const string fragmentSrc =
"#version 450\n"
"layout(location = 0) in highp vec2 texcoordFrag;\n"
"layout(location = 0) out highp vec4 fragColor;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler texSampler;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform texture2D texImage;\n"
"\n"
"void main (void)\n"
"{\n"
" fragColor = texture(sampler2D(texImage, texSampler), texcoordFrag);\n"
"}\n";
sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
{
const string fragmentSrc =
"#version 450\n"
"layout(location = 0) in highp vec2 texcoordFrag;\n"
"layout(location = 0) out highp vec4 fragColor;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform sampler texSampler;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform texture2D texImage;\n"
"\n"
"void main (void)\n"
"{\n"
" fragColor = texture(sampler2D(texImage, texSampler), texcoordFrag);\n"
"}\n";
sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
{
const string fragmentSrc =
"#version 450\n"
"layout(location = 0) in highp vec2 texcoordFrag;\n"
"layout(location = 0) out highp vec4 fragColor;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ", rgba8) uniform readonly image2D storageImage;\n"
"\n"
"void main (void)\n"
"{\n"
" fragColor = imageLoad(storageImage, ivec2(0));\n"
"}\n";
sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragmentSrc);
}
else
{
DE_FATAL("Unexpected descriptor type");
}
}
class PushDescriptorImageComputeTestInstance : public vkt::TestInstance
{
public:
PushDescriptorImageComputeTestInstance (Context& context, const TestParams& params);
virtual ~PushDescriptorImageComputeTestInstance (void);
void init (void);
virtual tcu::TestStatus iterate (void);
tcu::TestStatus verifyOutput (void);
private:
const TestParams m_params;
const PlatformInterface& m_vkp;
const Extensions m_instanceExtensions;
const Unique<VkInstance> m_instance;
const InstanceDriver m_vki;
const VkPhysicalDevice m_physicalDevice;
const deUint32 m_queueFamilyIndex;
const Extensions m_deviceExtensions;
const Unique<VkDevice> m_device;
const DeviceDriver m_vkd;
const VkQueue m_queue;
SimpleAllocator m_allocator;
const tcu::UVec2 m_textureSize;
const VkFormat m_colorFormat;
Move<VkShaderModule> m_computeShaderModule;
vector<VkImageSp> m_textureImages;
vector<AllocationSp> m_textureImageAllocs;
vector<VkImageViewSp> m_textureViews;
Move<VkSampler> m_whiteBorderSampler;
Move<VkSampler> m_blackBorderSampler;
Move<VkBuffer> m_outputBuffer;
de::MovePtr<Allocation> m_outputBufferAlloc;
Move<VkDescriptorSetLayout> m_descriptorSetLayout;
Move<VkPipelineLayout> m_pipelineLayout;
Move<VkPipeline> m_computePipeline;
Move<VkCommandPool> m_cmdPool;
Move<VkCommandBuffer> m_cmdBuffer;
deUint32 m_outputBufferBinding;
};
PushDescriptorImageComputeTestInstance::PushDescriptorImageComputeTestInstance (Context& context, const TestParams& params)
: vkt::TestInstance (context)
, m_params (params)
, m_vkp (context.getPlatformInterface())
, m_instanceExtensions (enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
, m_instance (createInstanceWithGetPhysicalDeviceProperties2(context, m_vkp, m_instanceExtensions))
, m_vki (m_vkp, *m_instance)
, m_physicalDevice (chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
, m_queueFamilyIndex (findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT))
, m_deviceExtensions (enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
, m_device (createDeviceWithPushDescriptor(context, m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex))
, m_vkd (m_vkp, *m_instance, *m_device)
, m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
, m_allocator (m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
, m_textureSize (32, 32)
, m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
, m_outputBufferBinding (0)
{
}
void PushDescriptorImageComputeTestInstance::init (void)
{
const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
// Create texture images
for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
{
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
const VkImageCreateInfo textureImageParams =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_colorFormat, // VkFormat format;
{ m_textureSize.x(), m_textureSize.y(), 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
usageFlags, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&m_queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
m_textureImages.push_back(VkImageSp(new Unique<VkImage>(createImage(m_vkd, *m_device, &textureImageParams))));
// Allocate and bind texture image memory
m_textureImageAllocs.push_back(AllocationSp(m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, **m_textureImages.back()), MemoryRequirement::Any).release()));
VK_CHECK(m_vkd.bindImageMemory(*m_device, **m_textureImages.back(), m_textureImageAllocs.back()->getMemory(), m_textureImageAllocs.back()->getOffset()));
}
// Create texture image views
for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
{
const VkImageViewCreateInfo textureViewParams =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
**m_textureImages[texIdx], // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
m_colorFormat, // VkFormat format;
componentMappingRGBA, // VkChannelMapping channels;
{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
};
m_textureViews.push_back(VkImageViewSp(new Unique<VkImageView>(createImageView(m_vkd, *m_device, &textureViewParams))));
}
VkClearValue clearValues[2];
clearValues[0].color.float32[0] = 0.0f;
clearValues[0].color.float32[1] = 1.0f;
clearValues[0].color.float32[2] = 0.0f;
clearValues[0].color.float32[3] = 1.0f;
clearValues[1].color.float32[0] = 1.0f;
clearValues[1].color.float32[1] = 0.0f;
clearValues[1].color.float32[2] = 0.0f;
clearValues[1].color.float32[3] = 1.0f;
const VkImageLayout textureImageLayout = (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
// Clear textures
for (deUint32 texIdx = 0; texIdx < 2; texIdx++)
{
const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Move<VkCommandPool> cmdPool;
Move<VkCommandBuffer> cmdBuffer;
cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
const VkImageMemoryBarrier preImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkAccessFlags srcAccessMask;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
**m_textureImages[texIdx], // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
aspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
const VkImageMemoryBarrier postImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
textureImageLayout, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
**m_textureImages[texIdx], // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
aspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
const VkImageSubresourceRange clearRange =
{
aspectMask, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
1u, // deUint32 levelCount;
0u, // deUint32 baseArrayLayer;
1u // deUint32 layerCount;
};
beginCommandBuffer(m_vkd, *cmdBuffer);
m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
m_vkd.cmdClearColorImage(*cmdBuffer, **m_textureImages[texIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValues[texIdx].color, 1, &clearRange);
m_vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
endCommandBuffer(m_vkd, *cmdBuffer);
submitCommandsAndWait(m_vkd, *m_device, m_queue, cmdBuffer.get());
}
// Create samplers: one with white and one with black border color to have a visible effect on switching the sampler
{
VkSamplerCreateInfo samplerParams =
{
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkSamplerCreateFlags flags;
VK_FILTER_NEAREST, // VkFilter magFilter;
VK_FILTER_NEAREST, // VkFilter minFilter;
VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeU;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeV;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeW;
0.0f, // float mipLodBias;
VK_FALSE, // VkBool32 anisotropyEnable;
0.0f, // float maxAnisotropy;
VK_FALSE, // VkBool32 compareEnable;
VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
0.0f, // float minLod;
0.0f, // float maxLod;
VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, // VkBorderColor borderColor;
VK_FALSE // VkBool32 unnormalizedCoordinates;
};
m_whiteBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
samplerParams.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
m_blackBorderSampler = createSampler(m_vkd, *m_device, &samplerParams);
}
// Create pipeline layout
{
// Create descriptor set layout
vector<VkDescriptorSetLayoutBinding> layoutBindings;
switch(m_params.descriptorType)
{
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBinding);
m_outputBufferBinding = m_params.binding + 1;
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLER:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex =
{
m_params.binding + 1, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBindingSampler);
layoutBindings.push_back(descriptorSetLayoutBindingTex);
m_outputBufferBinding = m_params.binding + 2;
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingSampler =
{
m_params.binding + 1, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingTex =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBindingSampler);
layoutBindings.push_back(descriptorSetLayoutBindingTex);
m_outputBufferBinding = m_params.binding + 2;
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
{
m_params.binding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBinding);
m_outputBufferBinding = m_params.binding + 1;
}
break;
default:
DE_FATAL("unexpected descriptor type");
break;
};
const VkDescriptorSetLayoutBinding descriptorSetLayoutBindingOutputBuffer =
{
m_outputBufferBinding, // uint32_t binding;
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
DE_NULL // const VkSampler* pImmutableSamplers;
};
layoutBindings.push_back(descriptorSetLayoutBindingOutputBuffer);
const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // VkDescriptorSetLayoutCreateFlags flags;
(deUint32)layoutBindings.size(), // uint32_t bindingCount;
layoutBindings.data() // const VkDescriptorSetLayoutBinding* pBindings;
};
m_descriptorSetLayout = createDescriptorSetLayout(m_vkd, *m_device, &descriptorSetLayoutCreateInfo, DE_NULL);
// Create pipeline layout
const VkPipelineLayoutCreateInfo pipelineLayoutParams =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineLayoutCreateFlags flags;
1u, // deUint32 descriptorSetCount;
&(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
0u, // deUint32 pushConstantRangeCount;
DE_NULL // const VkPushDescriptorRange* pPushDescriptorRanges;
};
m_pipelineLayout = createPipelineLayout(m_vkd, *m_device, &pipelineLayoutParams);
}
// Create output buffer
{
const VkBufferCreateInfo bufferCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags
64u, // VkDeviceSize size;
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&m_queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_outputBuffer = createBuffer(m_vkd, *m_device, &bufferCreateInfo);
m_outputBufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, *m_outputBuffer), MemoryRequirement::HostVisible);
VK_CHECK(m_vkd.bindBufferMemory(*m_device, *m_outputBuffer, m_outputBufferAlloc->getMemory(), m_outputBufferAlloc->getOffset()));
}
// Create shader
{
m_computeShaderModule = createShaderModule(m_vkd, *m_device, m_context.getBinaryCollection().get("compute"), 0u);
}
// Create pipeline
{
const VkPipelineShaderStageCreateInfo stageCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineShaderStageCreateFlags flags;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
*m_computeShaderModule, // VkShaderModule module;
"main", // const char* pName;
DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
};
const VkComputePipelineCreateInfo createInfo =
{
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineCreateFlags flags;
stageCreateInfo, // VkPipelineShaderStageCreateInfo stage;
*m_pipelineLayout, // VkPipelineLayout layout;
(VkPipeline)0, // VkPipeline basePipelineHandle;
0u, // int32_t basePipelineIndex;
};
m_computePipeline = createComputePipeline(m_vkd, *m_device, (vk::VkPipelineCache)0u, &createInfo);
}
// Create command pool
m_cmdPool = createCommandPool(m_vkd, *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
// Create command buffer
{
m_cmdBuffer = allocateCommandBuffer(m_vkd, *m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
beginCommandBuffer(m_vkd, *m_cmdBuffer, 0u);
m_vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
// Dispatch: Each dispatch switches the input image.
// Output buffer is exposed as a 2 x vec4 sized window.
for (deUint32 dispatchNdx = 0; dispatchNdx < m_params.numCalls; dispatchNdx++)
{
vector<VkSampler> samplers;
vector<VkImageView> imageViews;
samplers.push_back(*m_whiteBorderSampler);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
{
// Vary sampler between draws
samplers.push_back(*m_blackBorderSampler);
}
else
{
// Usa a single sampler
samplers.push_back(*m_whiteBorderSampler);
}
imageViews.push_back(**m_textureViews[0]);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
{
// Vary image view between draws
imageViews.push_back(**m_textureViews[1]);
}
else
{
// Usa a single image view
imageViews.push_back(**m_textureViews[0]);
}
const VkDescriptorImageInfo descriptorImageInfo =
{
samplers[dispatchNdx], // VkSampler sampler;
imageViews[dispatchNdx], // VkImageView imageView;
textureImageLayout // VkImageLayout imageLayout;
};
VkWriteDescriptorSet writeDescriptorSet =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkDescriptorSet dstSet;
m_params.binding, // uint32_t dstBinding;
0u, // uint32_t dstArrayElement;
1u, // uint32_t descriptorCount;
m_params.descriptorType, // VkDescriptorType descriptorType;
&descriptorImageInfo, // const VkDescriptorImageInfo* pImageInfo;
DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo;
DE_NULL // const VkBufferView* pTexelBufferView;
};
vector<VkWriteDescriptorSet> writeDescriptorSets;
writeDescriptorSets.push_back(writeDescriptorSet);
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
{
// Sampler also needs an image.
writeDescriptorSet.dstBinding++;
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
writeDescriptorSets.push_back(writeDescriptorSet);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
{
// Image also needs a sampler.
writeDescriptorSet.dstBinding++;
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
writeDescriptorSets.push_back(writeDescriptorSet);
}
const VkDescriptorBufferInfo descriptorBufferInfoOutput =
{
*m_outputBuffer, // VkBuffer buffer;
32u * dispatchNdx, // VkDeviceSize offset;
32u // VkDeviceSize range;
};
// Write output buffer descriptor set
const VkWriteDescriptorSet writeDescriptorSetOutput =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkDescriptorSet dstSet;
m_outputBufferBinding, // uint32_t dstBinding;
0u, // uint32_t dstArrayElement;
1u, // uint32_t descriptorCount;
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
DE_NULL, // const VkDescriptorImageInfo* pImageInfo;
&descriptorBufferInfoOutput, // const VkDescriptorBufferInfo* pBufferInfo;
DE_NULL // const VkBufferView* pTexelBufferView;
};
writeDescriptorSets.push_back(writeDescriptorSetOutput);
m_vkd.cmdPushDescriptorSetKHR(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, (deUint32)writeDescriptorSets.size(), writeDescriptorSets.data());
m_vkd.cmdDispatch(*m_cmdBuffer, 1, 1, 1);
}
endCommandBuffer(m_vkd, *m_cmdBuffer);
}
}
PushDescriptorImageComputeTestInstance::~PushDescriptorImageComputeTestInstance (void)
{
}
tcu::TestStatus PushDescriptorImageComputeTestInstance::iterate (void)
{
init();
submitCommandsAndWait(m_vkd, *m_device, m_queue, m_cmdBuffer.get());
return verifyOutput();
}
tcu::TestStatus PushDescriptorImageComputeTestInstance::verifyOutput (void)
{
float ref[16];
invalidateAlloc(m_vkd, *m_device, *m_outputBufferAlloc);
switch(m_params.descriptorType)
{
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
// Dispatch 1: inner & outer = green
ref[0] = ref[4] = 0.0f;
ref[1] = ref[5] = 1.0f;
ref[2] = ref[6] = 0.0f;
ref[3] = ref[7] = 1.0f;
// Dispatch 2: inner & outer = red
ref[8] = ref[12] = 1.0f;
ref[9] = ref[13] = 0.0f;
ref[10] = ref[14] = 0.0f;
ref[11] = ref[15] = 1.0f;
break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
// Dispatch 1: inner = green, outer = white
ref[0] = 0.0f;
ref[1] = 1.0f;
ref[2] = 0.0f;
ref[3] = 1.0f;
ref[4] = 1.0f;
ref[5] = 1.0f;
ref[6] = 1.0f;
ref[7] = 1.0f;
// Dispatch 2: inner = red, outer = black
ref[8] = 1.0f;
ref[9] = 0.0f;
ref[10] = 0.0f;
ref[11] = 1.0f;
ref[12] = 0.0f;
ref[13] = 0.0f;
ref[14] = 0.0f;
ref[15] = 1.0f;
break;
case VK_DESCRIPTOR_TYPE_SAMPLER:
// Dispatch 1: inner = green, outer = white
ref[0] = 0.0f;
ref[1] = 1.0f;
ref[2] = 0.0f;
ref[3] = 1.0f;
ref[4] = 1.0f;
ref[5] = 1.0f;
ref[6] = 1.0f;
ref[7] = 1.0f;
// Dispatch 2: inner = green, outer = black
ref[8] = 0.0f;
ref[9] = 1.0f;
ref[10] = 0.0f;
ref[11] = 1.0f;
ref[12] = 0.0f;
ref[13] = 0.0f;
ref[14] = 0.0f;
ref[15] = 1.0f;
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
// Dispatch 1: inner = green, outer = white
ref[0] = 0.0f;
ref[1] = 1.0f;
ref[2] = 0.0f;
ref[3] = 1.0f;
ref[4] = 1.0f;
ref[5] = 1.0f;
ref[6] = 1.0f;
ref[7] = 1.0f;
// Dispatch 2: inner = red, outer = white
ref[8] = 1.0f;
ref[9] = 0.0f;
ref[10] = 0.0f;
ref[11] = 1.0f;
ref[12] = 1.0f;
ref[13] = 1.0f;
ref[14] = 1.0f;
ref[15] = 1.0f;
break;
default:
DE_FATAL("unexpected descriptor type");
break;
};
// Verify result
if (deMemCmp((void*)ref, m_outputBufferAlloc->getHostPtr(), (size_t)(32u * m_params.numCalls)))
{
const float* ptr = (float*)m_outputBufferAlloc->getHostPtr();
std::string debugMsg = "Output buffer contents:\n";
for (deUint32 i = 0; i < m_params.numCalls * 8; i++)
debugMsg += de::toString(ptr[i]) + " vs " + de::toString(ref[i]) + "\n";
m_context.getTestContext().getLog() << tcu::TestLog::Message << debugMsg << tcu::TestLog::EndMessage;
return tcu::TestStatus::fail("Output mismatch");
}
return tcu::TestStatus::pass("Output matches expected values");
}
class PushDescriptorImageComputeTest : public vkt::TestCase
{
public:
PushDescriptorImageComputeTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params);
~PushDescriptorImageComputeTest (void);
void initPrograms (SourceCollections& sourceCollections) const;
TestInstance* createInstance (Context& context) const;
protected:
const TestParams m_params;
};
PushDescriptorImageComputeTest::PushDescriptorImageComputeTest (tcu::TestContext& testContext,
const string& name,
const string& description,
const TestParams& params)
: vkt::TestCase (testContext, name, description)
, m_params (params)
{
}
PushDescriptorImageComputeTest::~PushDescriptorImageComputeTest (void)
{
}
TestInstance* PushDescriptorImageComputeTest::createInstance (Context& context) const
{
return new PushDescriptorImageComputeTestInstance(context, m_params);
}
void PushDescriptorImageComputeTest::initPrograms (SourceCollections& sourceCollections) const
{
if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
{
const string computeSrc =
"#version 450\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler2D combinedSampler;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
"{\n"
" vec4 innerColor;\n"
" vec4 outerColor;\n"
"} outData;\n"
"\n"
"void main()\n"
"{\n"
" outData.innerColor = texture(combinedSampler, vec2(0.5));\n"
" outData.outerColor = texture(combinedSampler, vec2(-0.1));\n"
"}\n";
sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
{
const string computeSrc =
"#version 450\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform sampler texSampler;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform texture2D texImage;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 2) + ") writeonly buffer Output\n"
"{\n"
" vec4 innerColor;\n"
" vec4 outerColor;\n"
"} outData;\n"
"\n"
"void main()\n"
"{\n"
" outData.innerColor = texture(sampler2D(texImage, texSampler), vec2(0.5));\n"
" outData.outerColor = texture(sampler2D(texImage, texSampler), vec2(-0.1));\n"
"}\n";
sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
{
const string computeSrc =
"#version 450\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") uniform sampler texSampler;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ") uniform texture2D texImage;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 2) + ") writeonly buffer Output\n"
"{\n"
" vec4 innerColor;\n"
" vec4 outerColor;\n"
"} outData;\n"
"\n"
"void main()\n"
"{\n"
" outData.innerColor = texture(sampler2D(texImage, texSampler), vec2(0.5));\n"
" outData.outerColor = texture(sampler2D(texImage, texSampler), vec2(-0.1));\n"
"}\n";
sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
}
else if (m_params.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
{
const string computeSrc =
"#version 450\n"
"layout(set = 0, binding = " + de::toString(m_params.binding) + ", rgba8) uniform readonly image2D storageImage;\n"
"layout(set = 0, binding = " + de::toString(m_params.binding + 1) + ") writeonly buffer Output\n"
"{\n"
" vec4 innerColor;\n"
" vec4 outerColor;\n"
"} outData;\n"
"\n"
"void main()\n"
"{\n"
" outData.innerColor = imageLoad(storageImage, ivec2(0));\n"
" outData.outerColor = imageLoad(storageImage, ivec2(0));\n"
"}\n";
sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc);
}
else
{
DE_FATAL("Unexpected descriptor type");
}
}
class PushDescriptorTexelBufferGraphicsTestInstance : public vkt::TestInstance
{
public:
PushDescriptorTexelBufferGraphicsTestInstance (Context& context, const TestParams& params);
virtual ~PushDescriptorTexelBufferGraphicsTestInstance (void);
void init (void);
virtual tcu::TestStatus iterate (void);
tcu::TestStatus verifyImage (void);
private:
const TestParams m_params;
const PlatformInterface& m_vkp;
const Extensions m_instanceExtensions;
const Unique<VkInstance> m_instance;
const InstanceDriver m_vki;
const VkPhysicalDevice m_physicalDevice;
const deUint32 m_queueFamilyIndex;
const Extensions m_deviceExtensions;
const Unique<VkDevice> m_device;
const DeviceDriver m_vkd;
const VkQueue m_queue;
SimpleAllocator m_allocator;
const tcu::UVec2 m_renderSize;
const VkFormat m_colorFormat;
Move<VkImage> m_colorImage;
de::MovePtr<Allocation> m_colorImageAlloc;
Move<VkImageView> m_colorAttachmentView;
vector<VkBufferSp> m_buffers;
vector<AllocationSp> m_bufferAllocs;
vector<VkBufferViewSp> m_bufferViews;
const VkFormat m_bufferFormat;
Move<VkRenderPass> m_renderPass;
Move<VkFramebuffer> m_framebuffer;
Move<VkShaderModule> m_vertexShaderModule;
Move<VkShaderModule> m_fragmentShaderModule;
Move<VkBuffer> m_vertexBuffer;
de::MovePtr<Allocation> m_vertexBufferAlloc;
Move<VkDescriptorSetLayout> m_descriptorSetLayout;
Move<VkPipelineLayout> m_pipelineLayout;
Move<VkPipeline> m_graphicsPipelines;
Move<VkCommandPool> m_cmdPool;
Move<VkCommandBuffer> m_cmdBuffer;
vector<Vertex4RGBA> m_vertices;
};
PushDescriptorTexelBufferGraphicsTestInstance::PushDescriptorTexelBufferGraphicsTestInstance (Context& context, const TestParams& params)
: vkt::TestInstance (context)
, m_params (params)
, m_vkp (context.getPlatformInterface())
, m_instanceExtensions (enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
, m_instance (createInstanceWithGetPhysicalDeviceProperties2(context, m_vkp, m_instanceExtensions))
, m_vki (m_vkp, *m_instance)
, m_physicalDevice (chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
, m_queueFamilyIndex (findQueueFamilyIndexWithCaps(m_vki, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT))
, m_deviceExtensions (enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
, m_device (createDeviceWithPushDescriptor(context, m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex))
, m_vkd (m_vkp, *m_instance, *m_device)
, m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
, m_allocator (m_vkd, *m_device, getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice))
, m_renderSize (32, 32)
, m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
, m_bufferFormat (VK_FORMAT_R32G32B32A32_SFLOAT)
, m_vertices (createQuads(params.numCalls, 0.25f))
{
}
void PushDescriptorTexelBufferGraphicsTestInstance::init (void)
{
const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
// Create color image
{
const VkImageCreateInfo colorImageParams =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_colorFormat, // VkFormat format;
{ m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&m_queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
m_colorImage = createImage(m_vkd, *m_device, &colorImageParams);
// Allocate and bind color image memory
m_colorImageAlloc = m_allocator.allocate(getImageMemoryRequirements(m_vkd, *m_device, *m_colorImage), MemoryRequirement::Any);
VK_CHECK(m_vkd.bindImageMemory(*m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
}
// Create color attachment view
{
const VkImageViewCreateInfo colorAttachmentViewParams =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
*m_colorImage, // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
m_colorFormat, // VkFormat format;
componentMappingRGBA, // VkChannelMapping channels;
{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
};
m_colorAttachmentView = createImageView(m_vkd, *m_device, &colorAttachmentViewParams);
}
// Create buffers
for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
{
const VkBufferUsageFlags usageFlags = m_params.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
const VkBufferCreateInfo bufferCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags
16u, // VkDeviceSize size;
usageFlags, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&m_queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_buffers.push_back(VkBufferSp(new Unique<VkBuffer>(createBuffer(m_vkd, *m_device, &bufferCreateInfo))));
m_bufferAllocs.push_back(AllocationSp(m_allocator.allocate(getBufferMemoryRequirements(m_vkd, *m_device, **m_buffers[bufIdx]), MemoryRequirement::HostVisible).release()));
VK_CHECK(m_vkd.bindBufferMemory(*m_device, **m_buffers[bufIdx], m_bufferAllocs[bufIdx]->getMemory(), m_bufferAllocs[bufIdx]->getOffset()));
deMemcpy(m_bufferAllocs[bufIdx]->getHostPtr(), &defaultTestColors[bufIdx], 16u);
flushAlloc(m_vkd, *m_device, *m_bufferAllocs[bufIdx]);
}
// Create buffer views
for (deUint32 bufIdx = 0; bufIdx < DE_LENGTH_OF_ARRAY(defaultTestColors); bufIdx++)
{
const VkBufferViewCreateInfo bufferViewParams =
{
VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferViewCreateFlags flags;
**m_buffers[bufIdx], // VkBuffer buffer;
m_bufferFormat, // VkFormat format;
0u, // VkDeviceSize offset;
VK_WHOLE_SIZE // VkDeviceSize range;
};
m_bufferViews.push_back(VkBufferViewSp(new Unique<VkBufferView>(createBufferView(m_vkd, *m_device, &bufferViewParams))));
}
// Create render pass
m_renderPass = makeRenderPass(m_vkd, *m_device, m_colorFormat);
// Create framebuffer
{
const VkImageView attachmentBindInfos[] =
{
*m_colorAttachmentView
};
const VkFramebufferCreateInfo framebufferParams =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkFramebufferCreateFlags flags;
*m_renderPass, // VkRenderPass renderPass;
1u, // deUint32 attachmentCount;
attachmentBindInfos, // const VkImageView* pAttachments;
(deUint32)m_renderSize.x(), // deUint32 width;
(deUint32)m_renderSize.y(), // deUint32 height;
1u // deUint32 layers;
};
m_framebuffer = createFramebuffer(m_vkd, *m_device, &framebufferParams);
}
// Create pipeline layout
{
const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
{
m_params.binding, // uint32_t binding;
m_params.descriptorType, // VkDescriptorType descriptorType;
1u, // uint32_t descriptorCount;
VK_SHADER_STAGE_FRA