makeExtent2D(m_renderSize.x(), m_renderSize.y()),
};
+ const bool haveRenderSize = m_renderSize.x() > 0 && m_renderSize.y() > 0;
+
const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
1u, // uint32_t viewportCount;
- &viewport, // const VkViewport* pViewports;
+ haveRenderSize ? &viewport : DE_NULL, // const VkViewport* pViewports;
1u, // uint32_t scissorCount;
- &scissor, // const VkRect2D* pScissors;
+ haveRenderSize ? &scissor : DE_NULL, // const VkRect2D* pScissors;
};
const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
{ 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
};
+ std::vector<VkDynamicState> dynamicStates;
+ if (!haveRenderSize)
+ {
+ dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
+ dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
+ }
+
+ const VkPipelineDynamicStateCreateInfo pipelineDynamicStateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0, // VkPipelineDynamicStateCreateFlags flags;
+ static_cast<deUint32>(dynamicStates.size()), // uint32_t dynamicStateCount;
+ (dynamicStates.empty() ? DE_NULL : &dynamicStates[0]), // const VkDynamicState* pDynamicStates;
+ };
+
const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
{
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
(isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo), // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
(isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo), // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
(isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo), // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
- DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ &pipelineDynamicStateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
pipelineLayout, // VkPipelineLayout layout;
renderPass, // VkRenderPass renderPass;
0u, // deUint32 subpass;
namespace
{
-std::string getCaseName (const TessPrimitiveType primitiveType, const Winding winding)
+std::string getCaseName (const TessPrimitiveType primitiveType, const Winding winding, bool yFlip)
{
std::ostringstream str;
str << getTessPrimitiveTypeShaderName(primitiveType) << "_" << getWindingShaderName(winding);
+ if (yFlip)
+ str << "_yflip";
return str.str();
}
const tcu::ConstPixelBufferAccess image,
const TessPrimitiveType primitiveType,
const Winding winding,
+ bool yFlip,
const Winding frontFaceWinding)
{
const int totalNumPixels = image.getWidth()*image.getHeight();
return false;
}
- if (frontFaceWinding == winding)
+ if ((frontFaceWinding == winding) != yFlip)
{
if (primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
{
log << tcu::TestLog::Message << "Failure: wrong number of white pixels; expected approximately " << totalNumPixels/2 << tcu::TestLog::EndMessage;
return false;
}
+
+ // Check number of filled pixels (from left) in top and bottom rows to
+ // determine if triangle is in right orientation.
+ {
+ const tcu::IVec2 expectedStart (0, 1);
+ const tcu::IVec2 expectedEnd (image.getWidth()-1, image.getWidth());
+ const tcu::IVec2 expectedTop = yFlip ? expectedStart : expectedEnd;
+ const tcu::IVec2 expectedBottom = yFlip ? expectedEnd : expectedStart;
+ int numTopFilled = 0;
+ int numBottomFilled = 0;
+
+ for (int x = 0; x < image.getWidth(); ++x)
+ {
+ if (image.getPixel(x, 0) == white)
+ numTopFilled += 1;
+ else
+ break;
+ }
+
+ for (int x = 0; x < image.getWidth(); ++x)
+ {
+ if (image.getPixel(x, image.getHeight()-1) == white)
+ numBottomFilled += 1;
+ else
+ break;
+ }
+
+ if (!de::inBounds(numTopFilled, expectedTop[0], expectedTop[1]) ||
+ !de::inBounds(numBottomFilled, expectedBottom[0], expectedBottom[1]))
+ {
+ log << tcu::TestLog::Message << "Failure: triangle orientation is incorrect" << tcu::TestLog::EndMessage;
+ return false;
+ }
+ }
+
}
else if (primitiveType == TESSPRIMITIVETYPE_QUADS)
{
public:
WindingTest (tcu::TestContext& testCtx,
const TessPrimitiveType primitiveType,
- const Winding winding);
+ const Winding winding,
+ bool yFlip);
void initPrograms (SourceCollections& programCollection) const;
TestInstance* createInstance (Context& context) const;
private:
const TessPrimitiveType m_primitiveType;
const Winding m_winding;
+ const bool m_yFlip;
};
WindingTest::WindingTest (tcu::TestContext& testCtx,
const TessPrimitiveType primitiveType,
- const Winding winding)
- : TestCase (testCtx, getCaseName(primitiveType, winding), "")
+ const Winding winding,
+ bool yFlip)
+ : TestCase (testCtx, getCaseName(primitiveType, winding, yFlip), "")
, m_primitiveType (primitiveType)
, m_winding (winding)
+ , m_yFlip (yFlip)
{
}
public:
WindingTestInstance (Context& context,
const TessPrimitiveType primitiveType,
- const Winding winding);
+ const Winding winding,
+ bool yFlip);
tcu::TestStatus iterate (void);
private:
const TessPrimitiveType m_primitiveType;
const Winding m_winding;
+ const bool m_yFlip;
};
WindingTestInstance::WindingTestInstance (Context& context,
const TessPrimitiveType primitiveType,
- const Winding winding)
+ const Winding winding,
+ bool yFlip)
: TestInstance (context)
, m_primitiveType (primitiveType)
, m_winding (winding)
+ , m_yFlip (yFlip)
{
}
tcu::TestStatus WindingTestInstance::iterate (void)
{
+ if (m_yFlip && !de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), "VK_KHR_maintenance1"))
+ TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
+
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice device = m_context.getDevice();
const VkQueue queue = m_context.getUniversalQueue();
// Front face is static state, so we have to create two pipelines.
const Unique<VkPipeline> pipelineCounterClockwise(GraphicsPipelineBuilder()
- .setRenderSize (renderSize)
.setCullModeFlags(cullMode)
.setFrontFace (VK_FRONT_FACE_COUNTER_CLOCKWISE)
.setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL)
.build (vk, device, *pipelineLayout, *renderPass));
const Unique<VkPipeline> pipelineClockwise(GraphicsPipelineBuilder()
- .setRenderSize (renderSize)
.setCullModeFlags(cullMode)
.setFrontFace (VK_FRONT_FACE_CLOCKWISE)
.setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL)
beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
}
+ const VkViewport viewport =
+ {
+ 0.0f, // float x;
+ m_yFlip ? static_cast<float>(renderSize.y()) : 0.0f, // float y;
+ static_cast<float>(renderSize.x()), // float width;
+ static_cast<float>(m_yFlip ? -renderSize.y() : renderSize.y()), // float height;
+ 0.0f, // float minDepth;
+ 1.0f, // float maxDepth;
+ };
+ vk.cmdSetViewport(*cmdBuffer, 0, 1, &viewport);
+
+ const VkRect2D scissor =
+ {
+ makeOffset2D(0, 0),
+ makeExtent2D(renderSize.x(), renderSize.y()),
+ };
+ vk.cmdSetScissor(*cmdBuffer, 0, 1, &scissor);
+
vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, testCases[caseNdx].pipeline);
// Process a single abstract vertex.
log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
// Verify case result
- success = success && verifyResultImage(log, imagePixelAccess, m_primitiveType, m_winding, frontFaceWinding);
+ success = success && verifyResultImage(log, imagePixelAccess, m_primitiveType, m_winding, m_yFlip, frontFaceWinding);
}
} // for windingNdx
{
requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER);
- return new WindingTestInstance(context, m_primitiveType, m_winding);
+ return new WindingTestInstance(context, m_primitiveType, m_winding, m_yFlip);
}
} // anonymous
for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitivesNoIsolines); ++primitiveTypeNdx)
for (int windingNdx = 0; windingNdx < WINDING_LAST; ++windingNdx)
- group->addChild(new WindingTest(testCtx, primitivesNoIsolines[primitiveTypeNdx], (Winding)windingNdx));
+ {
+ group->addChild(new WindingTest(testCtx, primitivesNoIsolines[primitiveTypeNdx], (Winding)windingNdx, false));
+ group->addChild(new WindingTest(testCtx, primitivesNoIsolines[primitiveTypeNdx], (Winding)windingNdx, true));
+ }
return group.release();
}