blob: 1766a00c5b88f9e09ffcccb800efdf81a1f333ad [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2020 The Khronos Group Inc.
* Copyright (c) 2020 Valve Corporation
*
* 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 VK_AMD_shader_explicit_vertex_parameter tests
*//*--------------------------------------------------------------------*/
#include "vktDrawExplicitVertexParameterTests.hpp"
#include "vktDrawBaseClass.hpp"
#include "vkQueryUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkTypeUtil.hpp"
#include "deDefs.h"
#include "deRandom.hpp"
#include "deString.h"
#include "deMath.h"
#include "tcuTestCase.hpp"
#include "tcuRGBA.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuStringTemplate.hpp"
#include "rrRenderer.hpp"
#include <string>
#include <sstream>
namespace vkt
{
namespace Draw
{
namespace
{
using namespace vk;
using namespace std;
enum Interpolation
{
SMOOTH = 0,
NOPERSPECTIVE = 1,
};
enum AuxiliaryQualifier
{
AUX_NONE = 0,
AUX_CENTROID = 1,
AUX_SAMPLE = 2,
};
enum
{
WIDTH = 16,
HEIGHT = 16
};
struct PositionValueVertex {
PositionValueVertex(tcu::Vec4 pos, float val)
: position(pos)
, value(val)
{}
public:
tcu::Vec4 position;
float value;
};
struct DrawParams
{
Interpolation interpolation;
vk::VkSampleCountFlagBits samples;
AuxiliaryQualifier auxiliaryStorage;
};
const char* interpolationToString (Interpolation interpolation)
{
switch (interpolation)
{
case SMOOTH:
return "smooth";
case NOPERSPECTIVE:
return "noperspective";
default:
DE_FATAL("Invalid interpolation enum");
}
return "";
}
std::string barycentricVariableString (Interpolation interpolation, AuxiliaryQualifier aux)
{
std::ostringstream name;
name << "gl_BaryCoord";
switch (interpolation)
{
case SMOOTH:
name << "Smooth";
break;
case NOPERSPECTIVE:
name << "NoPersp";
break;
default:
DE_FATAL("Invalid interpolation enum");
}
switch (aux)
{
case AUX_CENTROID:
name << "Centroid";
break;
case AUX_SAMPLE:
name << "Sample";
break;
case AUX_NONE:
name << "";
break;
default:
DE_FATAL("Invalid auxiliary storage qualifier enum");
}
name << "AMD";
return name.str();
}
const char* auxiliaryQualifierToString (AuxiliaryQualifier aux)
{
switch (aux)
{
case AUX_CENTROID:
return "centroid";
case AUX_SAMPLE:
return "sample";
case AUX_NONE:
return "";
default:
DE_FATAL("Invalid auxiliary storage qualifier enum");
}
return "";
}
std::string getTestName (DrawParams params)
{
std::ostringstream name;
name << interpolationToString(params.interpolation) << "_";
if (params.auxiliaryStorage != AUX_NONE)
name << auxiliaryQualifierToString(params.auxiliaryStorage) << "_";
name << "samples_" << de::toString(params.samples);
return name.str();
}
class DrawTestInstance : public TestInstance
{
public:
DrawTestInstance (Context& context, const DrawParams& data);
~DrawTestInstance (void);
tcu::TestStatus iterate (void);
private:
DrawParams m_data;
};
DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data)
: vkt::TestInstance (context)
, m_data (data)
{
}
DrawTestInstance::~DrawTestInstance (void)
{
}
class DrawTestCase : public TestCase
{
public:
DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data);
~DrawTestCase (void);
virtual void initPrograms (SourceCollections& programCollection) const;
virtual TestInstance* createInstance (Context& context) const;
virtual void checkSupport (Context& context) const;
private:
DrawParams m_data;
};
DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data)
: vkt::TestCase (context, name, desc)
, m_data (data)
{
}
DrawTestCase::~DrawTestCase (void)
{
}
void DrawTestCase::checkSupport(Context &context) const
{
context.requireDeviceFunctionality("VK_AMD_shader_explicit_vertex_parameter");
if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & m_data.samples) == 0)
TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
}
void DrawTestCase::initPrograms (SourceCollections& programCollection) const
{
const deUint32 numValues = WIDTH * HEIGHT * m_data.samples;
const tcu::StringTemplate vertShader (string(
"#version 450\n"
"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
"\n"
"layout(location = 0) in vec4 in_position;\n"
"layout(location = 1) in float in_data;\n"
"layout(location = 0) __explicitInterpAMD out float out_data_explicit;\n"
"layout(location = 1) ${auxqualifier} ${qualifier} out float out_data_${qualifier};\n"
"\n"
"out gl_PerVertex {\n"
" vec4 gl_Position;\n"
" float gl_PointSize;\n"
"};\n"
"\n"
"void main() {\n"
" gl_PointSize = 1.0;\n"
" gl_Position = in_position;\n"
" out_data_explicit = in_data;\n"
" out_data_${qualifier} = in_data;\n"
"}\n"));
const tcu::StringTemplate fragShader (string(
"#version 450\n"
"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
"\n"
"layout(location = 0) __explicitInterpAMD in float in_data_explicit;\n"
"layout(location = 1) ${auxqualifier} ${qualifier} in float in_data_${qualifier};\n"
"layout(location = 0) out vec4 out_color;\n"
"layout (binding = 0, std140) writeonly buffer Output {\n"
" vec4 values [${numValues}];\n"
"} sb_out;\n"
"\n"
"void main()\n"
"{\n"
" uint index = (uint(gl_FragCoord.y) * ${width} * ${samples}) + uint(gl_FragCoord.x) * ${samples} + gl_SampleID;\n"
" // Barycentric coodinates (I, J, K)\n"
" vec3 bary_coord = vec3(${barycoord}.x, ${barycoord}.y, 1.0f - ${barycoord}.x - ${barycoord}.y);\n"
"\n"
" // Vertex 0 -> (I = 0, J = 0, K = 1)\n"
" float data0 = interpolateAtVertexAMD(in_data_explicit, 0);\n"
" // Vertex 1 -> (I = 1, J = 0, K = 0)\n"
" float data1 = interpolateAtVertexAMD(in_data_explicit, 1);\n"
" // Vertex 1 -> (I = 0, J = 1, K = 0)\n"
" float data2 = interpolateAtVertexAMD(in_data_explicit, 2);\n"
" // Match data component with barycentric coordinate\n"
" vec3 data = vec3(data1, data2, data0);\n"
"\n"
" float res = (bary_coord.x * data.x) + (bary_coord.y * data.y) + (bary_coord.z * data.z);\n"
" float expected = in_data_${qualifier};\n"
"\n"
" sb_out.values[ index ] = vec4(expected, res, 0u, 0u);\n"
"\n"
" const float threshold = 0.0005f;\n"
" if (abs(res - expected) < threshold)\n"
" out_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
" else\n"
" out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
"}\n"));
map<string, string> attributes;
attributes["width"] = de::toString(WIDTH);
attributes["numValues"] = de::toString(numValues * m_data.samples);
attributes["qualifier"] = interpolationToString(m_data.interpolation);
attributes["auxqualifier"] = auxiliaryQualifierToString(m_data.auxiliaryStorage);
attributes["barycoord"] = barycentricVariableString(m_data.interpolation, m_data.auxiliaryStorage);
attributes["samples"] = de::toString(m_data.samples);
programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
}
TestInstance* DrawTestCase::createInstance (Context& context) const
{
return new DrawTestInstance(context, m_data);
}
tcu::TestStatus DrawTestInstance::iterate (void)
{
de::SharedPtr<Image> colorTargetImage;
de::SharedPtr<Image> multisampleTargetImage;
tcu::TestLog &log = m_context.getTestContext().getLog();
// Run two iterations with shaders that have different interpolation decorations. Images should still match.
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice device = m_context.getDevice();
const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
const Unique<VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
const Unique<VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
de::SharedPtr<Buffer> vertexBuffer;
de::SharedPtr<Buffer> ssboBuffer;
Move<VkRenderPass> renderPass;
Move<VkImageView> colorTargetView;
Move<VkImageView> multisampleTargetView;
Move<VkFramebuffer> framebuffer;
Move<VkPipeline> pipeline;
Move<VkPipelineLayout> pipelineLayout;
Move<VkDescriptorPool> descriptorPool;
Move<VkDescriptorSet> descriptorSet;
Move<VkDescriptorSetLayout> descriptorSetLayout;
vk::VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
const deUint32 numValues = WIDTH * HEIGHT * m_data.samples;
const deBool useMultisampling = m_data.samples != VK_SAMPLE_COUNT_1_BIT;
// Create color buffer images.
{
const VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
if (useMultisampling)
{
const ImageCreateInfo multisampleTargetImageCreateInfo (VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, m_data.samples,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
multisampleTargetImage = Image::createAndAlloc(vk, device, multisampleTargetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
}
}
// Create render pass and frame buffer.
{
const ImageViewCreateInfo colorTargetViewInfo (colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, imageFormat);
colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
RenderPassCreateInfo renderPassCreateInfo;
renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL));
const VkAttachmentReference colorAttachmentRef = { 0u, VK_IMAGE_LAYOUT_GENERAL };
const VkAttachmentReference multisampleAttachmentRef = { 1u, VK_IMAGE_LAYOUT_GENERAL };
vector<VkImageView> colorAttachments;
colorAttachments.push_back(*colorTargetView);
if (useMultisampling)
{
const ImageViewCreateInfo multisamplingTargetViewInfo (multisampleTargetImage->object(),
vk::VK_IMAGE_VIEW_TYPE_2D,
imageFormat);
multisampleTargetView = createImageView(vk, device, &multisamplingTargetViewInfo);
colorAttachments.push_back(*multisampleTargetView);
renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
m_data.samples,
vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
vk::VK_ATTACHMENT_STORE_OP_STORE,
vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
vk::VK_IMAGE_LAYOUT_UNDEFINED,
vk::VK_IMAGE_LAYOUT_GENERAL));
}
renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
0,
0,
DE_NULL,
1u,
useMultisampling ? &multisampleAttachmentRef : &colorAttachmentRef,
useMultisampling ? &colorAttachmentRef : DE_NULL,
AttachmentReference(),
0,
DE_NULL));
renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
const FramebufferCreateInfo framebufferCreateInfo (*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
}
// Create vertex buffer.
{
const PositionValueVertex vertices[] =
{
PositionValueVertex(
tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f), // Coord
float(1.0f)), // Value
PositionValueVertex(
tcu::Vec4(-1.0f, -1.0f, 0.25f, 0.75f), // Coord
float(0.0f)), // Value
PositionValueVertex(
tcu::Vec4( 1.0f, 1.0f, 0.0f, 2.0f), // Coord
float(0.5f)), // Value
PositionValueVertex(
tcu::Vec4( 1.0f, -1.0f, 1.0f, 0.5f), // Coord
float(1.0f)), // Value
};
const VkDeviceSize dataSize = DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionValueVertex);
vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
}
// Create SSBO buffer
{
const VkDeviceSize dataSize = sizeof(tcu::Vec4) * numValues;
ssboBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
deUint8* ptr = reinterpret_cast<deUint8*>(ssboBuffer->getBoundMemory().getHostPtr());
deMemset(ptr, 0, static_cast<size_t>(dataSize));
flushMappedMemoryRange(vk, device, ssboBuffer->getBoundMemory().getMemory(), ssboBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
}
// Create Descriptor Set layout
{
descriptorSetLayout = DescriptorSetLayoutBuilder()
.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
.build(vk, device);
}
// Create Descriptor Set
{
descriptorPool = DescriptorPoolBuilder()
.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
const VkDescriptorBufferInfo bufferInfo =
{
ssboBuffer->object(), // VkBuffer buffer;
0u, // VkDeviceSize offset;
VK_WHOLE_SIZE // VkDeviceSize range;
};
DescriptorSetUpdateBuilder()
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
.update(vk, device);
}
// Create pipeline
{
const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
VkViewport viewport = makeViewport(WIDTH, HEIGHT);
VkRect2D scissor = makeRect2D(WIDTH, HEIGHT);
const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)(sizeof(tcu::Vec4) + sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX };
const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
{
{ 0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
{ 1u, 0u, vk::VK_FORMAT_R32_SFLOAT, (deUint32)(sizeof(float)* 4) }
};
PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
pipelineLayout = makePipelineLayout (vk, device, *descriptorSetLayout);
PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_data.samples));
pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
}
// Queue draw and read results.
{
const VkQueue queue = m_context.getUniversalQueue();
const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT);
const VkDeviceSize vertexBufferOffset = 0;
const VkBuffer buffer = vertexBuffer->object();
vector<VkClearValue> clearColors;
clearColors.push_back(makeClearValueColor(clearColor));
if (useMultisampling)
clearColors.push_back(makeClearValueColor(clearColor));
beginCommandBuffer(vk, *cmdBuffer, 0u);
const VkRenderPassBeginInfo renderPassBeginInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*renderPass, // VkRenderPass renderPass;
*framebuffer, // VkFramebuffer framebuffer;
renderArea, // VkRect2D renderArea;
(deUint32)clearColors.size(), // deUint32 clearValueCount;
clearColors.data(), // const VkClearValue* pClearValues;
};
vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
endRenderPass(vk, *cmdBuffer);
endCommandBuffer(vk, *cmdBuffer);
submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
}
qpTestResult res = QP_TEST_RESULT_PASS;
{
const Allocation& resultAlloc = ssboBuffer->getBoundMemory();
invalidateAlloc(vk, device, resultAlloc);
const tcu::Vec4* ptr = reinterpret_cast<tcu::Vec4*>(resultAlloc.getHostPtr());
for (deUint32 valueNdx = 0u; valueNdx < numValues; valueNdx++)
{
if (deFloatAbs(ptr[valueNdx].x() - ptr[valueNdx].y()) > 0.0005f)
{
log << tcu::TestLog::Message << "Expected value " << valueNdx << " is " << ptr[valueNdx].x() << ", got " << ptr[valueNdx].y()
<< tcu::TestLog::EndMessage;
res = QP_TEST_RESULT_FAIL;
}
}
}
return tcu::TestStatus(res, qpGetTestResultName(res));
}
void createTests (tcu::TestCaseGroup* testGroup)
{
tcu::TestContext& testCtx = testGroup->getTestContext();
const VkSampleCountFlagBits samples[] =
{
VK_SAMPLE_COUNT_1_BIT,
VK_SAMPLE_COUNT_2_BIT,
VK_SAMPLE_COUNT_4_BIT,
VK_SAMPLE_COUNT_8_BIT,
VK_SAMPLE_COUNT_16_BIT,
VK_SAMPLE_COUNT_32_BIT,
VK_SAMPLE_COUNT_64_BIT,
};
const Interpolation interTypes[] =
{
SMOOTH,
NOPERSPECTIVE
};
const AuxiliaryQualifier auxQualifiers[] =
{
AUX_NONE,
AUX_SAMPLE,
AUX_CENTROID,
};
for (deUint32 sampleNdx = 0; sampleNdx < DE_LENGTH_OF_ARRAY(samples); sampleNdx++)
for (deUint32 auxNdx = 0; auxNdx < DE_LENGTH_OF_ARRAY(auxQualifiers); auxNdx++)
for (deUint32 interNdx = 0; interNdx < DE_LENGTH_OF_ARRAY(interTypes); interNdx++)
{
if (samples[sampleNdx] == VK_SAMPLE_COUNT_1_BIT && auxQualifiers[auxNdx] != AUX_NONE)
continue;
const DrawParams params =
{
interTypes[interNdx],
samples[sampleNdx],
auxQualifiers[auxNdx],
};
testGroup->addChild(new DrawTestCase(testCtx, getTestName(params).c_str(), "", params));
}
}
} // anonymous
tcu::TestCaseGroup* createExplicitVertexParameterTests (tcu::TestContext& testCtx)
{
return createTestGroup(testCtx, "explicit_vertex_parameter", "Tests for VK_AMD_shader_explicit_vertex_parameter.", createTests);
}
} // Draw
} // vkt