1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Danylo Piliaiev <danylo.piliaiev@gmail.com>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Test for conditional rendering of vkCmdClearAttachments
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktConditionalClearAttachmentTests.hpp"
26 #include "vktConditionalRenderingTestUtil.hpp"
27
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawTestCaseUtil.hpp"
30
31 #include "vktDrawBaseClass.hpp"
32
33 #include "tcuTestLog.hpp"
34 #include "tcuResource.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuRGBA.hpp"
38
39 #include "vkDefs.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkTypeUtil.hpp"
42
43 namespace vkt
44 {
45 namespace conditional
46 {
47 namespace
48 {
49
50 struct ConditionalTestSpec : public Draw::TestSpecBase
51 {
52 ConditionalData conditionalData;
53 };
54
55 class ConditionalClearAttachmentTest : public Draw::DrawTestsBaseClass
56 {
57 public:
58 typedef ConditionalTestSpec TestSpec;
59
60 ConditionalClearAttachmentTest (Context &context, ConditionalTestSpec testSpec);
61
62 virtual tcu::TestStatus iterate (void);
63 protected:
64 const ConditionalData m_conditionalData;
65 de::SharedPtr<Draw::Buffer> m_conditionalBuffer;
66
67 vk::Move<vk::VkCommandBuffer> m_secondaryCmdBuffer;
68 };
69
ConditionalClearAttachmentTest(Context & context,ConditionalTestSpec testSpec)70 ConditionalClearAttachmentTest::ConditionalClearAttachmentTest (Context &context, ConditionalTestSpec testSpec)
71 : Draw::DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], false, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
72 , m_conditionalData(testSpec.conditionalData)
73 {
74 checkConditionalRenderingCapabilities(context, m_conditionalData);
75
76 m_data.push_back(Draw::VertexElementData(tcu::Vec4(0.0f), tcu::Vec4(0.0f), 0));
77
78 initialize();
79
80 m_secondaryCmdBuffer = vk::allocateCommandBuffer(m_vk, m_context.getDevice(), *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
81 }
82
iterate(void)83 tcu::TestStatus ConditionalClearAttachmentTest::iterate (void)
84 {
85 tcu::TestLog& log = m_context.getTestContext().getLog();
86 const vk::VkQueue queue = m_context.getUniversalQueue();
87 const vk::VkDevice device = m_context.getDevice();
88
89 const tcu::Vec4 clearColor = tcu::RGBA::black().toVec();
90 const tcu::Vec4 drawColor = tcu::RGBA::blue().toVec();
91
92 const bool useSecondaryCmdBuffer = m_conditionalData.conditionInherited || m_conditionalData.conditionInSecondaryCommandBuffer;
93 beginRender(useSecondaryCmdBuffer ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : vk::VK_SUBPASS_CONTENTS_INLINE);
94
95 vk::VkCommandBuffer targetCmdBuffer = *m_cmdBuffer;
96
97 if (useSecondaryCmdBuffer)
98 {
99 const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo =
100 {
101 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
102 DE_NULL,
103 m_conditionalData.conditionInherited ? VK_TRUE : VK_FALSE // conditionalRenderingEnable
104 };
105
106 const vk::VkCommandBufferInheritanceInfo inheritanceInfo =
107 {
108 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
109 &conditionalRenderingInheritanceInfo,
110 *m_renderPass, // renderPass
111 0u, // subpass
112 *m_framebuffer, // framebuffer
113 VK_FALSE, // occlusionQueryEnable
114 (vk::VkQueryControlFlags)0u, // queryFlags
115 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
116 };
117
118 const vk::VkCommandBufferBeginInfo commandBufferBeginInfo =
119 {
120 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
121 DE_NULL,
122 vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
123 &inheritanceInfo
124 };
125
126 m_vk.beginCommandBuffer(*m_secondaryCmdBuffer, &commandBufferBeginInfo);
127
128 targetCmdBuffer = *m_secondaryCmdBuffer;
129 }
130
131 m_vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
132
133 const vk::VkClearAttachment clearAttachment =
134 {
135 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
136 0u, // deUint32 colorAttachment;
137 vk::makeClearValueColor(drawColor) // VkClearValue clearValue;
138 };
139
140 const vk::VkClearRect rect =
141 {
142 vk::makeRect2D(WIDTH, HEIGHT), // VkRect2D rect;
143 0u, // uint32_t baseArrayLayer;
144 1u, // uint32_t layerCount;
145 };
146
147 m_conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);
148
149 if (m_conditionalData.conditionInSecondaryCommandBuffer)
150 {
151 beginConditionalRendering(m_vk, *m_secondaryCmdBuffer, *m_conditionalBuffer, m_conditionalData);
152 m_vk.cmdClearAttachments(*m_secondaryCmdBuffer, 1, &clearAttachment, 1, &rect);
153 m_vk.cmdEndConditionalRenderingEXT(*m_secondaryCmdBuffer);
154 m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
155 }
156 else if (m_conditionalData.conditionInherited)
157 {
158 m_vk.cmdClearAttachments(*m_secondaryCmdBuffer, 1, &clearAttachment, 1, &rect);
159 m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
160 }
161
162 if (m_conditionalData.conditionInPrimaryCommandBuffer)
163 {
164 beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);
165
166 if (m_conditionalData.conditionInherited)
167 {
168 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
169 }
170 else
171 {
172 m_vk.cmdClearAttachments(*m_cmdBuffer, 1, &clearAttachment, 1, &rect);
173 }
174
175 m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
176 }
177 else if (useSecondaryCmdBuffer)
178 {
179 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
180 }
181
182 endRender();
183 endCommandBuffer(m_vk, *m_cmdBuffer);
184
185 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
186
187 // Validation
188 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
189 referenceFrame.allocLevel(0);
190
191 const deInt32 frameWidth = referenceFrame.getWidth();
192 const deInt32 frameHeight = referenceFrame.getHeight();
193
194 tcu::clear(referenceFrame.getLevel(0), clearColor);
195
196 const tcu::Vec4 referenceColor = m_conditionalData.expectCommandExecution ?
197 drawColor : clearColor;
198
199 for (int y = 0; y < frameHeight; y++)
200 {
201 for (int x = 0; x < frameWidth; x++)
202 {
203 referenceFrame.getLevel(0).setPixel(referenceColor, x, y);
204 }
205 }
206
207 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
208 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
209 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
210
211 qpTestResult res = QP_TEST_RESULT_PASS;
212
213 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
214 referenceFrame.getLevel(0), renderedFrame, 0.05f,
215 tcu::COMPARE_LOG_RESULT))
216 {
217 res = QP_TEST_RESULT_FAIL;
218 }
219
220 return tcu::TestStatus(res, qpGetTestResultName(res));
221 }
222
223 } // anonymous
224
ConditionalClearAttachmentTests(tcu::TestContext & testCtx)225 ConditionalClearAttachmentTests::ConditionalClearAttachmentTests (tcu::TestContext &testCtx)
226 : TestCaseGroup (testCtx, "clear_attachments", "vkCmdClearAttachments with conditional rendering")
227 {
228 /* Left blank on purpose */
229 }
230
~ConditionalClearAttachmentTests(void)231 ConditionalClearAttachmentTests::~ConditionalClearAttachmentTests (void) {}
232
init(void)233 void ConditionalClearAttachmentTests::init (void)
234 {
235 for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
236 {
237 const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];
238
239 tcu::TestCaseGroup* conditionalDrawRootGroup = new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str(), "");
240
241 ConditionalTestSpec testSpec;
242 testSpec.conditionalData = conditionData;
243 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
244 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
245
246 conditionalDrawRootGroup->addChild(new Draw::InstanceFactory<ConditionalClearAttachmentTest>(m_testCtx, "clear_attachments", "", testSpec));
247
248 addChild(conditionalDrawRootGroup);
249 }
250 }
251
252 } // conditional
253 } // vkt
254