From: Toni Merilehti Date: Thu, 31 May 2018 11:05:10 +0000 (+0300) Subject: Added tests for rasterizer discard X-Git-Tag: upstream/1.3.5~2589 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4fb632f534f01bf347bef3d89d6056c790e07003;p=platform%2Fupstream%2FVK-GL-CTS.git Added tests for rasterizer discard New tests were added to verify correct functionality when setting rasterizerDiscardEnable to VK_TRUE in rasterizationStateCreateInfo. Tests verify that primitives are discarded before rasterization by comparing the rendered image to a blank reference image and ensuring that no fragment shader invocations have occured. New tests: dEQP-VK.rasterization.discard.* Components: Vulkan VK-GL-CTS issue: 1149 VK-GL-CTS public issue: 100 Change-Id: Ided170a2831efaac7e393ce8cafb93269180b3d0 --- diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 11213d9..7b9d2b0 100755 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -301057,6 +301057,18 @@ dEQP-VK.rasterization.culling.both_triangle_strip dEQP-VK.rasterization.culling.both_triangle_strip_reverse dEQP-VK.rasterization.culling.both_triangle_fan dEQP-VK.rasterization.culling.both_triangle_fan_reverse +dEQP-VK.rasterization.discard.triangle_list.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_list.query_pipeline_true +dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_true +dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_true +dEQP-VK.rasterization.discard.line_list.query_pipeline_false +dEQP-VK.rasterization.discard.line_list.query_pipeline_true +dEQP-VK.rasterization.discard.line_strip.query_pipeline_false +dEQP-VK.rasterization.discard.line_strip.query_pipeline_true +dEQP-VK.rasterization.discard.point_list.query_pipeline_false +dEQP-VK.rasterization.discard.point_list.query_pipeline_true dEQP-VK.rasterization.interpolation.basic.triangles dEQP-VK.rasterization.interpolation.basic.triangle_strip dEQP-VK.rasterization.interpolation.basic.triangle_fan diff --git a/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp b/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp index 9926650..55737e4 100644 --- a/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp +++ b/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp @@ -2202,6 +2202,519 @@ protected: const VkPolygonMode m_polygonMode; }; +class DiscardTestInstance : public BaseRenderingTestInstance +{ +public: + DiscardTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations) + : BaseRenderingTestInstance (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE) + , m_primitiveTopology (primitiveTopology) + , m_queryFragmentShaderInvocations (queryFragmentShaderInvocations) + {} + + virtual const VkPipelineRasterizationStateCreateInfo* getRasterizationStateCreateInfo (void) const; + tcu::TestStatus iterate (void); + +private: + void generateVertices (std::vector& outData) const; + void extractTriangles (std::vector& outTriangles, const std::vector& vertices) const; + void extractLines (std::vector& outLines, const std::vector& vertices) const; + void extractPoints (std::vector& outPoints, const std::vector& vertices) const; + void drawPrimitives (tcu::Surface& result, const std::vector& positionData, VkPrimitiveTopology primitiveTopology, Move& queryPool); + + const VkPrimitiveTopology m_primitiveTopology; + const deBool m_queryFragmentShaderInvocations; +}; + +tcu::TestStatus DiscardTestInstance::iterate (void) +{ + const DeviceInterface& vkd = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + deUint64 queryResult = 0u; + tcu::Surface resultImage (m_renderSize, m_renderSize); + std::vector drawBuffer; + std::vector points; + std::vector lines; + std::vector triangles; + + generateVertices(drawBuffer); + + switch (m_primitiveTopology) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + extractPoints(points, drawBuffer); + break; + + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + extractLines(lines, drawBuffer); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + extractTriangles(triangles, drawBuffer); + break; + + default: + DE_ASSERT(false); + } + + const VkQueryPoolCreateInfo queryPoolCreateInfo = + { + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType + DE_NULL, // const void* pNext + (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags + VK_QUERY_TYPE_PIPELINE_STATISTICS , // VkQueryType queryType + 1u, // deUint32 entryCount + VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT, // VkQueryPipelineStatisticFlags pipelineStatistics + }; + + if (m_queryFragmentShaderInvocations) + { + Move queryPool = createQueryPool(vkd, vkDevice, &queryPoolCreateInfo); + + drawPrimitives(resultImage, drawBuffer, m_primitiveTopology, queryPool); + vkd.getQueryPoolResults(vkDevice, *queryPool, 0u, 1u, sizeof(deUint64), &queryResult, 0u, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + } + else + BaseRenderingTestInstance::drawPrimitives(resultImage, drawBuffer, m_primitiveTopology); + + // compare + { + tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); + + const RasterizationArguments args = + { + 0, // int numSamples; + (int)m_subpixelBits, // int subpixelBits; + colorBits[0], // int redBits; + colorBits[1], // int greenBits; + colorBits[2] // int blueBits; + }; + + // Empty scene to compare to, primitives should be discarded before rasterization + TriangleSceneSpec scene; + + const bool isCompareOk = verifyTriangleGroupRasterization(resultImage, + scene, + args, + m_context.getTestContext().getLog(), + tcu::VERIFICATIONMODE_STRICT); + + if (isCompareOk) + { + if (m_queryFragmentShaderInvocations && queryResult > 0u) + return tcu::TestStatus::fail("Fragment shader invocations occured"); + else + return tcu::TestStatus::pass("Pass"); + } + else + return tcu::TestStatus::fail("Incorrect rendering"); + } +} + +void DiscardTestInstance::generateVertices (std::vector& outData) const +{ + de::Random rnd(12345); + + outData.resize(6); + + for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) + { + outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f); + outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f); + outData[vtxNdx].z() = 0.0f; + outData[vtxNdx].w() = 1.0f; + } +} + +void DiscardTestInstance::extractTriangles (std::vector& outTriangles, const std::vector& vertices) const +{ + switch (m_primitiveTopology) + { + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + { + for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3) + { + TriangleSceneSpec::SceneTriangle tri; + const tcu::Vec4& v0 = vertices[vtxNdx + 0]; + const tcu::Vec4& v1 = vertices[vtxNdx + 1]; + const tcu::Vec4& v2 = vertices[vtxNdx + 2]; + + tri.positions[0] = v0; + tri.positions[1] = v1; + tri.positions[2] = v2; + + outTriangles.push_back(tri); + } + + break; + } + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + { + for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx) + { + TriangleSceneSpec::SceneTriangle tri; + const tcu::Vec4& v0 = vertices[vtxNdx + 0]; + const tcu::Vec4& v1 = vertices[vtxNdx + 1]; + const tcu::Vec4& v2 = vertices[vtxNdx + 2]; + + tri.positions[0] = v0; + tri.positions[1] = v1; + tri.positions[2] = v2; + + outTriangles.push_back(tri); + } + + break; + } + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + { + for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) + { + TriangleSceneSpec::SceneTriangle tri; + const tcu::Vec4& v0 = vertices[0]; + const tcu::Vec4& v1 = vertices[vtxNdx + 0]; + const tcu::Vec4& v2 = vertices[vtxNdx + 1]; + + tri.positions[0] = v0; + tri.positions[1] = v1; + tri.positions[2] = v2; + + outTriangles.push_back(tri); + } + + break; + } + + default: + DE_ASSERT(false); + } +} + +void DiscardTestInstance::extractLines (std::vector& outLines, const std::vector& vertices) const +{ + switch (m_primitiveTopology) + { + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + { + for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2) + { + LineSceneSpec::SceneLine line; + + line.positions[0] = vertices[vtxNdx + 0]; + line.positions[1] = vertices[vtxNdx + 1]; + + outLines.push_back(line); + } + + break; + } + + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + { + for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) + { + LineSceneSpec::SceneLine line; + + line.positions[0] = vertices[vtxNdx + 0]; + line.positions[1] = vertices[vtxNdx + 1]; + + outLines.push_back(line); + } + + break; + } + + default: + DE_ASSERT(false); + } +} + +void DiscardTestInstance::extractPoints (std::vector& outPoints, const std::vector& vertices) const +{ + for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx) + { + for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx) + { + PointSceneSpec::ScenePoint point; + + point.position = vertices[vrtxNdx]; + point.pointSize = 1.0f; + + outPoints.push_back(point); + } + } +} + +const VkPipelineRasterizationStateCreateInfo* DiscardTestInstance::getRasterizationStateCreateInfo (void) const +{ + static const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + NULL, // const void* pNext; + 0, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClipEnable; + VK_TRUE, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkFillMode fillMode; + VK_CULL_MODE_NONE, // VkCullMode cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBias; + 0.0f, // float depthBiasClamp; + 0.0f, // float slopeScaledDepthBias; + getLineWidth(), // float lineWidth; + }; + + return &rasterizationStateCreateInfo; +} + +void DiscardTestInstance::drawPrimitives (tcu::Surface& result, const std::vector& positionData, VkPrimitiveTopology primitiveTopology, Move& queryPool) +{ + const DeviceInterface& vkd = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + const VkPhysicalDeviceProperties properties = m_context.getDeviceProperties(); + 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 VkDeviceSize vertexBufferOffset = 0; + de::MovePtr vertexBufferMemory; + Move vertexBuffer; + Move commandBuffer; + Move graphicsPipeline; + + if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset) + { + std::stringstream message; + message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ")."; + TCU_THROW(NotSupportedError, message.str().c_str()); + } + + // Create Graphics Pipeline + { + const VkVertexInputBindingDescription vertexInputBindingDescription = + { + 0u, // deUint32 binding; + sizeof(tcu::Vec4), // deUint32 strideInBytes; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; + }; + + const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = + { + { + 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; + (deUint32)attributeBatchSize // deUint32 offsetInBytes; + } + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // deUint32 bindingCount; + &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 2u, // deUint32 attributeCount; + vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const std::vector viewports (1, makeViewport(tcu::UVec2(m_renderSize))); + const std::vector scissors (1, makeRect2D(tcu::UVec2(m_renderSize))); + + const VkPipelineMultisampleStateCreateInfo multisampleStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineMultisampleStateCreateFlags flags; + m_sampleCount, // VkSampleCountFlagBits rasterizationSamples; + VK_FALSE, // VkBool32 sampleShadingEnable; + 0.0f, // float minSampleShading; + DE_NULL, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE // VkBool32 alphaToOneEnable; + }; + + graphicsPipeline = makeGraphicsPipeline(vkd, // const DeviceInterface& vk + vkDevice, // 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& viewports + scissors, // const std::vector& scissors + primitiveTopology, // const VkPrimitiveTopology topology + 0u, // const deUint32 subpass + 0u, // const deUint32 patchControlPoints + &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo + getRasterizationStateCreateInfo(), // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo + &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo + DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo, + getColorBlendStateCreateInfo()); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo + } + + // Create Vertex Buffer + { + const VkBufferCreateInfo vertexBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + attributeBatchSize * 2, // VkDeviceSize size; + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex // const deUint32* pQueueFamilyIndices; + }; + + const std::vector colorData (positionData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); + + vertexBuffer = createBuffer(vkd, vkDevice, &vertexBufferParams); + vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible); + + VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset())); + + // Load vertices into vertex buffer + deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize); + deMemcpy(reinterpret_cast(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize); + flushMappedMemoryRange(vkd, vkDevice, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset(), vertexBufferParams.size); + } + + // Create Command Buffer + commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); + + // Begin Command Buffer + beginCommandBuffer(vkd, *commandBuffer); + + addImageTransitionBarrier(*commandBuffer, // VkCommandBuffer commandBuffer + *m_image, // VkImage image + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask + 0, // VkAccessFlags srcAccessMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout; + + if (m_multisampling) + { + addImageTransitionBarrier(*commandBuffer, // VkCommandBuffer commandBuffer + *m_resolvedImage, // VkImage image + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask + 0, // VkAccessFlags srcAccessMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout; + } + + // Reset query pool + vkd.cmdResetQueryPool(*commandBuffer, *queryPool, 0u, 1u); + + // Begin render pass and start query + beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); + vkd.cmdBeginQuery(*commandBuffer, *queryPool, 0u, (VkQueryControlFlags)0u); + 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); + vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0); + endRenderPass(vkd, *commandBuffer); + vkd.cmdEndQuery(*commandBuffer, *queryPool, 0u); + + // Copy Image + { + const VkBufferMemoryBarrier bufferBarrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask; + VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + *m_resultBuffer, // VkBuffer buffer; + 0u, // VkDeviceSize offset; + m_resultBufferSize // VkDeviceSize size; + }; + + const VkBufferImageCopy copyRegion = + { + 0u, // VkDeviceSize bufferOffset; + m_renderSize, // deUint32 bufferRowLength; + m_renderSize, // deUint32 bufferImageHeight; + { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u }, // VkImageSubresourceCopy imageSubresource; + { 0, 0, 0 }, // VkOffset3D imageOffset; + { m_renderSize, m_renderSize, 1u } // VkExtent3D imageExtent; + }; + + addImageTransitionBarrier(*commandBuffer, // VkCommandBuffer commandBuffer + m_multisampling ? *m_resolvedImage : *m_image, // VkImage image + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask + VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); // VkImageLayout newLayout;) + + if (m_multisampling) + vkd.cmdCopyImageToBuffer(*commandBuffer, *m_resolvedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, ©Region); + else + vkd.cmdCopyImageToBuffer(*commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, ©Region); + + vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); + } + + endCommandBuffer(vkd, *commandBuffer); + + // Set Point Size + { + float pointSize = getPointSize(); + + deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize); + flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), m_uniformBufferSize); + } + + // Submit + submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get()); + + invalidateMappedMemoryRange(vkd, vkDevice, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset(), m_resultBufferSize); + tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr())); +} + +class DiscardTestCase : public BaseRenderingTestCase +{ +public: + DiscardTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT) + : BaseRenderingTestCase (context, name, description, sampleCount) + , m_primitiveTopology (primitiveTopology) + , m_queryFragmentShaderInvocations (queryFragmentShaderInvocations) + {} + + virtual TestInstance* createInstance (Context& context) const + { + if (m_queryFragmentShaderInvocations && !context.getDeviceFeatures().pipelineStatisticsQuery) + throw tcu::NotSupportedError("Pipeline statistics queries are not supported"); + + return new DiscardTestInstance (context, m_primitiveTopology, m_queryFragmentShaderInvocations); + } + +protected: + const VkPrimitiveTopology m_primitiveTopology; + const deBool m_queryFragmentShaderInvocations; +}; + class TriangleInterpolationTestInstance : public BaseRenderingTestInstance { public: @@ -2783,6 +3296,51 @@ void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests) } } + // .discard + { + static const struct PrimitiveType + { + VkPrimitiveTopology type; + const char* name; + } primitiveTypes[] = + { + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list" }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip" }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan" }, + { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list" }, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip" }, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list" } + }; + + static const struct queryPipeline + { + deBool useQuery; + const char* name; + } queryPipeline[] = + { + { DE_FALSE, "query_pipeline_false" }, + { DE_TRUE, "query_pipeline_true" }, + }; + + tcu::TestCaseGroup* const discard = new tcu::TestCaseGroup(testCtx, "discard", "Rasterizer discard"); + + for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx) + { + tcu::TestCaseGroup* const primitive = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveNdx].name, "Rasterizer discard"); + + for (int useQueryNdx = 0; useQueryNdx < DE_LENGTH_OF_ARRAY(queryPipeline); useQueryNdx++) + { + const std::string name = std::string(queryPipeline[useQueryNdx].name); + + primitive->addChild(new DiscardTestCase(testCtx, name, "Test primitive discarding.", primitiveTypes[primitiveNdx].type, queryPipeline[useQueryNdx].useQuery)); + } + + discard->addChild(primitive); + } + + rasterizationTests->addChild(discard); + } + // .interpolation { tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation"); diff --git a/external/vulkancts/mustpass/1.1.2/vk-default-no-waivers.txt b/external/vulkancts/mustpass/1.1.2/vk-default-no-waivers.txt index 6efcc63..fd1077c 100644 --- a/external/vulkancts/mustpass/1.1.2/vk-default-no-waivers.txt +++ b/external/vulkancts/mustpass/1.1.2/vk-default-no-waivers.txt @@ -301385,6 +301385,18 @@ dEQP-VK.rasterization.culling.both_triangle_strip dEQP-VK.rasterization.culling.both_triangle_strip_reverse dEQP-VK.rasterization.culling.both_triangle_fan dEQP-VK.rasterization.culling.both_triangle_fan_reverse +dEQP-VK.rasterization.discard.triangle_list.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_list.query_pipeline_true +dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_true +dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_true +dEQP-VK.rasterization.discard.line_list.query_pipeline_false +dEQP-VK.rasterization.discard.line_list.query_pipeline_true +dEQP-VK.rasterization.discard.line_strip.query_pipeline_false +dEQP-VK.rasterization.discard.line_strip.query_pipeline_true +dEQP-VK.rasterization.discard.point_list.query_pipeline_false +dEQP-VK.rasterization.discard.point_list.query_pipeline_true dEQP-VK.rasterization.interpolation.basic.triangles dEQP-VK.rasterization.interpolation.basic.triangle_strip dEQP-VK.rasterization.interpolation.basic.triangle_fan diff --git a/external/vulkancts/mustpass/1.1.2/vk-default.txt b/external/vulkancts/mustpass/1.1.2/vk-default.txt index 6fc17dc..de66e1b 100644 --- a/external/vulkancts/mustpass/1.1.2/vk-default.txt +++ b/external/vulkancts/mustpass/1.1.2/vk-default.txt @@ -301346,6 +301346,18 @@ dEQP-VK.rasterization.culling.both_triangle_strip dEQP-VK.rasterization.culling.both_triangle_strip_reverse dEQP-VK.rasterization.culling.both_triangle_fan dEQP-VK.rasterization.culling.both_triangle_fan_reverse +dEQP-VK.rasterization.discard.triangle_list.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_list.query_pipeline_true +dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_true +dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_false +dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_true +dEQP-VK.rasterization.discard.line_list.query_pipeline_false +dEQP-VK.rasterization.discard.line_list.query_pipeline_true +dEQP-VK.rasterization.discard.line_strip.query_pipeline_false +dEQP-VK.rasterization.discard.line_strip.query_pipeline_true +dEQP-VK.rasterization.discard.point_list.query_pipeline_false +dEQP-VK.rasterization.discard.point_list.query_pipeline_true dEQP-VK.rasterization.interpolation.basic.triangles dEQP-VK.rasterization.interpolation.basic.triangle_strip dEQP-VK.rasterization.interpolation.basic.triangle_fan