1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2017 Google Inc.
7 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Differing iterpolation decorations tests
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktDrawDifferingInterpolationTests.hpp"
27
28 #include "vktDrawBaseClass.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vktTestGroupUtil.hpp"
33
34 #include "deDefs.h"
35 #include "deRandom.hpp"
36 #include "deString.h"
37
38 #include "tcuTestCase.hpp"
39 #include "tcuRGBA.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuStringTemplate.hpp"
43
44 #include "rrRenderer.hpp"
45
46 #include <string>
47 #include <sstream>
48
49 namespace vkt
50 {
51 namespace Draw
52 {
53 namespace
54 {
55 using namespace vk;
56 using namespace std;
57
58 struct DrawParams
59 {
60 string vertShader;
61 string fragShader;
62 string refVertShader;
63 string refFragShader;
64 bool useDynamicRendering;
65 };
66
67 class DrawTestInstance : public TestInstance
68 {
69 public:
70 DrawTestInstance (Context& context, const DrawParams& data);
71 ~DrawTestInstance (void);
72 tcu::TestStatus iterate (void);
73 private:
74 DrawParams m_data;
75
76 enum
77 {
78 WIDTH = 256,
79 HEIGHT = 256
80 };
81 };
82
DrawTestInstance(Context & context,const DrawParams & data)83 DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data)
84 : vkt::TestInstance (context)
85 , m_data (data)
86 {
87 }
88
~DrawTestInstance(void)89 DrawTestInstance::~DrawTestInstance (void)
90 {
91 }
92
93 class DrawTestCase : public TestCase
94 {
95 public:
96 DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data);
97 ~DrawTestCase (void);
98 virtual void initPrograms (SourceCollections& programCollection) const;
99 virtual void checkSupport (Context& context) const;
100 virtual TestInstance* createInstance (Context& context) const;
101
102 private:
103 DrawParams m_data;
104 };
105
DrawTestCase(tcu::TestContext & context,const char * name,const char * desc,const DrawParams data)106 DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data)
107 : vkt::TestCase (context, name, desc)
108 , m_data (data)
109 {
110 }
111
~DrawTestCase(void)112 DrawTestCase::~DrawTestCase (void)
113 {
114 }
115
initPrograms(SourceCollections & programCollection) const116 void DrawTestCase::initPrograms (SourceCollections& programCollection) const
117 {
118 const tcu::StringTemplate vertShader (string(
119 "#version 430\n"
120 "layout(location = 0) in vec4 in_position;\n"
121 "layout(location = 1) in vec4 in_color;\n"
122 "layout(location = 0) ${qualifier:opt} out vec4 out_color;\n"
123 "out gl_PerVertex {\n"
124 " vec4 gl_Position;\n"
125 " float gl_PointSize;\n"
126 "};\n"
127 "void main() {\n"
128 " gl_PointSize = 1.0;\n"
129 " gl_Position = in_position;\n"
130 " out_color = in_color;\n"
131 "}\n"));
132
133 const tcu::StringTemplate fragShader (string(
134 "#version 430\n"
135 "layout(location = 0) ${qualifier:opt} in vec4 in_color;\n"
136 "layout(location = 0) out vec4 out_color;\n"
137 "void main()\n"
138 "{\n"
139 " out_color = in_color;\n"
140 "}\n"));
141
142 map<string, string> empty;
143 map<string, string> flat;
144 flat["qualifier"] = "flat";
145 map<string, string> noPerspective;
146 noPerspective["qualifier"] = "noperspective";
147
148 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(empty));
149 programCollection.glslSources.add("vertFlatColor") << glu::VertexSource(vertShader.specialize(flat));
150 programCollection.glslSources.add("vertNoPerspective") << glu::VertexSource(vertShader.specialize(noPerspective));
151 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(empty));
152 programCollection.glslSources.add("fragFlatColor") << glu::FragmentSource(fragShader.specialize(flat));
153 programCollection.glslSources.add("fragNoPerspective") << glu::FragmentSource(fragShader.specialize(noPerspective));
154 }
155
checkSupport(Context & context) const156 void DrawTestCase::checkSupport(Context& context) const
157 {
158 if (m_data.useDynamicRendering)
159 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
160 }
161
createInstance(Context & context) const162 TestInstance* DrawTestCase::createInstance (Context& context) const
163 {
164 return new DrawTestInstance(context, m_data);
165 }
166
iterate(void)167 tcu::TestStatus DrawTestInstance::iterate (void)
168 {
169 tcu::ConstPixelBufferAccess frames[2];
170 de::SharedPtr<Image> colorTargetImages[2];
171 const string vertShaderNames[2] = { m_data.vertShader, m_data.refVertShader };
172 const string fragShaderNames[2] = { m_data.fragShader, m_data.refFragShader };
173 tcu::TestLog &log = m_context.getTestContext().getLog();
174
175 // Run two iterations with shaders that have different interpolation decorations. Images should still match.
176 for (deUint32 frameIdx = 0; frameIdx < DE_LENGTH_OF_ARRAY(frames); frameIdx++)
177 {
178 const DeviceInterface& vk = m_context.getDeviceInterface();
179 const VkDevice device = m_context.getDevice();
180 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
181 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
182 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
183 const Unique<VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get(vertShaderNames[frameIdx].c_str()), 0));
184 const Unique<VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get(fragShaderNames[frameIdx].c_str()), 0));
185 const VkFormat targetImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
186 de::SharedPtr<Buffer> vertexBuffer;
187 Move<VkRenderPass> renderPass;
188 Move<VkImageView> colorTargetView;
189 Move<VkFramebuffer> framebuffer;
190 Move<VkPipeline> pipeline;
191
192 // Create color buffer image.
193 {
194 const VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
195 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, targetImageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
196 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
197 colorTargetImages[frameIdx] = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
198 }
199
200 const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[frameIdx]->object(), VK_IMAGE_VIEW_TYPE_2D, targetImageFormat);
201 colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
202
203 // Create render pass and frame buffer.
204 if (!m_data.useDynamicRendering)
205 {
206 RenderPassCreateInfo renderPassCreateInfo;
207 renderPassCreateInfo.addAttachment(AttachmentDescription(targetImageFormat,
208 VK_SAMPLE_COUNT_1_BIT,
209 VK_ATTACHMENT_LOAD_OP_LOAD,
210 VK_ATTACHMENT_STORE_OP_STORE,
211 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
212 VK_ATTACHMENT_STORE_OP_STORE,
213 VK_IMAGE_LAYOUT_GENERAL,
214 VK_IMAGE_LAYOUT_GENERAL));
215
216 const VkAttachmentReference colorAttachmentRef = { 0, VK_IMAGE_LAYOUT_GENERAL };
217 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
218 0,
219 0,
220 DE_NULL,
221 1,
222 &colorAttachmentRef,
223 DE_NULL,
224 AttachmentReference(),
225 0,
226 DE_NULL));
227
228 renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
229
230 vector<VkImageView> colorAttachments { *colorTargetView };
231 const FramebufferCreateInfo framebufferCreateInfo (*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
232 framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
233 }
234
235 // Create vertex buffer.
236 {
237 const PositionColorVertex vertices[] =
238 {
239 PositionColorVertex(
240 tcu::Vec4(-0.8f, -0.7f, 1.0f, 1.0f), // Coord
241 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)), // Color
242
243 PositionColorVertex(
244 tcu::Vec4(0.0f, 0.4f, 0.5f, 0.5f), // Coord
245 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)), // Color
246
247 PositionColorVertex(
248 tcu::Vec4(0.8f, -0.5f, 1.0f, 1.0f), // Coord
249 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)) // Color
250 };
251
252 const VkDeviceSize dataSize = DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionColorVertex);
253 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
254 deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
255
256 deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
257 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
258 }
259
260 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
261 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
262
263 // Create pipeline
264 {
265 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
266
267 VkViewport viewport = makeViewport(WIDTH, HEIGHT);
268 VkRect2D scissor = makeRect2D(WIDTH, HEIGHT);
269
270 const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX };
271
272 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
273 {
274 { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
275 { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float)* 4) }
276 };
277
278 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
279
280 PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
281 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
282 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
283 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
284 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
285 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
286 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
287 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
288 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
289 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
290
291 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
292 {
293 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
294 DE_NULL,
295 0u,
296 1u,
297 &targetImageFormat,
298 VK_FORMAT_UNDEFINED,
299 VK_FORMAT_UNDEFINED
300 };
301
302 if (m_data.useDynamicRendering)
303 pipelineCreateInfo.pNext = &renderingCreateInfo;
304
305 pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
306 }
307
308 // Queue draw and read results.
309 {
310 const VkQueue queue = m_context.getUniversalQueue();
311 const VkClearValue clearColor = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
312 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
313 const VkMemoryBarrier memBarrier =
314 {
315 VK_STRUCTURE_TYPE_MEMORY_BARRIER,
316 DE_NULL,
317 VK_ACCESS_TRANSFER_WRITE_BIT,
318 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
319 };
320 const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT);
321 const VkDeviceSize vertexBufferOffset = 0;
322 const VkBuffer buffer = vertexBuffer->object();
323 const VkOffset3D zeroOffset = { 0, 0, 0 };
324
325 beginCommandBuffer(vk, *cmdBuffer, 0u);
326
327 initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[frameIdx]->object(), VK_IMAGE_LAYOUT_GENERAL,
328 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
329
330 vk.cmdClearColorImage(*cmdBuffer, colorTargetImages[frameIdx]->object(),
331 VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &subresourceRange);
332
333 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
334 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
335 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
336
337 if (m_data.useDynamicRendering)
338 beginRendering(vk, *cmdBuffer, *colorTargetView, renderArea, clearColor);
339 else
340 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea);
341
342 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
343 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
344 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
345
346 if (m_data.useDynamicRendering)
347 endRendering(vk, *cmdBuffer);
348 else
349 endRenderPass(vk, *cmdBuffer);
350
351 endCommandBuffer(vk, *cmdBuffer);
352
353 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
354
355 frames[frameIdx] = colorTargetImages[frameIdx]->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
356 }
357 }
358
359 qpTestResult res = QP_TEST_RESULT_PASS;
360
361 if (!tcu::intThresholdCompare(log, "Result", "Image comparison result", frames[0], frames[1], tcu::UVec4(0), tcu::COMPARE_LOG_RESULT))
362 res = QP_TEST_RESULT_FAIL;
363
364 return tcu::TestStatus(res, qpGetTestResultName(res));
365 }
366
createTests(tcu::TestCaseGroup * testGroup,bool useDynamicRendering)367 void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
368 {
369 tcu::TestContext& testCtx = testGroup->getTestContext();
370 const DrawParams paramsFlat0 = { "vert", "fragFlatColor", "vertFlatColor", "fragFlatColor", useDynamicRendering };
371 const DrawParams paramsFlat1 = { "vertFlatColor", "frag", "vert", "frag", useDynamicRendering };
372
373 const DrawParams paramsNoPerspective0 = { "vert", "fragNoPerspective", "vertNoPerspective", "fragNoPerspective", useDynamicRendering };
374 const DrawParams paramsNoPerspective1 = { "vertNoPerspective", "frag", "vert", "frag", useDynamicRendering };
375
376 testGroup->addChild(new DrawTestCase(testCtx, "flat_0", "Mismatching flat interpolation testcase 0.", paramsFlat0));
377 testGroup->addChild(new DrawTestCase(testCtx, "flat_1", "Mismatching flat interpolation testcase 1.", paramsFlat1));
378
379 testGroup->addChild(new DrawTestCase(testCtx, "noperspective_0", "Mismatching noperspective interpolation testcase 0.", paramsNoPerspective0));
380 testGroup->addChild(new DrawTestCase(testCtx, "noperspective_1", "Mismatching noperspective interpolation testcase 1.", paramsNoPerspective1));
381 }
382
383 } // anonymous
384
createDifferingInterpolationTests(tcu::TestContext & testCtx,bool useDynamicRendering)385 tcu::TestCaseGroup* createDifferingInterpolationTests (tcu::TestContext& testCtx, bool useDynamicRendering)
386 {
387 return createTestGroup(testCtx, "differing_interpolation", "Tests for mismatched interpolation decorations.", createTests, useDynamicRendering);
388 }
389
390 } // Draw
391 } // vkt
392