blob: 7986470cbd9acbd55440cdea7ccd1b73be6a1019 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2020 The Khronos Group Inc.
* Copyright (c) 2020 ARM Ltd.
*
* 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_ARM_rasterization_order_attachment_access tests.
*//*--------------------------------------------------------------------*/
#include "deDefs.hpp"
#include "deSharedPtr.hpp"
#include "deUniquePtr.hpp"
#include "tcuCommandLine.hpp"
#include "tcuImageCompare.hpp"
#include "tcuResource.hpp"
#include "tcuTestLog.hpp"
#include "tcuStringTemplate.hpp"
#include "vkBarrierUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkDefs.hpp"
#include "vkImageUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkPlatform.hpp"
#include "vkPrograms.hpp"
#include "vkQueryUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vktRasterizationOrderAttachmentAccessTests.hpp"
#include "vktRasterizationTests.hpp"
#include "vkTypeUtil.hpp"
#include "vktTestCase.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"
using namespace vk;
using namespace std;
using namespace vkt;
using de::UniquePtr;
using de::MovePtr;
using de::SharedPtr;
namespace vkt
{
namespace rasterization
{
namespace
{
class AttachmentAccessOrderTestCase : public TestCase
{
public:
enum
{
ELEM_NUM = 6
};
AttachmentAccessOrderTestCase( tcu::TestContext& context, const std::string& name, const std::string& description,
bool explicitSync, bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
VkSampleCountFlagBits sampleCount, deUint32 inputAttachmentNum, bool integerFormat);
virtual ~AttachmentAccessOrderTestCase (void);
virtual void initPrograms (SourceCollections& programCollection) const;
virtual TestInstance* createInstance (Context& context) const;
virtual void checkSupport (Context& context) const;
virtual deUint32 getInputAttachmentNum() const = 0;
virtual deUint32 getColorAttachmentNum() const = 0;
virtual bool hasDepthStencil() const = 0;
virtual VkImageAspectFlagBits getDSAspect() const = 0;
deUint32 m_inputAttachmentNum;
const bool m_explicitSync;
const bool m_overlapDraws;
const bool m_overlapPrimitives;
const bool m_overlapInstances;
VkSampleCountFlagBits m_sampleCount;
const deUint32 m_sampleNum;
const bool m_integerFormat;
static deUint32 getSampleNum(VkSampleCountFlagBits sampleCount);
VkFormat getColorFormat() const
{
return m_integerFormat ? VK_FORMAT_R32G32_UINT : VK_FORMAT_R32G32_SFLOAT;
}
VkFormat getDSFormat() const
{
return VK_FORMAT_D32_SFLOAT_S8_UINT;
}
VkPipelineColorBlendStateCreateFlags getBlendStateFlags() const
{
return m_explicitSync ? 0 : VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM;
}
virtual VkPipelineDepthStencilStateCreateFlags getDSStateFlags() const
{
return 0;
}
virtual bool hasDepth() const
{
return false;
}
virtual bool hasStencil() const
{
return false;
}
protected:
virtual void addShadersInternal(SourceCollections& programCollection, const std::map<std::string, std::string> &params) const = 0;
void addSimpleVertexShader(SourceCollections& programCollection, const std::string &dest) const;
virtual void checkAdditionalRasterizationFlags(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM &rasterizationAccess) const
{
// unused parameter
DE_UNREF(rasterizationAccess);
}
};
class AttachmentAccessOrderColorTestCase : public AttachmentAccessOrderTestCase
{
public:
AttachmentAccessOrderColorTestCase( tcu::TestContext& context, const std::string& name, const std::string& description,
bool explicitSync, bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
VkSampleCountFlagBits sampleCount, deUint32 inputAttachmentNum, bool integerFormat)
:AttachmentAccessOrderTestCase( context, name, description, explicitSync, overlapDraws, overlapPrimitives, overlapInstances, sampleCount,
inputAttachmentNum, integerFormat)
{}
virtual deUint32 getInputAttachmentNum() const
{
return m_inputAttachmentNum;
}
virtual deUint32 getColorAttachmentNum() const
{
return m_inputAttachmentNum;
}
virtual bool hasDepthStencil() const
{
return false;
}
virtual VkImageAspectFlagBits getDSAspect() const
{
/* not relevant, this return value will not be used */
return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM;
}
protected:
virtual void addShadersInternal(SourceCollections& programCollection, const std::map<std::string, std::string> &params) const;
};
class AttachmentAccessOrderDepthTestCase : public AttachmentAccessOrderTestCase
{
public:
AttachmentAccessOrderDepthTestCase( tcu::TestContext& context, const std::string& name, const std::string& description,
bool explicitSync, bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
VkSampleCountFlagBits sampleCount)
:AttachmentAccessOrderTestCase( context, name, description, explicitSync, overlapDraws, overlapPrimitives, overlapInstances, sampleCount,
1, false)
{}
virtual deUint32 getInputAttachmentNum() const
{
return m_inputAttachmentNum + 1;
}
virtual deUint32 getColorAttachmentNum() const
{
return m_inputAttachmentNum;
}
virtual bool hasDepth() const
{
return true;
}
virtual bool hasDepthStencil() const
{
return true;
}
virtual VkImageAspectFlagBits getDSAspect() const
{
return VK_IMAGE_ASPECT_DEPTH_BIT;
}
virtual VkPipelineDepthStencilStateCreateFlags getDSStateFlags() const
{
return m_explicitSync ? 0 : VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM;
}
protected:
virtual void addShadersInternal(SourceCollections& programCollection, const std::map<std::string, std::string> &params) const;
virtual void checkAdditionalRasterizationFlags(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM &rasterizationAccess) const
{
if (!m_explicitSync && !rasterizationAccess.rasterizationOrderDepthAttachmentAccess)
{
TCU_THROW(NotSupportedError , "Implicit attachment access rasterization order not guaranteed for depth attachments");
}
}
};
class AttachmentAccessOrderStencilTestCase : public AttachmentAccessOrderTestCase
{
public:
AttachmentAccessOrderStencilTestCase( tcu::TestContext& context, const std::string& name, const std::string& description,
bool explicitSync, bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
VkSampleCountFlagBits sampleCount)
:AttachmentAccessOrderTestCase( context, name, description, explicitSync, overlapDraws, overlapPrimitives, overlapInstances, sampleCount,
1, true)
{}
virtual deUint32 getInputAttachmentNum() const
{
return m_inputAttachmentNum + 1;
}
virtual deUint32 getColorAttachmentNum() const
{
return m_inputAttachmentNum;
}
virtual bool hasStencil() const
{
return true;
}
virtual bool hasDepthStencil() const
{
return true;
}
virtual VkImageAspectFlagBits getDSAspect() const
{
return VK_IMAGE_ASPECT_STENCIL_BIT;
}
virtual VkPipelineDepthStencilStateCreateFlags getDSStateFlags() const
{
return m_explicitSync ? 0 : VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM;
}
protected:
virtual void addShadersInternal(SourceCollections& programCollection, const std::map<std::string, std::string> &params) const;
virtual void checkAdditionalRasterizationFlags(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM &rasterizationAccess) const
{
if (!m_explicitSync && !rasterizationAccess.rasterizationOrderStencilAttachmentAccess)
{
TCU_THROW(NotSupportedError , "Implicit attachment access rasterization order not guaranteed for stencil attachments");
}
}
};
class AttachmentAccessOrderTestInstance : public TestInstance
{
public:
AttachmentAccessOrderTestInstance (Context& context, const AttachmentAccessOrderTestCase *testCase);
virtual ~AttachmentAccessOrderTestInstance (void);
virtual tcu::TestStatus iterate (void);
protected:
class RenderSubpass
{
public:
const AttachmentAccessOrderTestCase *m_testCase;
deUint32 m_subpass;
VkSampleCountFlagBits m_sampleCount;
Move<VkPipeline> m_pipeline;
Move<VkPipelineLayout> m_pipelineLayout;
deUint32 m_colorAttNum;
std::vector<Move<VkImage> > m_inputAtt;
std::vector<MovePtr<Allocation> > m_inputAttMemory;
std::vector<Move<VkImageView> > m_inputAttView;
std::vector<VkAttachmentReference> m_attachmentReferences;
void createAttachments( int subpass, deUint32 inputAttachmentNum, deUint32 colorAttachmentNum, VkSampleCountFlagBits sampleCount,
Context &context, vector<VkImageView> &views, VkDescriptorSetLayout *pDsetLayout, const AttachmentAccessOrderTestCase *tc);
void createPipeline(VkRenderPass renderPass, Context &context);
deUint32 getColorAttachmentNum()
{
return m_colorAttNum;
}
deUint32 getInputAttachmentNum()
{
return static_cast<deUint32>(m_inputAtt.size());
}
VkAttachmentReference* getDepthStencilAttachment()
{
return (getColorAttachmentNum() == getInputAttachmentNum()) ? DE_NULL : &m_attachmentReferences[m_colorAttNum];
}
};
void addPipelineBarrier( VkCommandBuffer cmdBuffer,
VkImage image,
VkImageLayout oldLayout,
VkImageLayout newLayout,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT);
void addClearColor(VkCommandBuffer cmdBuffer, VkImage image);
void addClearDepthStencil(VkCommandBuffer cmdBuffer, VkImage image);
void writeDescriptorSets();
Move<VkRenderPass> createRenderPass(VkFormat attFormat);
void createVertexBuffer();
void createResultBuffer();
void addDependency( vector<VkSubpassDependency> &dependencies, deUint32 source, deUint32 dst,
VkPipelineStageFlags pipelineFlags, VkAccessFlags accessFlags);
tcu::TestStatus validateResults(deUint32 numDraws, deUint32 numPrimitives, deUint32 numInstances);
const AttachmentAccessOrderTestCase *m_testCase;
const DeviceInterface& m_vk;
vector<RenderSubpass> m_subpasses;
Move<VkRenderPass> m_renderPass;
Move<VkFramebuffer> m_framebuffer;
Move<VkBuffer> m_vertexBuffer;
MovePtr<Allocation> m_vertexBufferMemory;
Move<VkCommandPool> m_cmdPool;
Move<VkCommandBuffer> m_cmdBuffer;
Move<VkSampler> m_sampler;
Move<VkDescriptorSetLayout> m_descSetLayout;
Move<VkDescriptorPool> m_descPool;
Move<VkDescriptorSet> m_descSet;
Move<VkBuffer> m_resultBuffer;
MovePtr<Allocation> m_resultBufferMemory;
enum
{
WIDTH = 8,
HEIGHT = 8,
};
};
AttachmentAccessOrderTestCase::AttachmentAccessOrderTestCase ( tcu::TestContext& context, const std::string& name, const std::string& description,
bool explicitSync, bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
VkSampleCountFlagBits sampleCount, deUint32 inputAttachmentNum, bool integerFormat)
: TestCase(context, name, description)
, m_inputAttachmentNum(inputAttachmentNum)
, m_explicitSync(explicitSync)
, m_overlapDraws(overlapDraws)
, m_overlapPrimitives(overlapPrimitives)
, m_overlapInstances(overlapInstances)
, m_sampleCount(sampleCount)
, m_sampleNum(getSampleNum(sampleCount))
, m_integerFormat(integerFormat)
{
}
AttachmentAccessOrderTestCase::~AttachmentAccessOrderTestCase (void)
{
}
void AttachmentAccessOrderTestCase::addSimpleVertexShader(SourceCollections& programCollection, const std::string &dest) const
{
std::stringstream vertShader;
vertShader << "#version 310 es\n"
<< "layout(location = 0) in highp vec2 v_position;\n"
<< "void main ()\n"
<< "{\n"
<< " gl_Position = vec4(v_position, float(gl_InstanceIndex)/256.0, 1);\n"
<< "}\n";
programCollection.glslSources.add(dest) << glu::VertexSource(vertShader.str());
}
void AttachmentAccessOrderColorTestCase::addShadersInternal(SourceCollections& programCollection, const std::map<std::string, std::string> &params) const
{
addSimpleVertexShader(programCollection, "vert1");
addSimpleVertexShader(programCollection, "vert2");
std::stringstream fragShader;
fragShader << "#version 450\n"
<< "precision highp ${SCALAR_NAME};\n"
<< "precision highp ${SUBPASS_INPUT};\n";
for (deUint32 i=0; i < m_inputAttachmentNum; i++)
{
fragShader << "layout( set = 0, binding = " << i << ", input_attachment_index = " << i << " ) uniform ${SUBPASS_INPUT} in" << i << ";\n"
<< "layout( location = " << i << " ) out ${VEC_NAME}2 out" << i << ";\n";
}
fragShader << "layout( push_constant ) uniform ConstBlock\n"
<< "{\n"
<< " uint drawCur;\n"
<< "};\n"
<< "void main()\n"
<< "{\n"
<< " uint instanceCur = uint(round(gl_FragCoord.z * 256.0));\n"
<< " uint primitiveCur = uint(gl_PrimitiveID) / 2u;\n"
<< " uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
<< " uint instanceNum = ${INSTANCE_NUM}u;\n"
<< " uint drawNum = ${DRAW_NUM}u;\n"
<< " uint curIndex = drawCur * instanceNum * primitiveNum + instanceCur * primitiveNum + primitiveCur;\n"
<< " uint total = drawNum * instanceNum * primitiveNum;\n"
<< " uint zero = curIndex / total;\n"
<< " uint index;\n"
<< " uint pre_fetch_loop = uint(gl_FragCoord.x) * uint(gl_FragCoord.y) * (drawNum * primitiveNum - drawCur * primitiveNum - primitiveCur);\n"
<< " uint post_fetch_loop = uint(gl_FragCoord.x) + uint(gl_FragCoord.y) + (drawNum * instanceNum - drawCur * instanceNum - instanceCur);\n"
<< " for(index = 0u; index < pre_fetch_loop; index++)\n"
<< " {\n"
<< " zero = uint(sin(float(zero)));\n"
<< " }\n"
<< " ${VEC_NAME}2 previous[${ATT_NUM}];\n";
for (deUint32 i=0; i < m_inputAttachmentNum; i++)
{
if (m_sampleCount == VK_SAMPLE_COUNT_1_BIT)
{
fragShader << " previous[" << i << "] = subpassLoad( in" << i << ").xy;\n";
}
else
{
fragShader << " previous[" << i << "] = subpassLoad( in" << i << ", gl_SampleID).xy;\n";
}
}
fragShader << " for(index = 0u; index < post_fetch_loop; index++)\n"
<< " {\n"
<< " zero = uint(sin(float(zero)));\n"
<< " }\n";
for (deUint32 i=0; i < m_inputAttachmentNum; i++)
{
fragShader << " if (previous[" << i << "].y == 0 && curIndex == 0)\n"
<< " {\n"
<< " out" << i << ".y = previous[" << i << "].y + (1u + zero + gl_SampleID + " << i << "u);\n"
<< " out" << i << ".x = previous[" << i << "].x;\n"
<< " }\n"
<< " else if (previous[" << i << "].y == curIndex + gl_SampleID + " << i << ")\n"
<< " {\n"
<< " out" << i << ".y = previous[" << i << "].y + 1 + zero;\n"
<< " out" << i << ".x = previous[" << i << "].x;\n"
<< " }\n"
<< " else\n"
<< " {\n"
<< " out" << i << ".y = 0u;\n"
<< " out" << i << ".x = 1u;\n"
<< " }\n";
}
fragShader << "}\n";
tcu::StringTemplate fragShaderTpl(fragShader.str());
programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
}
void AttachmentAccessOrderDepthTestCase::addShadersInternal(SourceCollections& programCollection, const std::map<std::string, std::string> &params) const
{
std::stringstream vertShader;
vertShader << "#version 460\n"
<< "layout(location = 0) in highp vec2 v_position;\n"
<< "layout(location = 1) flat out uint instance_index;"
<< "layout( push_constant ) uniform ConstBlock\n"
<< "{\n"
<< " uint drawCur;\n"
<< "};\n"
<< "void main ()\n"
<< "{\n"
<< " uint primitiveCur = uint(gl_VertexIndex) / 6u;\n"
<< " uint instanceNum = ${INSTANCE_NUM};\n"
<< " uint primitiveNum = ${PRIMITIVE_NUM};\n"
<< " uint drawNum = ${DRAW_NUM};\n"
<< " uint curIndex = drawCur * instanceNum * primitiveNum + gl_InstanceIndex * primitiveNum + primitiveCur;\n"
<< " uint indexNum = drawNum * instanceNum * primitiveNum;\n"
<< " instance_index = gl_InstanceIndex;\n"
<< " gl_Position = vec4(v_position, 0.125 * float(curIndex) / float(indexNum), 1);\n"
<< "}\n";
tcu::StringTemplate vertShaderTpl(vertShader.str());
programCollection.glslSources.add("vert1") << glu::VertexSource(vertShaderTpl.specialize(params));
addSimpleVertexShader(programCollection, "vert2");
std::stringstream fragShader;
fragShader << "#version 450\n"
<< "precision highp ${SCALAR_NAME};\n"
<< "precision highp ${SUBPASS_INPUT};\n"
<< "layout( set = 0, binding = 0, input_attachment_index = 0 ) uniform ${SUBPASS_INPUT} in_color;\n"
<< "layout( set = 0, binding = 1, input_attachment_index = 1 ) uniform ${SUBPASS_INPUT} in_ds;\n"
<< "layout( location = 0 ) out ${VEC_NAME}2 out0;\n"
<< "layout( location = 1 ) flat in uint instance_index;\n"
<< "layout( push_constant ) uniform ConstBlock\n"
<< "{\n"
<< " uint drawCur;\n"
<< "};\n"
<< "void main()\n"
<< "{\n"
<< " uint instanceCur = instance_index;\n"
<< " uint primitiveCur = uint(gl_PrimitiveID) / 2u;\n"
<< " uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
<< " uint instanceNum = ${INSTANCE_NUM}u;\n"
<< " uint drawNum = ${DRAW_NUM}u;\n"
<< " uint curIndex = drawCur * instanceNum * primitiveNum + instanceCur * primitiveNum + primitiveCur;\n"
<< " uint total = drawNum * instanceNum * primitiveNum;\n"
<< " uint zero = curIndex / total;\n"
<< " uint index;\n"
<< " uint pre_fetch_loop = uint(gl_FragCoord.x) * uint(gl_FragCoord.y) * (drawNum * primitiveNum - drawCur * primitiveNum - primitiveCur);\n"
<< " uint post_fetch_loop = uint(gl_FragCoord.x) + uint(gl_FragCoord.y) + (drawNum * instanceNum - drawCur * instanceNum - instanceCur);\n"
<< " for(index = 0u; index < pre_fetch_loop; index++)\n"
<< " {\n"
<< " zero = uint(sin(float(zero)));\n"
<< " }\n";
if (m_sampleCount == VK_SAMPLE_COUNT_1_BIT)
{
fragShader << " vec2 ds = subpassLoad( in_ds ).xy;\n"
<< " ${VEC_NAME}2 color = subpassLoad( in_color ).xy;\n";
}
else
{
fragShader << " vec2 ds = subpassLoad( in_ds, gl_SampleID ).xy;\n"
<< " ${VEC_NAME}2 color = subpassLoad( in_color, gl_SampleID ).xy;\n";
}
fragShader << " for(index = 0u; index < post_fetch_loop; index++)\n"
<< " {\n"
<< " zero = uint(sin(float(zero)));\n"
<< " }\n"
<< " if (curIndex == 0 && ds.x == 0)\n"
<< " {\n"
<< " out0.x = color.x;\n"
<< " out0.y = curIndex + 1 + gl_SampleID + zero;\n";
if (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
{
fragShader << " gl_FragDepth = 0.125 * (float(curIndex) / float(total)) + gl_SampleID / 128.0;\n";
}
fragShader << " }\n"
<< " else if (ds.x == 0.125 * float(curIndex - 1) / float(total) + gl_SampleID / 128.0)\n"
<< " {\n"
<< " out0.x = color.x;\n"
<< " out0.y = curIndex + 1 + gl_SampleID + zero;\n";
if (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
{
fragShader << " gl_FragDepth = 0.125 * (float(curIndex) / float(total)) + gl_SampleID / 128.0;\n";
}
fragShader << " }\n"
<< " else\n"
<< " {\n"
<< " out0.y = 0;\n"
<< " out0.x = 1u;\n"
<< " }\n"
<< "}\n";
tcu::StringTemplate fragShaderTpl(fragShader.str());
programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
}
void AttachmentAccessOrderStencilTestCase::addShadersInternal(SourceCollections& programCollection, const std::map<std::string, std::string> &params) const
{
std::stringstream vertShader;
vertShader << "#version 460\n"
<< "layout(location = 0) in highp vec2 v_position;\n"
<< "layout(location = 1) flat out uint instance_index;"
<< "layout( push_constant ) uniform ConstBlock\n"
<< "{\n"
<< " uint drawCur;\n"
<< "};\n"
<< "void main ()\n"
<< "{\n"
<< " uint primitiveCur = uint(gl_VertexIndex) / 6u;\n"
<< " uint instanceNum = ${INSTANCE_NUM};\n"
<< " uint primitiveNum = ${PRIMITIVE_NUM};\n"
<< " uint drawNum = ${DRAW_NUM};\n"
<< " uint curIndex = drawCur * instanceNum * primitiveNum + gl_InstanceIndex * primitiveNum + primitiveCur;\n"
<< " uint indexNum = drawNum * instanceNum * primitiveNum;\n"
<< " instance_index = gl_InstanceIndex;\n"
<< " gl_Position = vec4(v_position, 0.125 * float(curIndex) / float(indexNum), 1);\n"
<< "}\n";
tcu::StringTemplate vertShaderTpl(vertShader.str());
programCollection.glslSources.add("vert1") << glu::VertexSource(vertShaderTpl.specialize(params));
addSimpleVertexShader(programCollection, "vert2");
std::stringstream fragShader;
fragShader << "#version 450\n"
<< "precision highp ${SCALAR_NAME};\n"
<< "precision highp ${SUBPASS_INPUT};\n"
<< "layout( set = 0, binding = 0, input_attachment_index = 0 ) uniform ${SUBPASS_INPUT} in_color;\n"
<< "layout( set = 0, binding = 1, input_attachment_index = 1 ) uniform ${SUBPASS_INPUT} in_ds;\n"
<< "layout( location = 0 ) out ${VEC_NAME}2 out0;\n"
<< "layout( location = 1 ) flat in uint instance_index;\n"
<< "layout( push_constant ) uniform ConstBlock\n"
<< "{\n"
<< " uint drawCur;\n"
<< "};\n"
<< "void main()\n"
<< "{\n"
<< " uint instanceCur = instance_index;\n"
<< " uint primitiveCur = uint(gl_PrimitiveID) / 2u;\n"
<< " uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
<< " uint instanceNum = ${INSTANCE_NUM}u;\n"
<< " uint drawNum = ${DRAW_NUM}u;\n"
<< " uint curIndex = drawCur * instanceNum * primitiveNum + instanceCur * primitiveNum + primitiveCur;\n"
<< " uint total = drawNum * instanceNum * primitiveNum;\n"
<< " uint zero = curIndex / total;\n"
<< " uint index;\n"
<< " uint pre_fetch_loop = uint(gl_FragCoord.x) * uint(gl_FragCoord.y) * (drawNum * primitiveNum - drawCur * primitiveNum - primitiveCur);\n"
<< " uint post_fetch_loop = uint(gl_FragCoord.x) + uint(gl_FragCoord.y) + (drawNum * instanceNum - drawCur * instanceNum - instanceCur);\n"
<< " for(index = 0u; index < pre_fetch_loop; index++)\n"
<< " {\n"
<< " zero = uint(sin(float(zero)));\n"
<< " }\n";
if (m_sampleCount == VK_SAMPLE_COUNT_1_BIT)
{
fragShader << " ${VEC_NAME}2 ds = subpassLoad( in_ds ).xy;\n"
<< " ${VEC_NAME}2 color = subpassLoad( in_color ).xy;\n";
}
else
{
fragShader << " ${VEC_NAME}2 ds = subpassLoad( in_ds, gl_SampleID).xy;\n"
<< " ${VEC_NAME}2 color = subpassLoad( in_color, gl_SampleID).xy;\n";
}
fragShader << " for(index = 0u; index < post_fetch_loop; index++)\n"
<< " {\n"
<< " zero = uint(sin(float(zero)));\n"
<< " }\n"
<< " if (ds.x == curIndex)\n"
<< " {\n"
<< " out0.x = color.x;\n"
<< " out0.y = curIndex + 1 + gl_SampleID + zero;\n"
<< " }\n"
<< " else\n"
<< " {\n"
<< " out0.y = 0;\n"
<< " out0.x = 1u;\n"
<< " }\n"
<< "}\n";
tcu::StringTemplate fragShaderTpl(fragShader.str());
programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
}
void AttachmentAccessOrderTestCase::initPrograms (SourceCollections& programCollection) const
{
std::map<std::string, std::string> params;
params["PRIMITIVE_NUM"] = std::to_string(m_overlapPrimitives?ELEM_NUM:1);
params["INSTANCE_NUM"] = std::to_string(m_overlapInstances?ELEM_NUM:1);
params["DRAW_NUM"] = std::to_string(m_overlapDraws?ELEM_NUM:1);
params["ATT_NUM"] = std::to_string(m_inputAttachmentNum);
params["SAMPLE_NUM"] = std::to_string(m_sampleNum);
if (m_integerFormat)
{
params["SUBPASS_INPUT"] = "usubpassInput";
params["SCALAR_NAME"] = "int";
params["VEC_NAME"] = "uvec";
}
else
{
params["SUBPASS_INPUT"] = "subpassInput";
params["SCALAR_NAME"] = "float";
params["VEC_NAME"] = "vec";
}
if (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
{
params["SUBPASS_INPUT"] = params["SUBPASS_INPUT"] + "MS";
}
/* add the vertex (for both renderpasses) and fragment shaders for first renderpass */
addShadersInternal(programCollection, params);
std::stringstream fragShaderResolve;
fragShaderResolve << "#version 450\n"
<< "precision highp ${SCALAR_NAME};\n"
<< "precision highp ${SUBPASS_INPUT};\n";
for (deUint32 i=0; i < m_inputAttachmentNum; i++)
{
fragShaderResolve << "layout( set = 0, binding = " << i << ", input_attachment_index = " << i << " ) uniform ${SUBPASS_INPUT} in" << i << ";\n";
}
fragShaderResolve << "layout( location = 0 ) out ${VEC_NAME}2 out0;\n";
fragShaderResolve << "void main()\n"
<< "{\n"
<< " uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
<< " uint instanceNum = ${INSTANCE_NUM}u;\n"
<< " uint drawNum = ${DRAW_NUM}u;\n"
<< " uint sampleNum = ${SAMPLE_NUM}u;\n"
<< " uint totalNum = primitiveNum * instanceNum * drawNum;\n"
<< " out0.y = totalNum;\n"
<< " out0.x = 0u;\n"
<< " ${VEC_NAME}2 val;\n"
<< " int i;\n";
for (deUint32 i=0; i < m_inputAttachmentNum; i++)
{
if (m_sampleNum == 1)
{
fragShaderResolve << " val = subpassLoad(in" << i << ").xy;\n"
<< " if (val.x != 0u || val.y != totalNum + " << i << "){\n"
<< " out0.y = val.y;\n"
<< " out0.x = val.x;\n"
<< " }\n";
}
else
{
fragShaderResolve << " for (i = 0; i < sampleNum; i++) {\n"
<< " val = subpassLoad(in" << i << ", i).xy;\n"
<< " if (val.x != 0u || val.y != totalNum + i + " << i << "){\n"
<< " out0.y = val.y;\n"
<< " out0.x = val.x;\n"
<< " }\n"
<< " }\n";
}
}
fragShaderResolve << "}\n";
tcu::StringTemplate fragShaderResolveTpl(fragShaderResolve.str());
programCollection.glslSources.add("frag_resolve") << glu::FragmentSource(fragShaderResolveTpl.specialize(params));
}
TestInstance* AttachmentAccessOrderTestCase::createInstance (Context& context) const
{
return new AttachmentAccessOrderTestInstance(context, this);
}
void AttachmentAccessOrderTestCase::checkSupport (Context& context) const
{
context.requireDeviceFunctionality("VK_ARM_rasterization_order_attachment_access");
VkPhysicalDeviceVulkan12Properties vulkan12Properties = {};
vulkan12Properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterizationAccess = {};
rasterizationAccess.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM;
rasterizationAccess.pNext = &vulkan12Properties;
VkPhysicalDeviceProperties2 properties = {};
properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties.pNext = &rasterizationAccess;
VkPhysicalDeviceFeatures features = {};
context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
if ( m_integerFormat )
{
if ((vulkan12Properties.framebufferIntegerColorSampleCounts & m_sampleCount) == 0 ||
(properties.properties.limits.sampledImageIntegerSampleCounts & m_sampleCount) == 0)
{
TCU_THROW(NotSupportedError, "Sample count not supported");
}
}
else
{
if ((properties.properties.limits.framebufferColorSampleCounts & m_sampleCount) == 0 ||
(properties.properties.limits.sampledImageColorSampleCounts & m_sampleCount) == 0)
{
TCU_THROW(NotSupportedError , "Sample count not supported");
}
}
/* sampleRateShading must be enabled to call fragment shader for all the samples in multisampling */
if ( (m_sampleCount != VK_SAMPLE_COUNT_1_BIT && !features.sampleRateShading) )
{
TCU_THROW(NotSupportedError , "sampleRateShading feature not supported");
}
/* Needed for gl_PrimitiveID */
if ( !features.geometryShader )
{
TCU_THROW(NotSupportedError , "geometryShader feature not supported");
}
if (properties.properties.limits.maxFragmentOutputAttachments < m_inputAttachmentNum ||
properties.properties.limits.maxPerStageDescriptorInputAttachments < m_inputAttachmentNum)
{
TCU_THROW(NotSupportedError , "Feedback attachment number not supported");
}
if (!m_explicitSync && !rasterizationAccess.rasterizationOrderColorAttachmentAccess)
{
TCU_THROW(NotSupportedError , "Implicit attachment access rasterization order not guaranteed for color attachments");
}
checkAdditionalRasterizationFlags(rasterizationAccess);
}
deUint32 AttachmentAccessOrderTestCase::getSampleNum(VkSampleCountFlagBits sampleCount)
{
deUint32 ret = 0;
switch(sampleCount)
{
case VK_SAMPLE_COUNT_1_BIT: ret = 1; break;
case VK_SAMPLE_COUNT_2_BIT: ret = 2; break;
case VK_SAMPLE_COUNT_4_BIT: ret = 4; break;
case VK_SAMPLE_COUNT_8_BIT: ret = 8; break;
case VK_SAMPLE_COUNT_16_BIT: ret = 16; break;
case VK_SAMPLE_COUNT_32_BIT: ret = 32; break;
case VK_SAMPLE_COUNT_64_BIT: ret = 64; break;
default: DE_ASSERT(false);
};
return ret;
}
void AttachmentAccessOrderTestInstance::RenderSubpass::createAttachments( int subpass, deUint32 inputAttachmentNum, deUint32 colorAttachmentNum,
VkSampleCountFlagBits sampleCount,
Context &context, vector<VkImageView> &views, VkDescriptorSetLayout *pDsetLayout,
const AttachmentAccessOrderTestCase *tc)
{
m_testCase = tc;
m_subpass = subpass;
m_sampleCount = sampleCount;
m_colorAttNum = colorAttachmentNum;
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
Allocator& allocator = context.getDefaultAllocator();
// Pipeline Layout
{
VkPushConstantRange pushConstantsInfo =
{
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
0, // uint32_t offset;
4, // uint32_t size;
};
if (m_testCase->hasDepthStencil())
{
pushConstantsInfo.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
}
const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineLayoutCreateFlags flags;
1u, // deUint32 descriptorSetCount;
pDsetLayout, // const VkDescriptorSetLayout* pSetLayouts;
m_subpass == 0 ? 1u : 0u, // deUint32 pushConstantRangeCount;
m_subpass == 0 ? &pushConstantsInfo : nullptr // const VkPushConstantRange* pPushConstantRanges;
};
m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
}
VkFormat attFormat = m_testCase->getColorFormat();
/* Same create info for all the color attachments */
VkImageCreateInfo colorImageCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
attFormat, // VkFormat format;
{ WIDTH, HEIGHT, 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
sampleCount, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
for (deUint32 i = 0; i < inputAttachmentNum; i++)
{
VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT;
/* Image for the DS attachment */
if (i >= colorAttachmentNum)
{
attFormat = m_testCase->getDSFormat();
colorImageCreateInfo.format = attFormat;
colorImageCreateInfo.usage &= ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
colorImageCreateInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
aspect = m_testCase->getDSAspect();
}
m_inputAtt.push_back(createImage(vk, device, &colorImageCreateInfo, DE_NULL));
VkImageViewCreateInfo colorTargetViewInfo =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
*m_inputAtt.back(), // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
attFormat, // VkFormat format;
makeComponentMappingRGBA(), // VkComponentMapping components;
{
aspect, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArrayLayer;
1u, // deUint32 arraySize;
}, // VkImageSubresourceRange subresourceRange;
};
m_inputAttMemory.push_back(allocator.allocate(getImageMemoryRequirements(vk, device, *m_inputAtt.back()), MemoryRequirement::Any));
VK_CHECK(vk.bindImageMemory(device, *m_inputAtt.back(), m_inputAttMemory.back()->getMemory(), m_inputAttMemory.back()->getOffset()));
m_inputAttView.push_back(createImageView(vk, device, &colorTargetViewInfo));
m_attachmentReferences.push_back({(deUint32)views.size(), VK_IMAGE_LAYOUT_GENERAL});
views.push_back(*m_inputAttView.back());
}
}
void AttachmentAccessOrderTestInstance::RenderSubpass::createPipeline(VkRenderPass renderPass, Context &context)
{
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const Unique<VkShaderModule> vs(createShaderModule(vk, device, context.getBinaryCollection().get(m_subpass == 0 ? "vert1" : "vert2"), 0));
const Unique<VkShaderModule> fs(createShaderModule(vk, device, context.getBinaryCollection().get(m_subpass == 0 ? "frag" : "frag_resolve"), 0));
const VkVertexInputBindingDescription vertexInputBindingDescription =
{
0, // deUint32 binding;
sizeof(tcu::Vec2), // deUint32 strideInBytes;
VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputStepRate stepRate;
};
const VkVertexInputAttributeDescription vertexInputAttributeDescription =
{
0u, // deUint32 location;
0u, // deUint32 binding;
VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
0u, // 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;
1u, // deUint32 attributeCount;
&vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
};
const std::vector<VkViewport> viewports(1, {0, 0, WIDTH, HEIGHT, 0, 1});
const std::vector<VkRect2D> scissors(1, { {0, 0}, {WIDTH, HEIGHT} });
const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineRasterizationStateCreateFlags flags;
VK_FALSE, // VkBool32 depthClampEnable;
VK_FALSE, // VkBool32 rasterizerDiscardEnable;
VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
VK_FALSE, // VkBool32 depthBiasEnable;
0.0f, // float depthBiasConstantFactor;
0.0f, // float depthBiasClamp;
0.0f, // float depthBiasSlopeFactor;
1.0f, // float lineWidth;
};
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_TRUE, // VkBool32 sampleShadingEnable;
1.0f, // float minSampleShading;
DE_NULL, // const VkSampleMask* pSampleMask;
VK_FALSE, // VkBool32 alphaToCoverageEnable;
VK_FALSE // VkBool32 alphaToOneEnable;
};
std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentState(m_colorAttNum,
{
false, // VkBool32 blendEnable;
VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
VK_BLEND_FACTOR_ONE, // VkBlend destBlendColor;
VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
VK_BLEND_FACTOR_ONE, // VkBlend destBlendAlpha;
VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
(VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT) // VkChannelFlags channelWriteMask;
});
const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
{
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
/* always needed */
m_testCase->getBlendStateFlags(), // VkPipelineColorBlendStateCreateFlags flags;
false, // VkBool32 logicOpEnable;
VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
(deUint32)colorBlendAttachmentState.size(), // deUint32 attachmentCount;
colorBlendAttachmentState.data(), // const VkPipelineColorBlendAttachmentState* pAttachments;
{ 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
};
VkStencilOpState stencilOpState =
{
VK_STENCIL_OP_ZERO, // VkStencilOp failOp;
VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp passOp;
VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp depthFailOp;
VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
0xff, // uint32_t compareMask;
0xff, // uint32_t writeMask;
0, // uint32_t reference;
};
VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
// VkStructureType sType;
DE_NULL, // const void* pNext;
m_testCase->getDSStateFlags(),
// VkPipelineDepthStencilStateCreateFlags flags;
VK_TRUE, // VkBool32 depthTestEnable;
VK_TRUE, // VkBool32 depthWriteEnable;
VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
VK_FALSE, // VkBool32 depthBoundsTestEnable;
VK_TRUE, // VkBool32 stencilTestEnable;
stencilOpState, // VkStencilOpState front;
stencilOpState, // VkStencilOpState back;
0.0f, // float minDepthBounds;
1.0f, // float maxDepthBounds;
};
m_pipeline = makeGraphicsPipeline( vk, // const DeviceInterface& vk
device, // const VkDevice device
*m_pipelineLayout, // const VkPipelineLayout pipelineLayout
*vs, // const VkShaderModule vertexShaderModule
DE_NULL, // const VkShaderModule tessellationControlShaderModule
DE_NULL, // const VkShaderModule tessellationEvalShaderModule
DE_NULL, // const VkShaderModule geometryShaderModule
*fs, // const VkShaderModule fragmentShaderModule
renderPass, // const VkRenderPass renderPass
viewports, // const std::vector<VkViewport>& viewports
scissors, // const std::vector<VkRect2D>& scissors
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,// const VkPrimitiveTopology topology
m_subpass, // const deUint32 subpass
0u, // const deUint32 patchControlPoints
&vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
&rasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
&multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
&depthStencilStateCreateInfo, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo,
&colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo,
DE_NULL); // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
}
static Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice& device)
{
const VkSamplerCreateInfo createInfo =
{
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_LINEAR, // VkSamplerMipmapMode mipmapMode;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
0.0f, // float mipLodBias;
VK_FALSE, // VkBool32 anisotropyEnable;
1.0f, // float maxAnisotropy;
VK_FALSE, // VkBool32 compareEnable;
VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
0.0f, // float minLod;
0.0f, // float maxLod;
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
VK_FALSE // VkBool32 unnormalizedCoordinates;
};
return createSampler(vk, device, &createInfo);
}
static Move<VkDescriptorSetLayout> makeDescriptorSetLayout(const DeviceInterface &vk, const VkDevice device, deUint32 attNum)
{
vector<VkDescriptorSetLayoutBinding> bindings(attNum,
{
0, // binding
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType
1u, // descriptorCount
VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
DE_NULL, // pImmutableSamplers
});
for (deUint32 i = 0; i < attNum; i++)
{
bindings[i].binding = i;
}
const VkDescriptorSetLayoutCreateInfo layoutCreateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
DE_NULL, // pNext
0u, // flags
attNum, // bindingCount
bindings.data(), // pBindings
};
return vk::createDescriptorSetLayout(vk, device, &layoutCreateInfo);
}
void AttachmentAccessOrderTestInstance::writeDescriptorSets()
{
deUint32 attNum = m_testCase->getInputAttachmentNum();
for (deUint32 i = 0 ; i < attNum ; i++ )
{
VkDescriptorImageInfo img_info = {};
img_info.sampler = *m_sampler;
img_info.imageView = *m_subpasses[0].m_inputAttView[i];
img_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
VkWriteDescriptorSet write = {};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.dstSet = *m_descSet;
write.dstBinding = i;
write.dstArrayElement = 0;
write.descriptorCount = 1;
write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
write.pImageInfo = &img_info;
m_vk.updateDescriptorSets(m_context.getDevice(), 1u, &write, 0u, DE_NULL);
}
}
void AttachmentAccessOrderTestInstance::addDependency( vector<VkSubpassDependency> &dependencies, deUint32 source, deUint32 dst,
VkPipelineStageFlags pipelineFlags, VkAccessFlags accessFlags)
{
dependencies.push_back({
source, //uint32_t srcSubpass;
dst, //uint32_t dstSubpass;
pipelineFlags, //VkPipelineStageFlags srcStageMask;
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, //VkPipelineStageFlags dstStageMask;
accessFlags, //VkAccessFlags srcAccessMask;
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, //VkAccessFlags dstAccessMask;
0, //VkDependencyFlags dependencyFlags;
});
}
Move<VkRenderPass> AttachmentAccessOrderTestInstance::createRenderPass(VkFormat attFormat)
{
const VkDevice device = m_context.getDevice();
vector<VkAttachmentDescription> attachmentDescs;
for (deUint32 subpass = 0; subpass < 2; subpass ++)
{
for (deUint32 i = 0 ; i < m_subpasses[subpass].getInputAttachmentNum(); i++)
{
VkFormat format = attFormat;
if (i >= m_subpasses[subpass].getColorAttachmentNum())
{
format = m_testCase->getDSFormat();
}
attachmentDescs.push_back({
0, // VkAttachmentDescriptionFlags flags;
format, // VkFormat format;
m_subpasses[subpass].m_sampleCount, // VkSampleCountFlagBits samples;
VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp stencilLoadOp;
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout finalLayout;
});
}
}
std::vector<VkSubpassDescription> subpasses(2, VkSubpassDescription{});
subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpasses[0].inputAttachmentCount = m_subpasses[0].getInputAttachmentNum();
subpasses[0].pInputAttachments = m_subpasses[0].m_attachmentReferences.data();
subpasses[0].colorAttachmentCount = m_subpasses[0].getColorAttachmentNum();
subpasses[0].pColorAttachments = m_subpasses[0].m_attachmentReferences.data();
subpasses[0].pDepthStencilAttachment = m_subpasses[0].getDepthStencilAttachment();
subpasses[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpasses[1].inputAttachmentCount = m_subpasses[0].getColorAttachmentNum();
subpasses[1].pInputAttachments = m_subpasses[0].m_attachmentReferences.data();
subpasses[1].colorAttachmentCount = m_subpasses[1].getColorAttachmentNum();
subpasses[1].pColorAttachments = m_subpasses[1].m_attachmentReferences.data();
/* self dependency for subpass 0 and dependency from subpass 0 to 1 */
vector<VkSubpassDependency> dependencies;
addDependency(dependencies, 0, 1, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
if (m_testCase->m_explicitSync)
{
addDependency(dependencies, 0, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
if (m_testCase->hasDepthStencil())
{
addDependency(dependencies, 0, 0, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
}
}
else
{
subpasses[0].flags = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM;
if (m_testCase->hasDepth())
{
subpasses[0].flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM;
}
else if (m_testCase->hasStencil())
{
subpasses[0].flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM;
}
}
VkRenderPassCreateInfo renderPassCreateInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
NULL, // const void* pNext;
0, // VkRenderPassCreateFlags flags;
(deUint32)attachmentDescs.size(), // uint32_t attachmentCount;
attachmentDescs.data(), // const VkAttachmentDescription* pAttachments;
(deUint32)subpasses.size(), // uint32_t subpassCount;
subpasses.data(), // const VkSubpassDescription* pSubpasses;
(deUint32)dependencies.size(), // uint32_t dependencyCount;
dependencies.data(), // const VkSubpassDependency* pDependencies;
};
return ::createRenderPass(m_vk, device, &renderPassCreateInfo);
}
void AttachmentAccessOrderTestInstance::createVertexBuffer()
{
deUint32 primitiveNum = m_testCase->m_overlapPrimitives ? AttachmentAccessOrderTestCase::ELEM_NUM * 2: 2;
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
const VkDevice device = m_context.getDevice();
Allocator& allocator = m_context.getDefaultAllocator();
std::vector<tcu::Vec2> vbo(3*primitiveNum);
for (deUint32 i=0; i < primitiveNum/2; i++)
{
vbo[i*6 + 0] = {-1, -1};
vbo[i*6 + 1] = { 1, -1};
vbo[i*6 + 2] = {-1, 1};
vbo[i*6 + 3] = { 1, 1};
vbo[i*6 + 4] = {-1, 1};
vbo[i*6 + 5] = { 1, -1};
}
const size_t dataSize = vbo.size() * sizeof(tcu::Vec2);
{
const VkBufferCreateInfo vertexBufferParams =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags;
dataSize, // VkDeviceSize size;
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_vertexBuffer = createBuffer(m_vk, device, &vertexBufferParams);
m_vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(m_vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible);
VK_CHECK(m_vk.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
}
/* Load vertices into vertex buffer */
deMemcpy(m_vertexBufferMemory->getHostPtr(), vbo.data(), dataSize);
flushAlloc(m_vk, device, *m_vertexBufferMemory);
}
void AttachmentAccessOrderTestInstance::createResultBuffer()
{
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
const VkDevice device = m_context.getDevice();
Allocator& allocator = m_context.getDefaultAllocator();
/* result buffer */
const VkBufferCreateInfo resultBufferInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags;
WIDTH * HEIGHT * sizeof(tcu::UVec2), // VkDeviceSize size;
VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
m_resultBuffer = createBuffer(m_vk, device, &resultBufferInfo);
m_resultBufferMemory = allocator.allocate( getBufferMemoryRequirements(m_vk, device, *m_resultBuffer), MemoryRequirement::HostVisible);
VK_CHECK(m_vk.bindBufferMemory(device, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
}
AttachmentAccessOrderTestInstance::AttachmentAccessOrderTestInstance( Context& context, const AttachmentAccessOrderTestCase *testCase)
: TestInstance(context)
, m_testCase (testCase)
, m_vk (m_context.getDeviceInterface())
, m_subpasses(2)
{
const VkDevice device = m_context.getDevice();
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
m_descSetLayout = makeDescriptorSetLayout(m_vk, device, m_testCase->getInputAttachmentNum());
m_descPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_testCase->getInputAttachmentNum())
.build(m_vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
m_descSet = makeDescriptorSet(m_vk, device, *m_descPool, *m_descSetLayout, nullptr);
vector<VkImageView> attachmentHandles;
VkDescriptorSetLayout dsetLayout = *m_descSetLayout;
m_subpasses[0].createAttachments( 0, m_testCase->getInputAttachmentNum(), m_testCase->getColorAttachmentNum(), m_testCase->m_sampleCount,
m_context, attachmentHandles, &dsetLayout, m_testCase);
m_subpasses[1].createAttachments(1, 1, 1, VK_SAMPLE_COUNT_1_BIT, m_context, attachmentHandles, &dsetLayout, m_testCase);
m_sampler = makeSampler(m_vk, device);
writeDescriptorSets();
m_renderPass = createRenderPass(m_testCase->getColorFormat());
m_framebuffer = makeFramebuffer(m_vk, device, *m_renderPass, (deUint32)attachmentHandles.size(), attachmentHandles.data(), WIDTH, HEIGHT, 1);
m_subpasses[0].createPipeline(*m_renderPass, m_context);
m_subpasses[1].createPipeline(*m_renderPass, m_context);
createVertexBuffer();
createResultBuffer();
m_cmdPool = createCommandPool(m_vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
m_cmdBuffer = allocateCommandBuffer(m_vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
}
AttachmentAccessOrderTestInstance::~AttachmentAccessOrderTestInstance (void)
{
}
void AttachmentAccessOrderTestInstance::addPipelineBarrier( VkCommandBuffer cmdBuffer,
VkImage image,
VkImageLayout oldLayout,
VkImageLayout newLayout,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageAspectFlags aspect)
{
VkImageMemoryBarrier barrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
srcAccessMask, // VkAccessFlags srcAccessMask;
dstAccessMask, // VkAccessFlags dstAccessMask;
oldLayout, // VkImageLayout oldLayout;
newLayout, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
image, // VkImage image;
{
aspect, //VkImageAspectFlags aspectMask;
0u, //uint32_t baseMipLevel;
1u, //uint32_t levelCount;
0u, //uint32_t baseArrayLayer;
1u, //uint32_t layerCount;
}, // VkImageSubresourceRange subresourceRange;
};
m_vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL,
0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
}
void AttachmentAccessOrderTestInstance::addClearColor(VkCommandBuffer cmdBuffer, VkImage image)
{
VkClearColorValue clearColor;
clearColor.float32[0] = 0.0;
clearColor.float32[1] = 0.0;
clearColor.float32[2] = 0.0;
clearColor.float32[3] = 1.0;
const VkImageSubresourceRange subresourceRange =
{
VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask;
0u, //uint32_t baseMipLevel;
1u, //uint32_t levelCount;
0u, //uint32_t baseArrayLayer;
1u, //uint32_t layerCount;
};
m_vk.cmdClearColorImage(cmdBuffer, image, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
}
void AttachmentAccessOrderTestInstance::addClearDepthStencil(VkCommandBuffer cmdBuffer, VkImage image)
{
VkClearDepthStencilValue clearValue;
clearValue.depth = 0.0;
clearValue.stencil = 0;
const VkImageSubresourceRange subresourceRange =
{
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, //VkImageAspectFlags aspectMask;
0u, //uint32_t baseMipLevel;
1u, //uint32_t levelCount;
0u, //uint32_t baseArrayLayer;
1u, //uint32_t layerCount;
};
m_vk.cmdClearDepthStencilImage(cmdBuffer, image, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &subresourceRange);
}
tcu::TestStatus AttachmentAccessOrderTestInstance::iterate (void)
{
const VkQueue queue = m_context.getUniversalQueue();
const VkDevice device = m_context.getDevice();
beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
for (deUint32 i=0; i < m_subpasses.size(); i++)
{
for (deUint32 j=0; j < m_subpasses[i].getColorAttachmentNum(); j++)
{
addPipelineBarrier( *m_cmdBuffer, *m_subpasses[i].m_inputAtt[j], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
addClearColor( *m_cmdBuffer, *m_subpasses[i].m_inputAtt[j]);
}
for (deUint32 j=m_subpasses[i].getColorAttachmentNum(); j < m_subpasses[i].getInputAttachmentNum(); j++)
{
addPipelineBarrier( *m_cmdBuffer, *m_subpasses[i].m_inputAtt[j], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
addClearDepthStencil( *m_cmdBuffer, *m_subpasses[i].m_inputAtt[j]);
}
}
const VkMemoryBarrier memBarrier =
{
VK_STRUCTURE_TYPE_MEMORY_BARRIER,
DE_NULL,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
};
m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT);
beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
const VkDeviceSize vertexBufferOffset = 0;
const VkBuffer vertexBuffer = *m_vertexBuffer;
m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[0].m_pipeline);
VkDescriptorSet dset = *m_descSet;
m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[0].m_pipelineLayout, 0, 1, &dset, 0, DE_NULL);
deUint32 numDraws = m_testCase->m_overlapDraws ? AttachmentAccessOrderTestCase::ELEM_NUM : 1;
deUint32 numPrimitives = m_testCase->m_overlapPrimitives ? 2 * AttachmentAccessOrderTestCase::ELEM_NUM : 2;
deUint32 numInstances = m_testCase->m_overlapInstances ? AttachmentAccessOrderTestCase::ELEM_NUM : 1;
for (deUint32 i=0; i < numDraws; i++)
{
m_vk.cmdPushConstants( *m_cmdBuffer, *m_subpasses[0].m_pipelineLayout,
VK_SHADER_STAGE_FRAGMENT_BIT | (m_testCase->hasDepthStencil() ? VK_SHADER_STAGE_VERTEX_BIT : 0),
0, 4, &i);
for (deUint32 j = 0; m_testCase->m_explicitSync && i != 0 && j < m_subpasses[0].getColorAttachmentNum(); j++)
{
addPipelineBarrier( *m_cmdBuffer, *m_subpasses[0].m_inputAtt[j], VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
for (deUint32 j = m_subpasses[0].getColorAttachmentNum(); m_testCase->m_explicitSync && i != 0 && j < m_subpasses[0].getInputAttachmentNum(); j++)
{
addPipelineBarrier( *m_cmdBuffer, *m_subpasses[0].m_inputAtt[j], VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
}
m_vk.cmdDraw(*m_cmdBuffer, numPrimitives * 3, numInstances, 0, 0);
}
m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[1].m_pipeline);
m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[1].m_pipelineLayout, 0, 1, &dset, 0, DE_NULL);
m_vk.cmdDraw(*m_cmdBuffer, 6, 1, 0, 0);
endRenderPass(m_vk, *m_cmdBuffer);
copyImageToBuffer( m_vk, *m_cmdBuffer, *m_subpasses[1].m_inputAtt[0], *m_resultBuffer, tcu::IVec2(WIDTH, HEIGHT), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_GENERAL);
endCommandBuffer(m_vk, *m_cmdBuffer);
submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
return validateResults(numDraws, numPrimitives, numInstances);
}
tcu::TestStatus AttachmentAccessOrderTestInstance::validateResults(deUint32 numDraws, deUint32 numPrimitives, deUint32 numInstances)
{
const VkDevice device = m_context.getDevice();
qpTestResult res = QP_TEST_RESULT_PASS;
invalidateAlloc(m_vk, device, *m_resultBufferMemory);
if (m_testCase->m_integerFormat)
{
tcu::UVec2 *resBuf = static_cast<tcu::UVec2 *> (m_resultBufferMemory->getHostPtr());
for (deUint32 y = 0; y < HEIGHT && res == QP_TEST_RESULT_PASS; y ++)
{
for (deUint32 x = 0; x < WIDTH && res == QP_TEST_RESULT_PASS; x ++)
{
tcu::UVec2 pixel = resBuf[y * WIDTH + x];
if (pixel[0] != 0 || pixel[1] != numDraws * numPrimitives/2 * numInstances)
{
res = QP_TEST_RESULT_FAIL;
}
}
}
}
else
{
tcu::Vec2 *resBuf = static_cast<tcu::Vec2 *> (m_resultBufferMemory->getHostPtr());
for (deUint32 y = 0; y < HEIGHT && res == QP_TEST_RESULT_PASS; y ++)
{
for (deUint32 x = 0; x < WIDTH && res == QP_TEST_RESULT_PASS; x ++)
{
tcu::Vec2 pixel = resBuf[y * WIDTH + x];
if (pixel[0] != 0 || pixel[1] != (float)(numDraws * numPrimitives/2 * numInstances))
{
res = QP_TEST_RESULT_FAIL;
}
}
}
}
return tcu::TestStatus(res, qpGetTestResultName(res));
}
} // anonymous ns
static void createRasterizationOrderAttachmentAccessTestVariations( tcu::TestContext& testCtx, tcu::TestCaseGroup *gr,
const string &prefix_name, const string &prefix_desc,
deUint32 inputNum, bool integerFormat, bool depth, bool stencil)
{
const struct
{
const std::string name;
const std::string description;
bool explicitSync;
bool overlapDraws;
bool overlapPrimitives;
bool overlapInstances;
} leafTestCreateParams[] =
{
{ "multi_draw_barriers", "Basic test with overlapping draw commands with barriers", true, true, false, false, },
{ "multi_draw", "Test with overlapping draw commands without barriers", false, true, false, false, },
{ "multi_primitives", "Test with a draw command with overlapping primitives", false, false, true, false, },
{ "multi_instances", "Test with a draw command with overlapping instances", false, false, false, true, },
{ "all", "Test with overlapping draw commands, each with overlapping primitives and instances", false, true, true, true, },
};
constexpr deUint32 leafTestCreateParamsNum = sizeof(leafTestCreateParams) / sizeof(leafTestCreateParams[0]);
VkSampleCountFlagBits sampleCountValues[] =
{
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,
};
constexpr deUint32 sampleCountValuesNum = sizeof(sampleCountValues) / sizeof(sampleCountValues[0]);
for (deUint32 i = 0; i < sampleCountValuesNum ; i++)
{
stringstream name;
stringstream desc;
name << prefix_name << "samples_" << AttachmentAccessOrderTestCase::getSampleNum(sampleCountValues[i]);
desc << prefix_desc << AttachmentAccessOrderTestCase::getSampleNum(sampleCountValues[i]) << " samples per pixel";
tcu::TestCaseGroup *subgr = new tcu::TestCaseGroup(testCtx, name.str().c_str(), desc.str().c_str());
for (deUint32 k = 0; k < leafTestCreateParamsNum; k++)
{
if (depth)
{
subgr->addChild(new AttachmentAccessOrderDepthTestCase( testCtx, leafTestCreateParams[k].name,
leafTestCreateParams[k].description,
leafTestCreateParams[k].explicitSync,
leafTestCreateParams[k].overlapDraws,
leafTestCreateParams[k].overlapPrimitives,
leafTestCreateParams[k].overlapInstances,
sampleCountValues[i]));
}
else if (stencil)
{
subgr->addChild(new AttachmentAccessOrderStencilTestCase( testCtx, leafTestCreateParams[k].name,
leafTestCreateParams[k].description,
leafTestCreateParams[k].explicitSync,
leafTestCreateParams[k].overlapDraws,
leafTestCreateParams[k].overlapPrimitives,
leafTestCreateParams[k].overlapInstances,
sampleCountValues[i]));
}
else
{
subgr->addChild(new AttachmentAccessOrderColorTestCase( testCtx, leafTestCreateParams[k].name,
leafTestCreateParams[k].description,
leafTestCreateParams[k].explicitSync,
leafTestCreateParams[k].overlapDraws,
leafTestCreateParams[k].overlapPrimitives,
leafTestCreateParams[k].overlapInstances,
sampleCountValues[i], inputNum, integerFormat));
}
}
gr->addChild(subgr);
}
}
static void createRasterizationOrderAttachmentAccessFormatTests(tcu::TestContext& testCtx, tcu::TestCaseGroup *gr, bool integerFormat)
{
const deUint32 inputNum[] = {1, 4, 8};
const deUint32 inputNumSize = sizeof(inputNum) / sizeof(inputNum[0]);
tcu::TestCaseGroup *formatGr;
if (integerFormat)
{
formatGr = new tcu::TestCaseGroup(testCtx, "format_integer", "Tests with an integer format" );
}
else
{
formatGr = new tcu::TestCaseGroup(testCtx, "format_float", "Tests with an float format" );
}
for (deUint32 i = 0; i < inputNumSize; i++)
{
stringstream numName;
stringstream numDesc;
numName << "attachments_" << inputNum[i] << "_";
numDesc << "Tests with " << inputNum[i] << " attachments and ";
createRasterizationOrderAttachmentAccessTestVariations(testCtx, formatGr, numName.str(), numDesc.str(), inputNum[i], integerFormat, false, false);
}
gr->addChild(formatGr);
}
tcu::TestCaseGroup* createRasterizationOrderAttachmentAccessTests(tcu::TestContext& testCtx)
{
/* Add the color tests */
tcu::TestCaseGroup *gr = new tcu::TestCaseGroup(testCtx, "rasterization_order_attachment_access", "Rasterization Order Attachment access tests");
createRasterizationOrderAttachmentAccessFormatTests(testCtx, gr, false);
createRasterizationOrderAttachmentAccessFormatTests(testCtx, gr, true);
/* Add the D/S tests */
tcu::TestCaseGroup *depth_gr = new tcu::TestCaseGroup(testCtx, "depth", "Tests depth rasterization order" );
tcu::TestCaseGroup *stencil_gr = new tcu::TestCaseGroup(testCtx, "stencil", "Tests stencil rasterization order" );
string name_prefix = "";
string desc_prefix = "Tests with ";
createRasterizationOrderAttachmentAccessTestVariations(testCtx, depth_gr, name_prefix, desc_prefix, 1, false, true, false);
createRasterizationOrderAttachmentAccessTestVariations(testCtx, stencil_gr, name_prefix, desc_prefix, 1, false, false, true);
gr->addChild(depth_gr);
gr->addChild(stencil_gr);
return gr;
}
} // rasterization
} // vkt