1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 The Android Open Source Project
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 Use of gl_Layer in Vertex and Tessellation Shaders
23 * (part of VK_EXT_ShaderViewportIndexLayer)
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktDrawShaderLayerTests.hpp"
27
28 #include "vktDrawBaseClass.hpp"
29 #include "vktTestCaseUtil.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39
40 #include "tcuTestLog.hpp"
41 #include "tcuVector.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuTextureUtil.hpp"
44
45 #include "deUniquePtr.hpp"
46 #include "deMath.h"
47
48 #include <vector>
49
50 namespace vkt
51 {
52 namespace Draw
53 {
54 using namespace vk;
55 using de::UniquePtr;
56 using de::MovePtr;
57 using de::SharedPtr;
58 using tcu::Vec4;
59 using tcu::Vec2;
60 using tcu::UVec2;
61 using tcu::UVec4;
62
63 namespace
64 {
65
66 enum Constants
67 {
68 MIN_MAX_FRAMEBUFFER_LAYERS = 256, //!< Minimum number of framebuffer layers.
69 MIN_MAX_VIEWPORTS = 16, //!< Minimum number of viewports for an implementation supporting multiViewport.
70 };
71
72 template<typename T>
sizeInBytes(const std::vector<T> & vec)73 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
74 {
75 return vec.size() * sizeof(vec[0]);
76 }
77
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)78 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize,
79 const VkBufferUsageFlags usage)
80 {
81 const VkBufferCreateInfo bufferCreateInfo =
82 {
83 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
84 DE_NULL, // const void* pNext;
85 (VkBufferCreateFlags)0, // VkBufferCreateFlags flags;
86 bufferSize, // VkDeviceSize size;
87 usage, // VkBufferUsageFlags usage;
88 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
89 0u, // deUint32 queueFamilyIndexCount;
90 DE_NULL, // const deUint32* pQueueFamilyIndices;
91 };
92 return bufferCreateInfo;
93 }
94
makePipelineLayout(const DeviceInterface & vk,const VkDevice device)95 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
96 const VkDevice device)
97 {
98 const VkPipelineLayoutCreateInfo info =
99 {
100 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
101 DE_NULL, // const void* pNext;
102 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
103 0u, // deUint32 setLayoutCount;
104 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
105 0u, // deUint32 pushConstantRangeCount;
106 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
107 };
108 return createPipelineLayout(vk, device, &info);
109 }
110
makeImageView(const DeviceInterface & vk,const VkDevice vkDevice,const VkImage image,const VkImageViewType viewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)111 Move<VkImageView> makeImageView (const DeviceInterface& vk,
112 const VkDevice vkDevice,
113 const VkImage image,
114 const VkImageViewType viewType,
115 const VkFormat format,
116 const VkImageSubresourceRange subresourceRange)
117 {
118 const VkImageViewCreateInfo imageViewParams =
119 {
120 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
121 DE_NULL, // const void* pNext;
122 (VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags;
123 image, // VkImage image;
124 viewType, // VkImageViewType viewType;
125 format, // VkFormat format;
126 makeComponentMappingRGBA(), // VkComponentMapping components;
127 subresourceRange, // VkImageSubresourceRange subresourceRange;
128 };
129 return createImageView(vk, vkDevice, &imageViewParams);
130 }
131
beginCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)132 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
133 {
134 const VkCommandBufferBeginInfo info =
135 {
136 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
137 DE_NULL, // const void* pNext;
138 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
139 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
140 };
141 VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
142 }
143
submitCommandsAndWait(const DeviceInterface & vk,const VkDevice device,const VkQueue queue,const VkCommandBuffer commandBuffer)144 void submitCommandsAndWait (const DeviceInterface& vk,
145 const VkDevice device,
146 const VkQueue queue,
147 const VkCommandBuffer commandBuffer)
148 {
149 const Unique<VkFence> fence(createFence(vk, device));
150
151 const VkSubmitInfo submitInfo =
152 {
153 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
154 DE_NULL, // const void* pNext;
155 0u, // uint32_t waitSemaphoreCount;
156 DE_NULL, // const VkSemaphore* pWaitSemaphores;
157 DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
158 1u, // uint32_t commandBufferCount;
159 &commandBuffer, // const VkCommandBuffer* pCommandBuffers;
160 0u, // uint32_t signalSemaphoreCount;
161 DE_NULL, // const VkSemaphore* pSignalSemaphores;
162 };
163 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
164 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
165 }
166
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const deUint32 width,const deUint32 height,const deUint32 layers=1u)167 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk,
168 const VkDevice device,
169 const VkRenderPass renderPass,
170 const deUint32 attachmentCount,
171 const VkImageView* pAttachments,
172 const deUint32 width,
173 const deUint32 height,
174 const deUint32 layers = 1u)
175 {
176 const VkFramebufferCreateInfo framebufferInfo = {
177 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
178 DE_NULL, // const void* pNext;
179 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
180 renderPass, // VkRenderPass renderPass;
181 attachmentCount, // uint32_t attachmentCount;
182 pAttachments, // const VkImageView* pAttachments;
183 width, // uint32_t width;
184 height, // uint32_t height;
185 layers, // uint32_t layers;
186 };
187
188 return createFramebuffer(vk, device, &framebufferInfo);
189 }
190
bindImage(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkImage image,const MemoryRequirement requirement)191 MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
192 {
193 MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
194 VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
195 return alloc;
196 }
197
makeImage(const vk::DeviceInterface & vk,const vk::VkDevice device,const vk::VkImageCreateInfo & createInfo)198 inline vk::Move<vk::VkImage> makeImage (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkImageCreateInfo& createInfo)
199 {
200 return createImage(vk, device, &createInfo);
201 }
202
makeImageCreateInfo(const VkFormat format,const UVec2 & size,const deUint32 numLayers,VkImageUsageFlags usage)203 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, const deUint32 numLayers, VkImageUsageFlags usage)
204 {
205 const VkImageCreateInfo imageParams =
206 {
207 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
208 DE_NULL, // const void* pNext;
209 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
210 VK_IMAGE_TYPE_2D, // VkImageType imageType;
211 format, // VkFormat format;
212 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
213 1u, // deUint32 mipLevels;
214 numLayers, // deUint32 arrayLayers;
215 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
216 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
217 usage, // VkImageUsageFlags usage;
218 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
219 0u, // deUint32 queueFamilyIndexCount;
220 DE_NULL, // const deUint32* pQueueFamilyIndices;
221 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
222 };
223 return imageParams;
224 }
225
226 //! A single-attachment, single-subpass render pass.
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)227 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
228 const VkDevice device,
229 const VkFormat colorFormat)
230 {
231 const VkAttachmentDescription colorAttachmentDescription =
232 {
233 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
234 colorFormat, // VkFormat format;
235 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
236 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
237 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
238 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
239 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
240 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
241 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
242 };
243
244 const VkAttachmentReference colorAttachmentRef =
245 {
246 0u, // deUint32 attachment;
247 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
248 };
249
250 const VkSubpassDescription subpassDescription =
251 {
252 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
253 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
254 0u, // deUint32 inputAttachmentCount;
255 DE_NULL, // const VkAttachmentReference* pInputAttachments;
256 1u, // deUint32 colorAttachmentCount;
257 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
258 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
259 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
260 0u, // deUint32 preserveAttachmentCount;
261 DE_NULL // const deUint32* pPreserveAttachments;
262 };
263
264 const VkRenderPassCreateInfo renderPassInfo =
265 {
266 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
267 DE_NULL, // const void* pNext;
268 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
269 1u, // deUint32 attachmentCount;
270 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
271 1u, // deUint32 subpassCount;
272 &subpassDescription, // const VkSubpassDescription* pSubpasses;
273 0u, // deUint32 dependencyCount;
274 DE_NULL // const VkSubpassDependency* pDependencies;
275 };
276
277 return createRenderPass(vk, device, &renderPassInfo);
278 }
279
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule tessellationControlModule,const VkShaderModule tessellationEvaluationModule,const VkShaderModule fragmentModule,const UVec2 renderSize)280 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
281 const VkDevice device,
282 const VkPipelineLayout pipelineLayout,
283 const VkRenderPass renderPass,
284 const VkShaderModule vertexModule,
285 const VkShaderModule tessellationControlModule,
286 const VkShaderModule tessellationEvaluationModule,
287 const VkShaderModule fragmentModule,
288 const UVec2 renderSize)
289 {
290 const VkVertexInputBindingDescription vertexInputBindingDescription =
291 {
292 0u, // uint32_t binding;
293 sizeof(PositionColorVertex), // uint32_t stride;
294 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
295 };
296
297 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
298 {
299 {
300 0u, // uint32_t location;
301 0u, // uint32_t binding;
302 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
303 0u, // uint32_t offset;
304 },
305 {
306 1u, // uint32_t location;
307 0u, // uint32_t binding;
308 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
309 sizeof(Vec4), // uint32_t offset;
310 },
311 };
312
313 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
314 {
315 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
316 DE_NULL, // const void* pNext;
317 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
318 1u, // uint32_t vertexBindingDescriptionCount;
319 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
320 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
321 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
322 };
323
324 const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
325
326 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
327 {
328 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
329 DE_NULL, // const void* pNext;
330 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
331 useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
332 VK_FALSE, // VkBool32 primitiveRestartEnable;
333 };
334
335
336 VkViewport viewport = makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
337 VkRect2D rectScissor = { { 0, 0 }, { renderSize.x(), renderSize.y() } };
338
339 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
340 {
341 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
342 DE_NULL, // const void* pNext;
343 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
344 1u, // uint32_t viewportCount;
345 &viewport, // const VkViewport* pViewports;
346 1u, // uint32_t scissorCount;
347 &rectScissor, // const VkRect2D* pScissors;
348 };
349
350 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
351 {
352 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
353 DE_NULL, // const void* pNext;
354 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
355 VK_FALSE, // VkBool32 depthClampEnable;
356 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
357 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
358 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
359 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
360 VK_FALSE, // VkBool32 depthBiasEnable;
361 0.0f, // float depthBiasConstantFactor;
362 0.0f, // float depthBiasClamp;
363 0.0f, // float depthBiasSlopeFactor;
364 1.0f, // float lineWidth;
365 };
366
367 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
368 {
369 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
370 DE_NULL, // const void* pNext;
371 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
372 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
373 VK_FALSE, // VkBool32 sampleShadingEnable;
374 0.0f, // float minSampleShading;
375 DE_NULL, // const VkSampleMask* pSampleMask;
376 VK_FALSE, // VkBool32 alphaToCoverageEnable;
377 VK_FALSE // VkBool32 alphaToOneEnable;
378 };
379
380 const VkStencilOpState stencilOpState = makeStencilOpState(
381 VK_STENCIL_OP_KEEP, // stencil fail
382 VK_STENCIL_OP_KEEP, // depth & stencil pass
383 VK_STENCIL_OP_KEEP, // depth only fail
384 VK_COMPARE_OP_ALWAYS, // compare op
385 0u, // compare mask
386 0u, // write mask
387 0u); // reference
388
389 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
390 {
391 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
392 DE_NULL, // const void* pNext;
393 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
394 VK_FALSE, // VkBool32 depthTestEnable;
395 VK_FALSE, // VkBool32 depthWriteEnable;
396 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
397 VK_FALSE, // VkBool32 depthBoundsTestEnable;
398 VK_FALSE, // VkBool32 stencilTestEnable;
399 stencilOpState, // VkStencilOpState front;
400 stencilOpState, // VkStencilOpState back;
401 0.0f, // float minDepthBounds;
402 1.0f, // float maxDepthBounds;
403 };
404
405 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
406 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
407 {
408 VK_FALSE, // VkBool32 blendEnable;
409 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
410 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
411 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
412 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
413 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
414 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
415 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
416 };
417
418 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
419 {
420 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
421 DE_NULL, // const void* pNext;
422 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
423 VK_FALSE, // VkBool32 logicOpEnable;
424 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
425 1u, // deUint32 attachmentCount;
426 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
427 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
428 };
429
430 const VkPipelineShaderStageCreateInfo pShaderStages[] =
431 {
432 {
433 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
434 DE_NULL, // const void* pNext;
435 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
436 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
437 vertexModule, // VkShaderModule module;
438 "main", // const char* pName;
439 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
440 },
441 {
442 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
443 DE_NULL, // const void* pNext;
444 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
445 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
446 fragmentModule, // VkShaderModule module;
447 "main", // const char* pName;
448 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
449 },
450 {
451 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
452 DE_NULL, // const void* pNext;
453 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
454 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage;
455 tessellationControlModule, // VkShaderModule module;
456 "main", // const char* pName;
457 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
458 },
459 {
460 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
461 DE_NULL, // const void* pNext;
462 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
463 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage;
464 tessellationEvaluationModule, // VkShaderModule module;
465 "main", // const char* pName;
466 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
467 },
468 };
469
470 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
471 {
472 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
473 DE_NULL, // const void* pNext;
474 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
475 3, // uint32_t patchControlPoints;
476 };
477
478 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
479 {
480 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
481 DE_NULL, // const void* pNext;
482 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
483 useTessellationShaders ? deUint32(4) : deUint32(2), // deUint32 stageCount;
484 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
485 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
486 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
487 useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
488 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
489 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
490 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
491 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
492 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
493 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
494 pipelineLayout, // VkPipelineLayout layout;
495 renderPass, // VkRenderPass renderPass;
496 0u, // deUint32 subpass;
497 DE_NULL, // VkPipeline basePipelineHandle;
498 0, // deInt32 basePipelineIndex;
499 };
500
501 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
502 }
503
504 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const UVec4 & cell,const Vec4 & cellColor)505 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
506 const UVec2& renderSize,
507 const Vec4& clearColor,
508 const UVec4& cell,
509 const Vec4& cellColor)
510 {
511 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
512 tcu::clear(image.getAccess(), clearColor);
513
514 tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
515 cellColor);
516
517 return image;
518 }
519
initVertexTestPrograms(SourceCollections & programCollection,const int numViewports)520 void initVertexTestPrograms (SourceCollections& programCollection, const int numViewports)
521 {
522 DE_UNREF(numViewports);
523
524 // Vertex shader
525 {
526 std::ostringstream src;
527 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
528 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
529 << "\n"
530 << "layout(location = 0) in vec4 in_position;\n"
531 << "layout(location = 1) in vec4 in_color;\n"
532 << "layout(location = 0) out vec4 out_color;\n"
533 << "\n"
534 << "void main(void)\n"
535 << "{\n"
536 << " gl_Layer = gl_VertexIndex / 6;\n"
537 << " gl_Position = in_position;\n"
538 << " out_color = in_color;\n"
539 << "}\n";
540
541 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
542 }
543
544 // Fragment shader
545 {
546 std::ostringstream src;
547 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
548 << "\n"
549 << "layout(location = 0) in vec4 in_color;\n"
550 << "layout(location = 0) out vec4 out_color;\n"
551 << "\n"
552 << "void main(void)\n"
553 << "{\n"
554 << " out_color = in_color;\n"
555 << "}\n";
556
557 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
558 }
559 }
560
initTessellationTestPrograms(SourceCollections & programCollection,const int numViewports)561 void initTessellationTestPrograms (SourceCollections& programCollection, const int numViewports)
562 {
563 DE_UNREF(numViewports);
564
565 // Vertex shader
566 {
567 std::ostringstream src;
568 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
569 << "\n"
570 << "layout(location = 0) in vec4 in_position;\n"
571 << "layout(location = 1) in vec4 in_color;\n"
572 << "layout(location = 0) out vec4 out_color;\n"
573 << "\n"
574 << "void main(void)\n"
575 << "{\n"
576 << " gl_Position = in_position;\n"
577 << " out_color = in_color;\n"
578 << "}\n";
579
580 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
581 }
582
583 // Tessellation control shader
584 {
585 std::ostringstream src;
586 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
587 << "\n"
588 << "layout(vertices = 3) out;\n"
589 << "\n"
590 << "layout(location = 0) in vec4 in_color[];\n"
591 << "layout(location = 0) out vec4 out_color[];\n"
592 << "\n"
593 << "void main(void)\n"
594 << "{\n"
595 << " if (gl_InvocationID == 0) {\n"
596 << " gl_TessLevelInner[0] = 1.0;\n"
597 << " gl_TessLevelInner[1] = 1.0;\n"
598 << " gl_TessLevelOuter[0] = 1.0;\n"
599 << " gl_TessLevelOuter[1] = 1.0;\n"
600 << " gl_TessLevelOuter[2] = 1.0;\n"
601 << " gl_TessLevelOuter[3] = 1.0;\n"
602 << " }\n"
603 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
604 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
605 << "}\n";
606
607 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
608 }
609
610 // Tessellation evaluation shader
611 {
612 std::ostringstream src;
613 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
614 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
615 << "\n"
616 << "layout(triangles, equal_spacing, cw) in;\n"
617 << "\n"
618 << "layout(location = 0) in vec4 in_color[];\n"
619 << "layout(location = 0) out vec4 out_color;\n"
620 << "\n"
621 << "void main(void)\n"
622 << "{\n"
623 << " gl_Layer = gl_PrimitiveID / 2;\n"
624 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
625 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
626 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
627 << "\n"
628 << " out_color = in_color[0] * gl_TessCoord.x +\n"
629 << " in_color[1] * gl_TessCoord.y +\n"
630 << " in_color[2] * gl_TessCoord.z;\n"
631 << "}\n";
632
633 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
634 }
635
636 // Fragment shader
637 {
638 std::ostringstream src;
639 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
640 << "\n"
641 << "layout(location = 0) in vec4 in_color;\n"
642 << "layout(location = 0) out vec4 out_color;\n"
643 << "\n"
644 << "void main(void)\n"
645 << "{\n"
646 << " out_color = in_color;\n"
647 << "}\n";
648
649 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
650 }
651 }
652
generateGrid(const int numCells,const UVec2 & renderSize)653 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
654 {
655 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
656 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
657 const int rectWidth = renderSize.x() / numCols;
658 const int rectHeight = renderSize.y() / numRows;
659
660 std::vector<UVec4> cells;
661 cells.reserve(numCells);
662
663 int x = 0;
664 int y = 0;
665
666 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
667 {
668 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
669 if (nextRow)
670 {
671 x = 0;
672 y += rectHeight;
673 }
674
675 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
676
677 x += rectWidth;
678 }
679
680 return cells;
681 }
682
generateColors(int numColors)683 std::vector<Vec4> generateColors (int numColors)
684 {
685 const Vec4 colors[] =
686 {
687 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
688 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
689 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
690 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
691 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
692 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
693 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
694 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
695 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
696 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
697 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
698 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
699 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
700 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
701 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
702 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
703 };
704
705 std::vector<Vec4> result;
706 result.reserve(numColors);
707
708 for (int i = 0; i < numColors; ++i)
709 {
710 result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
711 }
712
713 return result;
714 }
715
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)716 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
717 {
718 DE_ASSERT(colors.size() == grid.size());
719
720 // Two triangles for each cell. Each cell correspond to a layer.
721 std::size_t total = grid.size() * 6;
722
723 std::vector<PositionColorVertex> result;
724 result.reserve(total);
725
726 for (std::size_t i = 0; i < total; ++i)
727 {
728 Vec4 pos;
729 pos.z() = 0.0;
730 pos.w() = 1.0;
731
732 Vec4 cell = grid[i/6].asFloat() * 2.0f;
733 float x = cell.x() / float(renderSize.x()) - 1.0f;
734 float y = cell.y() / float(renderSize.y()) - 1.0f;
735 float width = cell.z() / float(renderSize.x());
736 float height = cell.w() / float(renderSize.y());
737
738 switch (i % 6)
739 {
740 case 0: pos.xy() = Vec2(x, y + height); break;
741 case 1: pos.xy() = Vec2(x + width, y + height); break;
742 case 2: pos.xy() = Vec2(x, y); break;
743 case 3: pos.xy() = Vec2(x + width, y); break;
744 case 4: pos.xy() = Vec2(x + width, y + height); break;
745 case 5: pos.xy() = Vec2(x, y); break;
746 }
747
748 result.push_back(PositionColorVertex(pos, colors[i/6]));
749 }
750
751 return result;
752 }
753
754 // Renderer generates two triangles per layer, each pair using a different
755 // color and a different position.
756 class Renderer
757 {
758 public:
759 enum Shader
760 {
761 VERTEX,
762 TESSELLATION,
763 };
764
Renderer(Context & context,const UVec2 & renderSize,const int numLayers,const VkFormat colorFormat,const Vec4 & clearColor,const std::vector<PositionColorVertex> & vertices,const Shader shader)765 Renderer (Context& context,
766 const UVec2& renderSize,
767 const int numLayers,
768 const VkFormat colorFormat,
769 const Vec4& clearColor,
770 const std::vector<PositionColorVertex>& vertices,
771 const Shader shader)
772 : m_renderSize (renderSize)
773 , m_colorFormat (colorFormat)
774 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
775 , m_clearColor (clearColor)
776 , m_numLayers (numLayers)
777 , m_vertices (vertices)
778 {
779 const DeviceInterface& vk = context.getDeviceInterface();
780 const VkDevice device = context.getDevice();
781 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
782 Allocator& allocator = context.getDefaultAllocator();
783 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
784
785 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
786 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
787 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
788
789 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
790
791 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
792 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
793
794 if (shader == TESSELLATION)
795 {
796 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
797 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u);
798 }
799
800 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
801 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
802 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
803 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, 1u, &m_colorAttachment.get(),
804 static_cast<deUint32>(m_renderSize.x()),
805 static_cast<deUint32>(m_renderSize.y()),
806 numLayers);
807 m_pipelineLayout = makePipelineLayout (vk, device);
808 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
809 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
810 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
811 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
812 }
813
draw(Context & context,const VkBuffer colorBuffer) const814 void draw (Context& context, const VkBuffer colorBuffer) const
815 {
816 const DeviceInterface& vk = context.getDeviceInterface();
817 const VkDevice device = context.getDevice();
818 const VkQueue queue = context.getUniversalQueue();
819
820 beginCommandBuffer(vk, *m_cmdBuffer);
821
822 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
823 const VkRect2D renderArea =
824 {
825 makeOffset2D(0, 0),
826 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
827 };
828 const VkRenderPassBeginInfo renderPassBeginInfo =
829 {
830 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
831 DE_NULL, // const void* pNext;
832 *m_renderPass, // VkRenderPass renderPass;
833 *m_framebuffer, // VkFramebuffer framebuffer;
834 renderArea, // VkRect2D renderArea;
835 1u, // uint32_t clearValueCount;
836 &clearValue, // const VkClearValue* pClearValues;
837 };
838 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
839
840 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
841 {
842 const VkBuffer vertexBuffer = m_vertexBuffer->object();
843 const VkDeviceSize vertexBufferOffset = 0ull;
844 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
845 }
846 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u); // two triangles per layer
847 vk.cmdEndRenderPass(*m_cmdBuffer);
848
849 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, m_colorSubresourceRange.layerCount);
850
851 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
852 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
853 }
854
855 private:
856 const UVec2 m_renderSize;
857 const VkFormat m_colorFormat;
858 const VkImageSubresourceRange m_colorSubresourceRange;
859 const Vec4 m_clearColor;
860 const int m_numLayers;
861 const std::vector<PositionColorVertex> m_vertices;
862
863 Move<VkImage> m_colorImage;
864 MovePtr<Allocation> m_colorImageAlloc;
865 Move<VkImageView> m_colorAttachment;
866 SharedPtr<Buffer> m_vertexBuffer;
867 Move<VkShaderModule> m_vertexModule;
868 Move<VkShaderModule> m_tessellationControlModule;
869 Move<VkShaderModule> m_tessellationEvaluationModule;
870 Move<VkShaderModule> m_fragmentModule;
871 Move<VkRenderPass> m_renderPass;
872 Move<VkFramebuffer> m_framebuffer;
873 Move<VkPipelineLayout> m_pipelineLayout;
874 Move<VkPipeline> m_pipeline;
875 Move<VkCommandPool> m_cmdPool;
876 Move<VkCommandBuffer> m_cmdBuffer;
877
878 // "deleted"
879 Renderer (const Renderer&);
880 Renderer& operator= (const Renderer&);
881 };
882
checkRequirements(const Context & context)883 void checkRequirements (const Context& context)
884 {
885 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
886 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
887
888 if (!features.multiViewport)
889 TCU_THROW(NotSupportedError, "Required feature is not supported: multiViewport");
890
891 if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
892 TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
893
894 if (limits.maxViewports < MIN_MAX_VIEWPORTS)
895 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
896
897 const std::vector<std::string>& extensions = context.getDeviceExtensions();
898 if (!isDeviceExtensionSupported(context.getUsedApiVersion(), extensions, "VK_EXT_shader_viewport_index_layer"))
899 TCU_THROW(NotSupportedError, "Extension VK_EXT_shader_viewport_index_layer not supported");
900 }
901
testVertexShader(Context & context,const int numLayers)902 tcu::TestStatus testVertexShader (Context& context, const int numLayers)
903 {
904 checkRequirements(context);
905
906 const DeviceInterface& vk = context.getDeviceInterface();
907 const VkDevice device = context.getDevice();
908 Allocator& allocator = context.getDefaultAllocator();
909
910 const UVec2 renderSize (256, 256);
911 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
912 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
913 const std::vector<UVec4> grid = generateGrid(numLayers, renderSize);
914 const std::vector<Vec4> colors = generateColors(numLayers);
915 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
916
917 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
918
919 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
920
921 // Zero buffer.
922 {
923 const Allocation alloc = colorBuffer->getBoundMemory();
924 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
925 flushAlloc(vk, device, alloc);
926 }
927
928 {
929 context.getTestContext().getLog()
930 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
931 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
932 }
933
934 // Draw.
935 {
936 const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
937 renderer.draw(context, colorBuffer->object());
938 }
939
940 // Verify layers.
941 {
942 const Allocation alloc = colorBuffer->getBoundMemory();
943 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize);
944
945 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
946 for (int i = 0; i < numLayers; i++)
947 {
948 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
949 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
950 std::string imageSetName = "layer_" + de::toString(i);
951 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
952 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
953 TCU_FAIL("Rendered image is not correct");
954 }
955 }
956
957 return tcu::TestStatus::pass("OK");
958 }
959
testTessellationShader(Context & context,const int numLayers)960 tcu::TestStatus testTessellationShader (Context& context, const int numLayers)
961 {
962 checkRequirements(context);
963
964 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
965 if (!features.tessellationShader)
966 TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
967
968 const DeviceInterface& vk = context.getDeviceInterface();
969 const VkDevice device = context.getDevice();
970 Allocator& allocator = context.getDefaultAllocator();
971
972 const UVec2 renderSize (256, 256);
973 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
974 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
975 const std::vector<UVec4> grid = generateGrid(numLayers, renderSize);
976 const std::vector<Vec4> colors = generateColors(numLayers);
977 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
978
979 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
980
981 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
982
983 // Zero buffer.
984 {
985 const Allocation alloc = colorBuffer->getBoundMemory();
986 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
987 flushAlloc(vk, device, alloc);
988 }
989
990 {
991 context.getTestContext().getLog()
992 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
993 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
994 }
995
996 // Draw.
997 {
998 const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
999 renderer.draw(context, colorBuffer->object());
1000 }
1001
1002 // Verify layers.
1003 {
1004 const Allocation alloc = colorBuffer->getBoundMemory();
1005 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize);
1006
1007 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
1008 for (int i = 0; i < numLayers; i++) {
1009 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
1010 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
1011 std::string imageSetName = "layer_" + de::toString(i);
1012 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
1013 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1014 TCU_FAIL("Rendered image is not correct");
1015 }
1016 }
1017
1018 return tcu::TestStatus::pass("OK");
1019 }
1020
1021 } // anonymous
1022
createShaderLayerTests(tcu::TestContext & testCtx)1023 tcu::TestCaseGroup* createShaderLayerTests (tcu::TestContext& testCtx)
1024 {
1025 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
1026
1027 int numLayersToTest[] =
1028 {
1029 1,
1030 2,
1031 3,
1032 4,
1033 5,
1034 6,
1035 7,
1036 8,
1037 MIN_MAX_FRAMEBUFFER_LAYERS,
1038 };
1039
1040 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1041 {
1042 int numLayers = numLayersToTest[i];
1043 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(numLayers), "", initVertexTestPrograms, testVertexShader, numLayers);
1044 }
1045
1046 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1047 {
1048 int numLayers = numLayersToTest[i];
1049 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(numLayers), "", initTessellationTestPrograms, testTessellationShader, numLayers);
1050 }
1051
1052 return group.release();
1053 }
1054
1055 } // Draw
1056 } // vkt
1057