#include "vkBufferWithMemory.hpp"
#include "vkImageWithMemory.hpp"
#include "vkBarrierUtil.hpp"
+#include "vkBufferWithMemory.hpp"
#ifndef CTS_USES_VULKANSC
#include "vktRasterizationOrderAttachmentAccessTests.hpp"
#endif // CTS_USES_VULKANSC
#include <vector>
#include <sstream>
+#include <memory>
using namespace vk;
using tcu::TriangleSceneSpec;
using tcu::PointSceneSpec;
using tcu::LineSceneSpec;
-using tcu::LineInterpolationMethod;
static const char* const s_shaderVertexTemplate = "#version 310 es\n"
"layout(location = 0) in highp vec4 a_position;\n"
LINESTIPPLE_DISABLED = 0,
LINESTIPPLE_STATIC,
LINESTIPPLE_DYNAMIC,
+ LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY,
LINESTIPPLE_LAST
};
virtual float getLineWidth (void) const;
virtual float getPointSize (void) const;
virtual bool getLineStippleDynamic (void) const { return false; }
+ virtual bool isDynamicTopology (void) const { return false; }
+ virtual VkPrimitiveTopology getWrongTopology (void) const { return VK_PRIMITIVE_TOPOLOGY_LAST; }
+ virtual VkPrimitiveTopology getRightTopology (void) const { return VK_PRIMITIVE_TOPOLOGY_LAST; }
+ virtual std::vector<tcu::Vec4> getOffScreenPoints (void) const { return std::vector<tcu::Vec4>(); }
virtual
const VkPipelineRasterizationStateCreateInfo* getRasterizationStateCreateInfo (void) const;
const VkQueue queue = m_context.getUniversalQueue();
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
Allocator& allocator = m_context.getDefaultAllocator();
- const size_t attributeBatchSize = positionData.size() * sizeof(tcu::Vec4);
+ const size_t attributeBatchSize = de::dataSize(positionData);
+ const auto offscreenData = getOffScreenPoints();
Move<VkCommandBuffer> commandBuffer;
Move<VkPipeline> graphicsPipeline;
Move<VkBuffer> vertexBuffer;
de::MovePtr<Allocation> vertexBufferMemory;
+ std::unique_ptr<BufferWithMemory> offscreenDataBuffer;
const VkPhysicalDeviceProperties properties = m_context.getDeviceProperties();
if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
DE_NULL // const VkDynamicState* pDynamicStates
};
- VkDynamicState dynamicState = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
+ std::vector<VkDynamicState> dynamicStates;
+
+ if (getLineStippleDynamic())
+ dynamicStates.push_back(VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
+
+#ifndef CTS_USES_VULKANSC
+ if (isDynamicTopology())
+ dynamicStates.push_back(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
+#endif // CTS_USES_VULKANSC
+
if (getLineStippleDynamic())
{
- dynamicStateCreateInfo.dynamicStateCount = 1;
- dynamicStateCreateInfo.pDynamicStates = &dynamicState;
+ dynamicStateCreateInfo.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
+ dynamicStateCreateInfo.pDynamicStates = de::dataOrNull(dynamicStates);
}
graphicsPipeline = makeGraphicsPipeline(vkd, // const DeviceInterface& vk
flushAlloc(vkd, vkDevice, *vertexBufferMemory);
}
+ if (!offscreenData.empty())
+ {
+ // Concatenate positions with vertex colors.
+ const std::vector<tcu::Vec4> colors (offscreenData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+ std::vector<tcu::Vec4> fullOffscreenData (offscreenData);
+ fullOffscreenData.insert(fullOffscreenData.end(), colors.begin(), colors.end());
+
+ // Copy full data to offscreen data buffer.
+ const auto offscreenBufferSizeSz = de::dataSize(fullOffscreenData);
+ const auto offscreenBufferSize = static_cast<VkDeviceSize>(offscreenBufferSizeSz);
+ const auto offscreenDataCreateInfo = makeBufferCreateInfo(offscreenBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
+
+ offscreenDataBuffer .reset(new BufferWithMemory(vkd, vkDevice, allocator, offscreenDataCreateInfo, MemoryRequirement::HostVisible));
+ auto& bufferAlloc = offscreenDataBuffer->getAllocation();
+ void* dataPtr = bufferAlloc.getHostPtr();
+
+ deMemcpy(dataPtr, fullOffscreenData.data(), offscreenBufferSizeSz);
+ flushAlloc(vkd, vkDevice, bufferAlloc);
+ }
+
// Create Command Buffer
commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
- vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
if (getLineStippleDynamic())
+ {
vkd.cmdSetLineStippleEXT(*commandBuffer, lineStippleFactor, lineStipplePattern);
+#ifndef CTS_USES_VULKANSC
+ if (isDynamicTopology())
+ {
+ // Using a dynamic topology can interact with the dynamic line stipple set above on some implementations, so we try to
+ // check nothing breaks here. We set a wrong topology, draw some offscreen data and go back to the right topology
+ // _without_ re-setting the line stipple again. Side effects should not be visible.
+ DE_ASSERT(!!offscreenDataBuffer);
+
+ vkd.cmdSetPrimitiveTopology(*commandBuffer, getWrongTopology());
+ vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &offscreenDataBuffer->get(), &vertexBufferOffset);
+ vkd.cmdDraw(*commandBuffer, static_cast<uint32_t>(offscreenData.size()), 1u, 0u, 0u);
+ vkd.cmdSetPrimitiveTopology(*commandBuffer, getRightTopology());
+ }
+#endif // CTS_USES_VULKANSC
+ }
+ vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
endRenderPass(vkd, *commandBuffer);
virtual tcu::TestStatus iterate (void);
virtual float getLineWidth (void) const;
bool getLineStippleEnable (void) const { return m_stipple != LINESTIPPLE_DISABLED; }
- virtual bool getLineStippleDynamic (void) const { return m_stipple == LINESTIPPLE_DYNAMIC; }
+ virtual bool getLineStippleDynamic (void) const { return (m_stipple == LINESTIPPLE_DYNAMIC || m_stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY); }
+ virtual bool isDynamicTopology (void) const { return m_stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY; }
+
+ virtual
+ std::vector<tcu::Vec4> getOffScreenPoints (void) const;
virtual
VkPipelineRasterizationLineStateCreateInfoEXT initLineRasterizationStateCreateInfo (void) const;
return m_lineWidths[m_iteration];
}
+std::vector<tcu::Vec4> BaseLineTestInstance::getOffScreenPoints (void) const
+{
+ // These points will be used to draw something with the wrong topology.
+ // They are offscreen so as not to affect the render result.
+ return std::vector<tcu::Vec4>
+ {
+ tcu::Vec4(2.0f, 2.0f, 0.0f, 1.0f),
+ tcu::Vec4(2.0f, 3.0f, 0.0f, 1.0f),
+ tcu::Vec4(2.0f, 4.0f, 0.0f, 1.0f),
+ tcu::Vec4(2.0f, 5.0f, 0.0f, 1.0f),
+ };
+}
+
VkPipelineRasterizationLineStateCreateInfoEXT BaseLineTestInstance::initLineRasterizationStateCreateInfo (void) const
{
VkPipelineRasterizationLineStateCreateInfoEXT lineRasterizationStateInfo =
{
if (m_isLineTest)
{
+ if (m_stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
+ context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
+
if (m_wideness == PRIMITIVEWIDENESS_WIDE)
context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
}
bool getLineStippleEnable (void) const { return m_stipple != LINESTIPPLE_DISABLED; }
- virtual bool getLineStippleDynamic (void) const { return m_stipple == LINESTIPPLE_DYNAMIC; }
protected:
const PrimitiveWideness m_wideness;
class LinesTestInstance : public BaseLineTestInstance
{
public:
- LinesTestInstance (Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, LineStippleFactorCase stippleFactor, deUint32 additionalRenderSize = 0)
- : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, strictness, sampleCount, stipple, lineRasterizationMode, stippleFactor, additionalRenderSize)
- {}
+ LinesTestInstance (Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, LineStippleFactorCase stippleFactor, deUint32 additionalRenderSize = 0)
+ : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, strictness, sampleCount, stipple, lineRasterizationMode, stippleFactor, additionalRenderSize)
+ {}
+
+ VkPrimitiveTopology getWrongTopology (void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; }
+ VkPrimitiveTopology getRightTopology (void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; }
+ void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) override;
- virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
};
void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
class LineStripTestInstance : public BaseLineTestInstance
{
public:
- LineStripTestInstance (Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, LineStippleFactorCase stippleFactor, deUint32)
- : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, strictness, sampleCount, stipple, lineRasterizationMode, stippleFactor)
- {}
+ LineStripTestInstance (Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, LineStippleFactorCase stippleFactor, deUint32)
+ : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, strictness, sampleCount, stipple, lineRasterizationMode, stippleFactor)
+ {}
- virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
+ VkPrimitiveTopology getWrongTopology (void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; }
+ VkPrimitiveTopology getRightTopology (void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; }
+ void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) override;
};
void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
tcu::TestCaseGroup* const nostippleTests = new tcu::TestCaseGroup(testCtx, "no_stipple", "No stipple");
tcu::TestCaseGroup* const stippleStaticTests = new tcu::TestCaseGroup(testCtx, "static_stipple", "Line stipple static");
tcu::TestCaseGroup* const stippleDynamicTests = new tcu::TestCaseGroup(testCtx, "dynamic_stipple", "Line stipple dynamic");
+#ifndef CTS_USES_VULKANSC
+ tcu::TestCaseGroup* const stippleDynamicTopoTests = new tcu::TestCaseGroup(testCtx, "dynamic_stipple_and_topology", "Dynamic line stipple and topology");
+#endif // CTS_USES_VULKANSC
tcu::TestCaseGroup* const strideZeroTests = new tcu::TestCaseGroup(testCtx, "stride_zero", "Test input assembly with stride zero");
primitives->addChild(nostippleTests);
primitives->addChild(stippleStaticTests);
primitives->addChild(stippleDynamicTests);
+#ifndef CTS_USES_VULKANSC
+ primitives->addChild(stippleDynamicTopoTests);
+#endif // CTS_USES_VULKANSC
primitives->addChild(strideZeroTests);
// .stride_zero
nostippleTests->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "non_strict_lines_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE, PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "non_strict_line_strip_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in nonstrict mode with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE, PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
- for (int i = 0; i < 3; ++i) {
-
- tcu::TestCaseGroup *g = i == 2 ? stippleDynamicTests : i == 1 ? stippleStaticTests : nostippleTests;
+ for (int i = 0; i < static_cast<int>(LINESTIPPLE_LAST); ++i) {
LineStipple stipple = (LineStipple)i;
+#ifdef CTS_USES_VULKANSC
+ if (stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
+ continue;
+#endif // CTS_USES_VULKANSC
+
+ tcu::TestCaseGroup *g = (stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
+#ifndef CTS_USES_VULKANSC
+ ? stippleDynamicTopoTests
+#else
+ ? nullptr // Note this is actually unused, due to the continue statement above.
+#endif // CTS_USES_VULKANSC
+ : (stipple == LINESTIPPLE_DYNAMIC)
+ ? stippleDynamicTests
+ : (stipple == LINESTIPPLE_STATIC)
+ ? stippleStaticTests
+ : nostippleTests;
+
for (const auto& sfCase : stippleFactorCases)
{
if (sfCase.stippleFactor != LineStippleFactorCase::DEFAULT && stipple != LINESTIPPLE_DISABLED)
nostippleTests->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "non_strict_lines", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode, verify rasterization result", PRIMITIVEWIDENESS_NARROW, PRIMITIVESTRICTNESS_NONSTRICT, true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
nostippleTests->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "non_strict_lines_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE, PRIMITIVESTRICTNESS_NONSTRICT, true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
- for (int i = 0; i < 3; ++i) {
-
- tcu::TestCaseGroup *g = i == 2 ? stippleDynamicTests : i == 1 ? stippleStaticTests : nostippleTests;
+ for (int i = 0; i < static_cast<int>(LINESTIPPLE_LAST); ++i) {
LineStipple stipple = (LineStipple)i;
+ // These variants are not needed for multisample cases.
+ if (stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
+ continue;
+
+ tcu::TestCaseGroup *g = (stipple == LINESTIPPLE_DYNAMIC)
+ ? stippleDynamicTests
+ : (stipple == LINESTIPPLE_STATIC)
+ ? stippleStaticTests
+ : nostippleTests;
+
g->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result", PRIMITIVEWIDENESS_NARROW, PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, LineStippleFactorCase::DEFAULT, i == 0 ? RESOLUTION_NPOT : 0));
g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result", PRIMITIVEWIDENESS_NARROW, PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
g->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE, PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));