1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Clipping tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktClippingTests.hpp"
25 #include "vktTestCase.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktClippingUtil.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "tcuTestLog.hpp"
33 #include "deUniquePtr.hpp"
34 #include "deStringUtil.hpp"
35 #include "deRandom.hpp"
52 RENDER_SIZE_LARGE = 128,
53 NUM_RENDER_PIXELS = RENDER_SIZE * RENDER_SIZE,
54 NUM_PATCH_CONTROL_POINTS = 3,
55 MAX_NUM_SHADER_MODULES = 5,
56 MAX_CLIP_DISTANCES = 8,
57 MAX_CULL_DISTANCES = 8,
58 MAX_COMBINED_CLIP_AND_CULL_DISTANCES = 8,
63 VkShaderStageFlagBits stage;
64 const ProgramBinary* binary;
66 Shader (const VkShaderStageFlagBits stage_, const ProgramBinary& binary_)
73 //! Sets up a graphics pipeline and enables simple draw calls to predefined attachments.
74 //! Clip volume uses wc = 1.0, which gives clip coord ranges: x = [-1, 1], y = [-1, 1], z = [0, 1]
75 //! Clip coords (-1,-1) map to viewport coords (0, 0).
79 DrawContext (Context& context,
80 const std::vector<Shader>& shaders,
81 const std::vector<Vec4>& vertices,
82 const VkPrimitiveTopology primitiveTopology,
83 const deUint32 renderSize = static_cast<deUint32>(RENDER_SIZE),
84 const bool depthClampEnable = false,
85 const bool blendEnable = false,
86 const float lineWidth = 1.0f);
89 tcu::ConstPixelBufferAccess getColorPixels (void) const;
93 const VkFormat m_colorFormat;
94 const VkImageSubresourceRange m_colorSubresourceRange;
95 const UVec2 m_renderSize;
96 const VkExtent3D m_imageExtent;
97 const VkPrimitiveTopology m_primitiveTopology;
98 const bool m_depthClampEnable;
99 const bool m_blendEnable;
100 const deUint32 m_numVertices;
101 const float m_lineWidth;
102 const deUint32 m_numPatchControlPoints;
103 MovePtr<Buffer> m_vertexBuffer;
104 MovePtr<Image> m_colorImage;
105 MovePtr<Buffer> m_colorAttachmentBuffer;
106 Move<VkImageView> m_colorImageView;
107 Move<VkRenderPass> m_renderPass;
108 Move<VkFramebuffer> m_framebuffer;
109 Move<VkPipelineLayout> m_pipelineLayout;
110 Move<VkPipeline> m_pipeline;
111 Move<VkCommandPool> m_cmdPool;
112 Move<VkCommandBuffer> m_cmdBuffer;
113 Move<VkShaderModule> m_shaderModules[MAX_NUM_SHADER_MODULES];
115 DrawContext (const DrawContext&); // "deleted"
116 DrawContext& operator= (const DrawContext&); // "deleted"
119 DrawContext::DrawContext (Context& context,
120 const std::vector<Shader>& shaders,
121 const std::vector<Vec4>& vertices,
122 const VkPrimitiveTopology primitiveTopology,
123 const deUint32 renderSize,
124 const bool depthClampEnable,
125 const bool blendEnable,
126 const float lineWidth)
127 : m_context (context)
128 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
129 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
130 , m_renderSize (renderSize, renderSize)
131 , m_imageExtent (makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
132 , m_primitiveTopology (primitiveTopology)
133 , m_depthClampEnable (depthClampEnable)
134 , m_blendEnable (blendEnable)
135 , m_numVertices (static_cast<deUint32>(vertices.size()))
136 , m_lineWidth (lineWidth)
137 , m_numPatchControlPoints (NUM_PATCH_CONTROL_POINTS) // we're treating patches as triangles
139 const DeviceInterface& vk = m_context.getDeviceInterface();
140 const VkDevice device = m_context.getDevice();
141 Allocator& allocator = m_context.getDefaultAllocator();
145 m_cmdPool = makeCommandPool(vk, device, m_context.getUniversalQueueFamilyIndex());
146 m_cmdBuffer = makeCommandBuffer(vk, device, *m_cmdPool);
149 // Color attachment image
151 const VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
152 const VkImageCreateInfo imageCreateInfo =
154 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
155 DE_NULL, // const void* pNext;
156 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
157 VK_IMAGE_TYPE_2D, // VkImageType imageType;
158 m_colorFormat, // VkFormat format;
159 m_imageExtent, // VkExtent3D extent;
160 1u, // uint32_t mipLevels;
161 1u, // uint32_t arrayLayers;
162 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
163 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
164 usage, // VkImageUsageFlags usage;
165 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
166 VK_QUEUE_FAMILY_IGNORED, // uint32_t queueFamilyIndexCount;
167 DE_NULL, // const uint32_t* pQueueFamilyIndices;
168 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
171 m_colorImage = MovePtr<Image>(new Image(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
172 m_colorImageView = makeImageView(vk, device, **m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
174 // Buffer to copy attachment data after rendering
176 const VkDeviceSize bitmapSize = tcu::getPixelSize(mapVkFormat(m_colorFormat)) * m_renderSize.x() * m_renderSize.y();
177 m_colorAttachmentBuffer = MovePtr<Buffer>(new Buffer(
178 vk, device, allocator, makeBufferCreateInfo(bitmapSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
181 const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
182 deMemset(alloc.getHostPtr(), 0, (size_t)bitmapSize);
183 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bitmapSize);
189 const VkDeviceSize bufferSize = vertices.size() * sizeof(vertices[0]);
190 m_vertexBuffer = MovePtr<Buffer>(new Buffer(
191 vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
193 const Allocation& alloc = m_vertexBuffer->getAllocation();
194 deMemcpy(alloc.getHostPtr(), &vertices[0], (size_t)bufferSize);
195 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
200 m_pipelineLayout = makePipelineLayoutWithoutDescriptors(vk, device);
205 const VkAttachmentDescription colorAttachmentDescription =
207 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
208 m_colorFormat, // VkFormat format;
209 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
210 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
211 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
212 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
213 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
214 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
215 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
218 const VkAttachmentReference colorAttachmentReference =
220 0u, // deUint32 attachment;
221 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
224 const VkAttachmentReference depthAttachmentReference =
226 VK_ATTACHMENT_UNUSED, // deUint32 attachment;
227 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout;
230 const VkSubpassDescription subpassDescription =
232 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
233 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
234 0u, // deUint32 inputAttachmentCount;
235 DE_NULL, // const VkAttachmentReference* pInputAttachments;
236 1u, // deUint32 colorAttachmentCount;
237 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
238 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
239 &depthAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
240 0u, // deUint32 preserveAttachmentCount;
241 DE_NULL // const deUint32* pPreserveAttachments;
244 const VkRenderPassCreateInfo renderPassInfo =
246 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
247 DE_NULL, // const void* pNext;
248 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
249 1u, // deUint32 attachmentCount;
250 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
251 1u, // deUint32 subpassCount;
252 &subpassDescription, // const VkSubpassDescription* pSubpasses;
253 0u, // deUint32 dependencyCount;
254 DE_NULL // const VkSubpassDependency* pDependencies;
257 m_renderPass = createRenderPass(vk, device, &renderPassInfo);
262 const VkFramebufferCreateInfo framebufferInfo = {
263 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
264 DE_NULL, // const void* pNext;
265 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
266 *m_renderPass, // VkRenderPass renderPass;
267 1u, // uint32_t attachmentCount;
268 &m_colorImageView.get(), // const VkImageView* pAttachments;
269 m_renderSize.x(), // uint32_t width;
270 m_renderSize.y(), // uint32_t height;
271 1u, // uint32_t layers;
274 m_framebuffer = createFramebuffer(vk, device, &framebufferInfo);
279 const deUint32 vertexStride = sizeof(Vec4);
280 const VkFormat vertexFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
282 const VkVertexInputBindingDescription bindingDesc =
284 0u, // uint32_t binding;
285 vertexStride, // uint32_t stride;
286 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
288 const VkVertexInputAttributeDescription attributeDesc =
290 0u, // uint32_t location;
291 0u, // uint32_t binding;
292 vertexFormat, // VkFormat format;
293 0u, // uint32_t offset;
296 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
298 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
299 DE_NULL, // const void* pNext;
300 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
301 1u, // uint32_t vertexBindingDescriptionCount;
302 &bindingDesc, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
303 1u, // uint32_t vertexAttributeDescriptionCount;
304 &attributeDesc, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
307 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
309 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
310 DE_NULL, // const void* pNext;
311 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
312 m_primitiveTopology, // VkPrimitiveTopology topology;
313 VK_FALSE, // VkBool32 primitiveRestartEnable;
316 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
318 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
319 DE_NULL, // const void* pNext;
320 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
321 m_numPatchControlPoints, // uint32_t patchControlPoints;
324 const VkViewport viewport = makeViewport(
326 static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
329 const VkRect2D scissor = {
331 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
334 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
336 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
337 DE_NULL, // const void* pNext;
338 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
339 1u, // uint32_t viewportCount;
340 &viewport, // const VkViewport* pViewports;
341 1u, // uint32_t scissorCount;
342 &scissor, // const VkRect2D* pScissors;
345 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
347 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
348 DE_NULL, // const void* pNext;
349 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
350 m_depthClampEnable, // VkBool32 depthClampEnable;
351 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
352 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
353 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
354 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
355 VK_FALSE, // VkBool32 depthBiasEnable;
356 0.0f, // float depthBiasConstantFactor;
357 0.0f, // float depthBiasClamp;
358 0.0f, // float depthBiasSlopeFactor;
359 m_lineWidth, // float lineWidth;
362 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
364 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
365 DE_NULL, // const void* pNext;
366 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
367 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
368 VK_FALSE, // VkBool32 sampleShadingEnable;
369 0.0f, // float minSampleShading;
370 DE_NULL, // const VkSampleMask* pSampleMask;
371 VK_FALSE, // VkBool32 alphaToCoverageEnable;
372 VK_FALSE // VkBool32 alphaToOneEnable;
375 const VkStencilOpState stencilOpState = makeStencilOpState(
376 VK_STENCIL_OP_KEEP, // stencil fail
377 VK_STENCIL_OP_KEEP, // depth & stencil pass
378 VK_STENCIL_OP_KEEP, // depth only fail
379 VK_COMPARE_OP_NEVER, // compare op
384 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
386 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
387 DE_NULL, // const void* pNext;
388 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
389 VK_FALSE, // VkBool32 depthTestEnable;
390 VK_FALSE, // VkBool32 depthWriteEnable;
391 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
392 VK_FALSE, // VkBool32 depthBoundsTestEnable;
393 VK_FALSE, // VkBool32 stencilTestEnable;
394 stencilOpState, // VkStencilOpState front;
395 stencilOpState, // VkStencilOpState back;
396 0.0f, // float minDepthBounds;
397 1.0f, // float maxDepthBounds;
400 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
401 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
403 m_blendEnable, // VkBool32 blendEnable;
404 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor;
405 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor;
406 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
407 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor;
408 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor;
409 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
410 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
413 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
415 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
416 DE_NULL, // const void* pNext;
417 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
418 VK_FALSE, // VkBool32 logicOpEnable;
419 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
420 1u, // deUint32 attachmentCount;
421 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
422 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
425 // Create shader stages
427 std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
428 VkShaderStageFlags stageFlags = (VkShaderStageFlags)0;
430 DE_ASSERT(shaders.size() <= MAX_NUM_SHADER_MODULES);
431 for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
433 m_shaderModules[shaderNdx] = createShaderModule(vk, device, *shaders[shaderNdx].binary, (VkShaderModuleCreateFlags)0);
435 const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
437 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
438 DE_NULL, // const void* pNext;
439 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
440 shaders[shaderNdx].stage, // VkShaderStageFlagBits stage;
441 *m_shaderModules[shaderNdx], // VkShaderModule module;
442 "main", // const char* pName;
443 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
446 shaderStages.push_back(pipelineShaderStageInfo);
447 stageFlags |= shaders[shaderNdx].stage;
451 (m_primitiveTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ||
452 (stageFlags & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)));
454 const bool tessellationEnabled = (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
455 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
457 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
458 DE_NULL, // const void* pNext;
459 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
460 static_cast<deUint32>(shaderStages.size()), // deUint32 stageCount;
461 &shaderStages[0], // const VkPipelineShaderStageCreateInfo* pStages;
462 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
463 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
464 (tessellationEnabled ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo* pTessellationState;
465 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
466 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
467 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
468 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
469 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
470 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
471 *m_pipelineLayout, // VkPipelineLayout layout;
472 *m_renderPass, // VkRenderPass renderPass;
473 0u, // deUint32 subpass;
474 DE_NULL, // VkPipeline basePipelineHandle;
475 0, // deInt32 basePipelineIndex;
478 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
483 const VkDeviceSize zeroOffset = 0ull;
485 beginCommandBuffer(vk, *m_cmdBuffer);
489 const VkClearValue clearValue = makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 1.0f));
490 const VkRect2D renderArea =
493 makeExtent2D(m_renderSize.x(), m_renderSize.y())
496 const VkRenderPassBeginInfo renderPassBeginInfo = {
497 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
498 DE_NULL, // const void* pNext;
499 *m_renderPass, // VkRenderPass renderPass;
500 *m_framebuffer, // VkFramebuffer framebuffer;
501 renderArea, // VkRect2D renderArea;
502 1u, // uint32_t clearValueCount;
503 &clearValue, // const VkClearValue* pClearValues;
506 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
509 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
510 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &(**m_vertexBuffer), &zeroOffset);
512 vk.cmdDraw(*m_cmdBuffer, m_numVertices, 1u, 0u, 1u);
513 vk.cmdEndRenderPass(*m_cmdBuffer);
515 // Barrier: draw -> copy from image
517 const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
518 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
519 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
520 **m_colorImage, m_colorSubresourceRange);
522 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
523 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
527 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), m_imageExtent);
528 vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorAttachmentBuffer, 1u, ©Region);
531 // Barrier: copy to buffer -> host read
533 const VkBufferMemoryBarrier barrier = makeBufferMemoryBarrier(
534 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
535 **m_colorAttachmentBuffer, 0ull, VK_WHOLE_SIZE);
537 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
538 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
541 endCommandBuffer(vk, *m_cmdBuffer);
545 void DrawContext::draw (void)
547 const DeviceInterface& vk = m_context.getDeviceInterface();
548 const VkDevice device = m_context.getDevice();
549 const VkQueue queue = m_context.getUniversalQueue();
550 tcu::TestLog& log = m_context.getTestContext().getLog();
552 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
554 log << tcu::LogImageSet("attachments", "") << tcu::LogImage("color0", "", getColorPixels()) << tcu::TestLog::EndImageSet;
557 tcu::ConstPixelBufferAccess DrawContext::getColorPixels (void) const
559 const DeviceInterface& vk = m_context.getDeviceInterface();
560 const VkDevice device = m_context.getDevice();
562 const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
563 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
565 return tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, alloc.getHostPtr());
568 std::vector<Vec4> genVertices (const VkPrimitiveTopology topology, const Vec4& offset, const float slope)
570 const float p = 1.0f;
571 const float hp = 0.5f;
572 const float z = 0.0f;
573 const float w = 1.0f;
575 std::vector<Vec4> vertices;
577 // We're setting adjacent vertices to zero where needed, as we don't use them in meaningful way.
581 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
582 vertices.push_back(offset + Vec4(0.0f, 0.0f, slope/2.0f + z, w));
583 vertices.push_back(offset + Vec4( -hp, -hp, z, w));
584 vertices.push_back(offset + Vec4( hp, -hp, slope + z, w));
585 vertices.push_back(offset + Vec4( -hp, hp, z, w));
586 vertices.push_back(offset + Vec4( hp, hp, slope + z, w));
589 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
590 vertices.push_back(offset + Vec4(-p, -p, z, w));
591 vertices.push_back(offset + Vec4( p, p, slope + z, w)); // line 0
592 vertices.push_back(offset + Vec4( p, p, slope + z, w));
593 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // line 1
594 vertices.push_back(offset + Vec4( p, -p, slope + z, w));
595 vertices.push_back(offset + Vec4(-p, p, z, w)); // line 2
598 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
599 vertices.push_back(Vec4());
600 vertices.push_back(offset + Vec4(-p, -p, z, w));
601 vertices.push_back(offset + Vec4( p, p, slope + z, w)); // line 0
602 vertices.push_back(Vec4());
603 vertices.push_back(Vec4());
604 vertices.push_back(offset + Vec4( p, p, slope + z, w));
605 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // line 1
606 vertices.push_back(Vec4());
607 vertices.push_back(Vec4());
608 vertices.push_back(offset + Vec4( p, -p, slope + z, w));
609 vertices.push_back(offset + Vec4(-p, p, z, w)); // line 2
610 vertices.push_back(Vec4());
613 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
614 vertices.push_back(offset + Vec4(-p, -p, z, w));
615 vertices.push_back(offset + Vec4( p, p, slope + z, w)); // line 0
616 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // line 1
617 vertices.push_back(offset + Vec4(-p, p, z, w)); // line 2
620 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
621 vertices.push_back(Vec4());
622 vertices.push_back(offset + Vec4(-p, -p, z, w));
623 vertices.push_back(offset + Vec4( p, p, slope + z, w)); // line 0
624 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // line 1
625 vertices.push_back(offset + Vec4(-p, p, z, w)); // line 2
626 vertices.push_back(Vec4());
629 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
630 vertices.push_back(offset + Vec4( p, -p, slope + z, w));
631 vertices.push_back(offset + Vec4(-p, -p, z, w));
632 vertices.push_back(offset + Vec4(-p, p, z, w)); // triangle 0
633 vertices.push_back(offset + Vec4(-p, p, z, w));
634 vertices.push_back(offset + Vec4( p, p, slope + z, w));
635 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // triangle 1
638 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
639 vertices.push_back(offset + Vec4( p, -p, slope + z, w));
640 vertices.push_back(Vec4());
641 vertices.push_back(offset + Vec4(-p, -p, z, w));
642 vertices.push_back(Vec4());
643 vertices.push_back(offset + Vec4(-p, p, z, w)); // triangle 0
644 vertices.push_back(Vec4());
645 vertices.push_back(offset + Vec4(-p, p, z, w));
646 vertices.push_back(Vec4());
647 vertices.push_back(offset + Vec4( p, p, slope + z, w));
648 vertices.push_back(Vec4());
649 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // triangle 1
650 vertices.push_back(Vec4());
653 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
654 vertices.push_back(offset + Vec4(-p, -p, z, w));
655 vertices.push_back(offset + Vec4(-p, p, z, w));
656 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // triangle 0
657 vertices.push_back(offset + Vec4( p, p, slope + z, w)); // triangle 1
660 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
661 vertices.push_back(offset + Vec4(-p, -p, z, w));
662 vertices.push_back(Vec4());
663 vertices.push_back(offset + Vec4(-p, p, z, w));
664 vertices.push_back(Vec4());
665 vertices.push_back(offset + Vec4( p, -p, slope + z, w)); // triangle 0
666 vertices.push_back(Vec4());
667 vertices.push_back(offset + Vec4( p, p, slope + z, w)); // triangle 1
668 vertices.push_back(Vec4());
671 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
672 vertices.push_back(offset + Vec4( p, -p, slope + z, w));
673 vertices.push_back(offset + Vec4(-p, -p, z, w));
674 vertices.push_back(offset + Vec4(-p, p, z, w)); // triangle 0
675 vertices.push_back(offset + Vec4( p, p, slope + z, w)); // triangle 1
678 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
689 bool inline isColorInRange (const Vec4& color, const Vec4& minColor, const Vec4& maxColor)
691 return (minColor.x() <= color.x() && color.x() <= maxColor.x())
692 && (minColor.y() <= color.y() && color.y() <= maxColor.y())
693 && (minColor.z() <= color.z() && color.z() <= maxColor.z())
694 && (minColor.w() <= color.w() && color.w() <= maxColor.w());
697 //! Count pixels that match color within threshold, in the specified region.
698 int countPixels (const tcu::ConstPixelBufferAccess pixels, const IVec2& regionOffset, const IVec2& regionSize, const Vec4& color, const Vec4& colorThreshold)
700 const Vec4 minColor = color - colorThreshold;
701 const Vec4 maxColor = color + colorThreshold;
702 const int xEnd = regionOffset.x() + regionSize.x();
703 const int yEnd = regionOffset.y() + regionSize.y();
706 DE_ASSERT(xEnd <= pixels.getWidth());
707 DE_ASSERT(yEnd <= pixels.getHeight());
709 for (int y = regionOffset.y(); y < yEnd; ++y)
710 for (int x = regionOffset.x(); x < xEnd; ++x)
712 if (isColorInRange(pixels.getPixel(x, y), minColor, maxColor))
719 int countPixels (const tcu::ConstPixelBufferAccess pixels, const Vec4& color, const Vec4& colorThreshold)
721 return countPixels(pixels, IVec2(), IVec2(pixels.getWidth(), pixels.getHeight()), color, colorThreshold);
724 //! Clipping against the default clip volume.
728 //! Used by wide lines test.
731 LINE_ORIENTATION_AXIS_ALIGNED,
732 LINE_ORIENTATION_DIAGONAL,
735 const VkPointClippingBehaviorKHR invalidClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_KHR_LAST;
737 VkPointClippingBehaviorKHR getClippingBehavior (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
739 VkPhysicalDevicePointClippingPropertiesKHR behaviorProperties =
741 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR, // VkStructureType sType
742 DE_NULL, // void* pNext
743 invalidClippingBehavior // VkPointClippingBehaviorKHR pointClippingBehavior
745 VkPhysicalDeviceProperties2KHR properties2;
747 DE_ASSERT(getPointClippingBehaviorKHRName(invalidClippingBehavior) == DE_NULL);
749 deMemset(&properties2, 0, sizeof(properties2));
751 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
752 properties2.pNext = &behaviorProperties;
754 vk.getPhysicalDeviceProperties2KHR(physicalDevice, &properties2);
756 return behaviorProperties.pointClippingBehavior;
759 void addSimplePrograms (SourceCollections& programCollection, const float pointSize = 0.0f)
763 const bool usePointSize = pointSize > 0.0f;
765 std::ostringstream src;
766 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
768 << "layout(location = 0) in vec4 v_position;\n"
770 << "out gl_PerVertex {\n"
771 << " vec4 gl_Position;\n"
772 << (usePointSize ? " float gl_PointSize;\n" : "")
775 << "void main (void)\n"
777 << " gl_Position = v_position;\n"
778 << (usePointSize ? " gl_PointSize = " + de::floatToString(pointSize, 1) + ";\n" : "")
781 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
786 std::ostringstream src;
787 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
789 << "layout(location = 0) out vec4 o_color;\n"
791 << "void main (void)\n"
793 << " o_color = vec4(1.0, gl_FragCoord.z, 0.0, 1.0);\n"
796 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
800 void initPrograms (SourceCollections& programCollection, const VkPrimitiveTopology topology)
802 const float pointSize = (topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ? 1.0f : 0.0f);
803 addSimplePrograms(programCollection, pointSize);
806 void initPrograms (SourceCollections& programCollection, const LineOrientation lineOrientation)
808 DE_UNREF(lineOrientation);
809 addSimplePrograms(programCollection);
812 void initProgramsPointSize (SourceCollections& programCollection)
814 addSimplePrograms(programCollection, 0.75f * RENDER_SIZE);
817 //! Primitives fully inside the clip volume.
818 tcu::TestStatus testPrimitivesInside (Context& context, const VkPrimitiveTopology topology)
820 int minExpectedBlackPixels = 0;
824 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
825 // We draw only 5 points.
826 minExpectedBlackPixels = NUM_RENDER_PIXELS - 5;
829 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
830 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
831 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
832 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
833 // Allow for some error.
834 minExpectedBlackPixels = NUM_RENDER_PIXELS - 3 * RENDER_SIZE;
837 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
838 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
839 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
840 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
841 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
842 // All render area should be covered.
843 minExpectedBlackPixels = 0;
851 std::vector<Shader> shaders;
852 shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert")));
853 shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag")));
855 tcu::TestLog& log = context.getTestContext().getLog();
860 const char* const desc;
864 { "Draw primitives at near clipping plane, z = 0.0", 0.0f, },
865 { "Draw primitives at z = 0.5", 0.5f, },
866 { "Draw primitives at far clipping plane, z = 1.0", 1.0f, },
869 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
871 log << tcu::TestLog::Message << cases[caseNdx].desc << tcu::TestLog::EndMessage;
873 const std::vector<Vec4> vertices = genVertices(topology, Vec4(0.0f, 0.0f, cases[caseNdx].zPos, 0.0f), 0.0f);
874 DrawContext drawContext(context, shaders, vertices, topology);
877 const int numBlackPixels = countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
878 if (numBlackPixels >= minExpectedBlackPixels)
882 return (numPassed == DE_LENGTH_OF_ARRAY(cases) ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
885 //! Primitives fully outside the clip volume.
886 tcu::TestStatus testPrimitivesOutside (Context& context, const VkPrimitiveTopology topology)
888 std::vector<Shader> shaders;
889 shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert")));
890 shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag")));
892 tcu::TestLog& log = context.getTestContext().getLog();
897 const char* const desc;
901 { "Draw primitives in front of the near clipping plane, z < 0.0", -0.5f, },
902 { "Draw primitives behind the far clipping plane, z > 1.0", 1.5f, },
905 log << tcu::TestLog::Message << "Drawing primitives outside the clip volume. Expecting an empty image." << tcu::TestLog::EndMessage;
907 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
909 log << tcu::TestLog::Message << cases[caseNdx].desc << tcu::TestLog::EndMessage;
911 const std::vector<Vec4> vertices = genVertices(topology, Vec4(0.0f, 0.0f, cases[caseNdx].zPos, 0.0f), 0.0f);
912 DrawContext drawContext(context, shaders, vertices, topology);
915 // All pixels must be black -- nothing is drawn.
916 const int numBlackPixels = countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
917 if (numBlackPixels == NUM_RENDER_PIXELS)
921 return (numPassed == DE_LENGTH_OF_ARRAY(cases) ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
924 //! Primitives partially outside the clip volume, but depth clamped
925 tcu::TestStatus testPrimitivesDepthClamp (Context& context, const VkPrimitiveTopology topology)
927 requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_DEPTH_CLAMP);
929 std::vector<Shader> shaders;
930 shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert")));
931 shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag")));
933 const int numCases = 4;
934 const IVec2 regionSize = IVec2(RENDER_SIZE/2, RENDER_SIZE); //! size of the clamped region
935 const int regionPixels = regionSize.x() * regionSize.y();
936 tcu::TestLog& log = context.getTestContext().getLog();
941 const char* const desc;
943 bool depthClampEnable;
948 { "Draw primitives intersecting the near clipping plane, depth clamp disabled", -0.5f, false, IVec2(0, 0), Vec4(0.0f, 0.0f, 0.0f, 1.0f) },
949 { "Draw primitives intersecting the near clipping plane, depth clamp enabled", -0.5f, true, IVec2(0, 0), Vec4(1.0f, 0.0f, 0.0f, 1.0f) },
950 { "Draw primitives intersecting the far clipping plane, depth clamp disabled", 0.5f, false, IVec2(RENDER_SIZE/2, 0), Vec4(0.0f, 0.0f, 0.0f, 1.0f) },
951 { "Draw primitives intersecting the far clipping plane, depth clamp enabled", 0.5f, true, IVec2(RENDER_SIZE/2, 0), Vec4(1.0f, 1.0f, 0.0f, 1.0f) },
954 // Per case minimum number of colored pixels.
955 int caseMinPixels[numCases] = { 0, 0, 0, 0 };
959 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
960 caseMinPixels[0] = caseMinPixels[2] = regionPixels - 1;
961 caseMinPixels[1] = caseMinPixels[3] = 2;
964 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
965 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
966 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
967 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
968 caseMinPixels[0] = regionPixels;
969 caseMinPixels[1] = RENDER_SIZE - 2;
970 caseMinPixels[2] = regionPixels;
971 caseMinPixels[3] = 2 * (RENDER_SIZE - 2);
974 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
975 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
976 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
977 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
978 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
979 caseMinPixels[0] = caseMinPixels[1] = caseMinPixels[2] = caseMinPixels[3] = regionPixels;
987 for (int caseNdx = 0; caseNdx < numCases; ++caseNdx)
989 log << tcu::TestLog::Message << cases[caseNdx].desc << tcu::TestLog::EndMessage;
991 const std::vector<Vec4> vertices = genVertices(topology, Vec4(0.0f, 0.0f, cases[caseNdx].zPos, 0.0f), 1.0f);
992 DrawContext drawContext(context, shaders, vertices, topology, static_cast<deUint32>(RENDER_SIZE), cases[caseNdx].depthClampEnable);
995 const int numPixels = countPixels(drawContext.getColorPixels(), cases[caseNdx].regionOffset, regionSize, cases[caseNdx].color, Vec4());
997 if (numPixels >= caseMinPixels[caseNdx])
1001 return (numPassed == numCases ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
1004 //! Large point clipping
1005 //! Spec: If the primitive under consideration is a point, then clipping passes it unchanged if it lies within the clip volume;
1006 //! otherwise, it is discarded.
1007 tcu::TestStatus testLargePoints (Context& context)
1009 requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_LARGE_POINTS);
1011 bool pointClippingOutside = true;
1013 if (de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance2"))
1015 VkPointClippingBehaviorKHR clippingBehavior = getClippingBehavior(context.getInstanceInterface(), context.getPhysicalDevice());
1017 switch (clippingBehavior)
1019 case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR: pointClippingOutside = true; break;
1020 case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR: pointClippingOutside = false; break;
1021 case invalidClippingBehavior: TCU_FAIL("Clipping behavior read failure"); break;
1024 TCU_FAIL("Unexpected clipping behavior reported");
1030 //TODO: Now we have 2 cases {some-points-drawn|nothing}, we should have {all-points-drawn|some-points-drawn|nothing}
1031 return tcu::TestStatus::pass("OK");
1034 std::vector<Shader> shaders;
1035 shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert")));
1036 shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag")));
1038 std::vector<Vec4> vertices;
1040 const float delta = 0.1f; // much smaller than the point size
1041 const float p = 1.0f + delta;
1043 vertices.push_back(Vec4( -p, -p, 0.1f, 1.0f));
1044 vertices.push_back(Vec4( -p, p, 0.2f, 1.0f));
1045 vertices.push_back(Vec4( p, p, 0.4f, 1.0f));
1046 vertices.push_back(Vec4( p, -p, 0.6f, 1.0f));
1047 vertices.push_back(Vec4(0.0f, -p, 0.8f, 1.0f));
1048 vertices.push_back(Vec4( p, 0.0f, 0.9f, 1.0f));
1049 vertices.push_back(Vec4(0.0f, p, 0.1f, 1.0f));
1050 vertices.push_back(Vec4( -p, 0.0f, 0.2f, 1.0f));
1053 tcu::TestLog& log = context.getTestContext().getLog();
1055 log << tcu::TestLog::Message << "Drawing several large points just outside the clip volume. Expecting an empty image." << tcu::TestLog::EndMessage;
1057 DrawContext drawContext(context, shaders, vertices, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1060 const int numBlackPixels = countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
1061 bool result = false;
1063 if (pointClippingOutside)
1065 // All pixels must be black -- nothing is drawn.
1066 result = (numBlackPixels == NUM_RENDER_PIXELS);
1070 // Rendering pixels without clipping: some pixels should not be black -- something is drawn.
1071 result = (numBlackPixels < NUM_RENDER_PIXELS);
1074 return (result ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
1077 //! Wide line clipping
1078 //! Spec: If the primitive is a line segment, then clipping does nothing to it if it lies entirely within the clip volume, and discards it
1079 //! if it lies entirely outside the volume.
1080 tcu::TestStatus testWideLines (Context& context, const LineOrientation lineOrientation)
1082 requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_WIDE_LINES);
1084 std::vector<Shader> shaders;
1085 shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert")));
1086 shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag")));
1088 const float delta = 0.1f; // much smaller than the line width
1090 std::vector<Vec4> vertices;
1091 if (lineOrientation == LINE_ORIENTATION_AXIS_ALIGNED)
1093 // Axis-aligned lines just outside the clip volume.
1094 const float p = 1.0f + delta;
1095 const float q = 0.9f;
1097 vertices.push_back(Vec4(-p, -q, 0.1f, 1.0f));
1098 vertices.push_back(Vec4(-p, q, 0.9f, 1.0f)); // line 0
1099 vertices.push_back(Vec4(-q, p, 0.1f, 1.0f));
1100 vertices.push_back(Vec4( q, p, 0.9f, 1.0f)); // line 1
1101 vertices.push_back(Vec4( p, q, 0.1f, 1.0f));
1102 vertices.push_back(Vec4( p, -q, 0.9f, 1.0f)); // line 2
1103 vertices.push_back(Vec4( q, -p, 0.1f, 1.0f));
1104 vertices.push_back(Vec4(-q, -p, 0.9f, 1.0f)); // line 3
1106 else if (lineOrientation == LINE_ORIENTATION_DIAGONAL)
1108 // Diagonal lines just outside the clip volume.
1109 const float p = 2.0f + delta;
1111 vertices.push_back(Vec4( -p, 0.0f, 0.1f, 1.0f));
1112 vertices.push_back(Vec4(0.0f, -p, 0.9f, 1.0f)); // line 0
1113 vertices.push_back(Vec4(0.0f, -p, 0.1f, 1.0f));
1114 vertices.push_back(Vec4( p, 0.0f, 0.9f, 1.0f)); // line 1
1115 vertices.push_back(Vec4( p, 0.0f, 0.1f, 1.0f));
1116 vertices.push_back(Vec4(0.0f, p, 0.9f, 1.0f)); // line 2
1117 vertices.push_back(Vec4(0.0f, p, 0.1f, 1.0f));
1118 vertices.push_back(Vec4( -p, 0.0f, 0.9f, 1.0f)); // line 3
1123 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
1125 const float lineWidth = std::min(static_cast<float>(RENDER_SIZE), limits.lineWidthRange[1]);
1126 tcu::TestLog& log = context.getTestContext().getLog();
1128 log << tcu::TestLog::Message << "Drawing several wide lines just outside the clip volume. Expecting an empty image." << tcu::TestLog::EndMessage
1129 << tcu::TestLog::Message << "Line width is " << lineWidth << "." << tcu::TestLog::EndMessage;
1131 DrawContext drawContext(context, shaders, vertices, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, static_cast<deUint32>(RENDER_SIZE), false, false, lineWidth);
1134 // All pixels must be black -- nothing is drawn.
1135 const int numBlackPixels = countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
1137 return (numBlackPixels == NUM_RENDER_PIXELS ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
1142 namespace ClipDistance
1145 struct CaseDefinition
1147 const VkPrimitiveTopology topology;
1148 const bool dynamicIndexing;
1149 const bool enableTessellation;
1150 const bool enableGeometry;
1151 const int numClipDistances;
1152 const int numCullDistances;
1154 CaseDefinition (const VkPrimitiveTopology topology_,
1155 const int numClipDistances_,
1156 const int numCullDistances_,
1157 const bool enableTessellation_,
1158 const bool enableGeometry_,
1159 const bool dynamicIndexing_)
1160 : topology (topology_)
1161 , dynamicIndexing (dynamicIndexing_)
1162 , enableTessellation (enableTessellation_)
1163 , enableGeometry (enableGeometry_)
1164 , numClipDistances (numClipDistances_)
1165 , numCullDistances (numCullDistances_)
1170 void initPrograms (SourceCollections& programCollection, const CaseDefinition caseDef)
1172 DE_ASSERT(caseDef.numClipDistances + caseDef.numCullDistances <= MAX_COMBINED_CLIP_AND_CULL_DISTANCES);
1174 std::string perVertexBlock;
1176 std::ostringstream str;
1177 str << "gl_PerVertex {\n"
1178 << " vec4 gl_Position;\n";
1179 if (caseDef.numClipDistances > 0)
1180 str << " float gl_ClipDistance[" << caseDef.numClipDistances << "];\n";
1181 if (caseDef.numCullDistances > 0)
1182 str << " float gl_CullDistance[" << caseDef.numCullDistances << "];\n";
1184 perVertexBlock = str.str();
1189 std::ostringstream src;
1190 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1192 << "layout(location = 0) in vec4 v_position;\n"
1193 << "layout(location = 0) out vec4 out_color;\n"
1195 << "out " << perVertexBlock << ";\n"
1197 << "void main (void)\n"
1199 << " gl_Position = v_position;\n"
1200 << " out_color = vec4(1.0, 0.5 * (v_position.x + 1.0), 0.0, 1.0);\n"
1202 << " const int barNdx = gl_VertexIndex / 6;\n";
1203 if (caseDef.dynamicIndexing)
1205 if (caseDef.numClipDistances > 0)
1206 src << " for (int i = 0; i < " << caseDef.numClipDistances << "; ++i)\n"
1207 << " gl_ClipDistance[i] = (barNdx == i ? v_position.y : 0.0);\n";
1208 if (caseDef.numCullDistances > 0)
1209 src << " for (int i = 0; i < " << caseDef.numCullDistances << "; ++i)\n"
1210 << " gl_CullDistance[i] = 0.0;\n";
1214 for (int i = 0; i < caseDef.numClipDistances; ++i)
1215 src << " gl_ClipDistance[" << i << "] = (barNdx == " << i << " ? v_position.y : 0.0);\n";
1216 for (int i = 0; i < caseDef.numCullDistances; ++i)
1217 src << " gl_CullDistance[" << i << "] = 0.0;\n"; // don't cull anything
1221 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1224 if (caseDef.enableTessellation)
1226 std::ostringstream src;
1227 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1229 << "layout(vertices = " << NUM_PATCH_CONTROL_POINTS << ") out;\n"
1231 << "layout(location = 0) in vec4 in_color[];\n"
1232 << "layout(location = 0) out vec4 out_color[];\n"
1234 << "in " << perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
1236 << "out " << perVertexBlock << " gl_out[];\n"
1238 << "void main (void)\n"
1240 << " gl_TessLevelInner[0] = 1.0;\n"
1241 << " gl_TessLevelInner[1] = 1.0;\n"
1243 << " gl_TessLevelOuter[0] = 1.0;\n"
1244 << " gl_TessLevelOuter[1] = 1.0;\n"
1245 << " gl_TessLevelOuter[2] = 1.0;\n"
1246 << " gl_TessLevelOuter[3] = 1.0;\n"
1248 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1249 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
1251 if (caseDef.dynamicIndexing)
1253 if (caseDef.numClipDistances > 0)
1254 src << " for (int i = 0; i < " << caseDef.numClipDistances << "; ++i)\n"
1255 << " gl_out[gl_InvocationID].gl_ClipDistance[i] = gl_in[gl_InvocationID].gl_ClipDistance[i];\n";
1256 if (caseDef.numCullDistances > 0)
1257 src << " for (int i = 0; i < " << caseDef.numCullDistances << "; ++i)\n"
1258 << " gl_out[gl_InvocationID].gl_CullDistance[i] = gl_in[gl_InvocationID].gl_CullDistance[i];\n";
1262 for (int i = 0; i < caseDef.numClipDistances; ++i)
1263 src << " gl_out[gl_InvocationID].gl_ClipDistance[" << i << "] = gl_in[gl_InvocationID].gl_ClipDistance[" << i << "];\n";
1264 for (int i = 0; i < caseDef.numCullDistances; ++i)
1265 src << " gl_out[gl_InvocationID].gl_CullDistance[" << i << "] = gl_in[gl_InvocationID].gl_CullDistance[" << i << "];\n";
1269 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
1272 if (caseDef.enableTessellation)
1274 DE_ASSERT(NUM_PATCH_CONTROL_POINTS == 3); // assumed in shader code
1276 std::ostringstream src;
1277 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1279 << "layout(triangles, equal_spacing, ccw) in;\n"
1281 << "layout(location = 0) in vec4 in_color[];\n"
1282 << "layout(location = 0) out vec4 out_color;\n"
1284 << "in " << perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
1286 << "out " << perVertexBlock << ";\n"
1288 << "void main (void)\n"
1290 << " vec3 px = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n"
1291 << " vec3 py = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n"
1292 << " vec3 pz = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
1293 << " gl_Position = vec4(px + py + pz, 1.0);\n"
1294 << " out_color = (in_color[0] + in_color[1] + in_color[2]) / 3.0;\n"
1296 if (caseDef.dynamicIndexing)
1298 if (caseDef.numClipDistances > 0)
1299 src << " for (int i = 0; i < " << caseDef.numClipDistances << "; ++i)\n"
1300 << " gl_ClipDistance[i] = gl_TessCoord.x * gl_in[0].gl_ClipDistance[i]\n"
1301 << " + gl_TessCoord.y * gl_in[1].gl_ClipDistance[i]\n"
1302 << " + gl_TessCoord.z * gl_in[2].gl_ClipDistance[i];\n";
1303 if (caseDef.numCullDistances > 0)
1304 src << " for (int i = 0; i < " << caseDef.numCullDistances << "; ++i)\n"
1305 << " gl_CullDistance[i] = gl_TessCoord.x * gl_in[0].gl_CullDistance[i]\n"
1306 << " + gl_TessCoord.y * gl_in[1].gl_CullDistance[i]\n"
1307 << " + gl_TessCoord.z * gl_in[2].gl_CullDistance[i];\n";
1311 for (int i = 0; i < caseDef.numClipDistances; ++i)
1312 src << " gl_ClipDistance[" << i << "] = gl_TessCoord.x * gl_in[0].gl_ClipDistance[" << i << "]\n"
1313 << " + gl_TessCoord.y * gl_in[1].gl_ClipDistance[" << i << "]\n"
1314 << " + gl_TessCoord.z * gl_in[2].gl_ClipDistance[" << i << "];\n";
1315 for (int i = 0; i < caseDef.numCullDistances; ++i)
1316 src << " gl_CullDistance[" << i << "] = gl_TessCoord.x * gl_in[0].gl_CullDistance[" << i << "]\n"
1317 << " + gl_TessCoord.y * gl_in[1].gl_CullDistance[" << i << "]\n"
1318 << " + gl_TessCoord.z * gl_in[2].gl_CullDistance[" << i << "];\n";
1322 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
1325 if (caseDef.enableGeometry)
1327 std::ostringstream src;
1328 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1330 << "layout(triangles) in;\n"
1331 << "layout(triangle_strip, max_vertices = 3) out;\n"
1333 << "layout(location = 0) in vec4 in_color[];\n"
1334 << "layout(location = 0) out vec4 out_color;\n"
1336 << "in " << perVertexBlock << " gl_in[];\n"
1338 << "out " << perVertexBlock << ";\n"
1340 << "void main (void)\n"
1342 for (int vertNdx = 0; vertNdx < 3; ++vertNdx)
1346 src << " gl_Position = gl_in[" << vertNdx << "].gl_Position;\n"
1347 << " out_color = in_color[" << vertNdx << "];\n";
1348 if (caseDef.dynamicIndexing)
1350 if (caseDef.numClipDistances > 0)
1351 src << " for (int i = 0; i < " << caseDef.numClipDistances << "; ++i)\n"
1352 << " gl_ClipDistance[i] = gl_in[" << vertNdx << "].gl_ClipDistance[i];\n";
1353 if (caseDef.numCullDistances > 0)
1354 src << " for (int i = 0; i < " << caseDef.numCullDistances << "; ++i)\n"
1355 << " gl_CullDistance[i] = gl_in[" << vertNdx << "].gl_CullDistance[i];\n";
1359 for (int i = 0; i < caseDef.numClipDistances; ++i)
1360 src << " gl_ClipDistance[" << i << "] = gl_in[" << vertNdx << "].gl_ClipDistance[" << i << "];\n";
1361 for (int i = 0; i < caseDef.numCullDistances; ++i)
1362 src << " gl_CullDistance[" << i << "] = gl_in[" << vertNdx << "].gl_CullDistance[" << i << "];\n";
1364 src << " EmitVertex();\n";
1368 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1373 std::ostringstream src;
1374 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1376 << "layout(location = 0) in flat vec4 in_color;\n"
1377 << "layout(location = 0) out vec4 o_color;\n"
1379 << "void main (void)\n"
1381 << " o_color = vec4(in_color.rgb + vec3(0.0, 0.0, 0.5), 1.0);\n" // mix with a constant color in case variable wasn't passed correctly through stages
1384 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1388 tcu::TestStatus testClipDistance (Context& context, const CaseDefinition caseDef)
1390 // Check test requirements
1392 const InstanceInterface& vki = context.getInstanceInterface();
1393 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1394 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
1396 FeatureFlags requirements = (FeatureFlags)0;
1398 if (caseDef.numClipDistances > 0)
1399 requirements |= FEATURE_SHADER_CLIP_DISTANCE;
1400 if (caseDef.numCullDistances > 0)
1401 requirements |= FEATURE_SHADER_CULL_DISTANCE;
1402 if (caseDef.enableTessellation)
1403 requirements |= FEATURE_TESSELLATION_SHADER;
1404 if (caseDef.enableGeometry)
1405 requirements |= FEATURE_GEOMETRY_SHADER;
1407 requireFeatures(vki, physDevice, requirements);
1409 // Check limits for supported features
1411 if (caseDef.numClipDistances > 0 && limits.maxClipDistances < MAX_CLIP_DISTANCES)
1412 return tcu::TestStatus::fail("maxClipDistances smaller than the minimum required by the spec");
1413 if (caseDef.numCullDistances > 0 && limits.maxCullDistances < MAX_CULL_DISTANCES)
1414 return tcu::TestStatus::fail("maxCullDistances smaller than the minimum required by the spec");
1415 if (caseDef.numCullDistances > 0 && limits.maxCombinedClipAndCullDistances < MAX_COMBINED_CLIP_AND_CULL_DISTANCES)
1416 return tcu::TestStatus::fail("maxCombinedClipAndCullDistances smaller than the minimum required by the spec");
1419 std::vector<Shader> shaders;
1420 shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert")));
1421 shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag")));
1422 if (caseDef.enableTessellation)
1424 shaders.push_back(Shader(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, context.getBinaryCollection().get("tesc")));
1425 shaders.push_back(Shader(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese")));
1427 if (caseDef.enableGeometry)
1428 shaders.push_back(Shader(VK_SHADER_STAGE_GEOMETRY_BIT, context.getBinaryCollection().get("geom")));
1430 const int numBars = MAX_COMBINED_CLIP_AND_CULL_DISTANCES;
1432 std::vector<Vec4> vertices;
1434 const float dx = 2.0f / numBars;
1435 for (int i = 0; i < numBars; ++i)
1437 const float x = -1.0f + dx * static_cast<float>(i);
1439 vertices.push_back(Vec4(x, -1.0f, 0.0f, 1.0f));
1440 vertices.push_back(Vec4(x, 1.0f, 0.0f, 1.0f));
1441 vertices.push_back(Vec4(x + dx, -1.0f, 0.0f, 1.0f));
1443 vertices.push_back(Vec4(x, 1.0f, 0.0f, 1.0f));
1444 vertices.push_back(Vec4(x + dx, 1.0f, 0.0f, 1.0f));
1445 vertices.push_back(Vec4(x + dx, -1.0f, 0.0f, 1.0f));
1449 tcu::TestLog& log = context.getTestContext().getLog();
1451 log << tcu::TestLog::Message << "Drawing " << numBars << " colored bars, clipping the first " << caseDef.numClipDistances << tcu::TestLog::EndMessage
1452 << tcu::TestLog::Message << "Using " << caseDef.numClipDistances << " ClipDistance(s) and " << caseDef.numCullDistances << " CullDistance(s)" << tcu::TestLog::EndMessage
1453 << tcu::TestLog::Message << "Expecting upper half of the clipped bars to be black." << tcu::TestLog::EndMessage;
1455 DrawContext drawContext(context, shaders, vertices, caseDef.topology);
1458 // Count black pixels in the whole image.
1459 const int numBlackPixels = countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
1460 const IVec2 clipRegion = IVec2(caseDef.numClipDistances * RENDER_SIZE / numBars, RENDER_SIZE / 2);
1461 const int expectedClippedPixels = clipRegion.x() * clipRegion.y();
1462 // Make sure the bottom half has no black pixels (possible if image became corrupted).
1463 const int guardPixels = countPixels(drawContext.getColorPixels(), IVec2(0, RENDER_SIZE/2), clipRegion, Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
1465 return (numBlackPixels == expectedClippedPixels && guardPixels == 0 ? tcu::TestStatus::pass("OK")
1466 : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
1469 } // ClipDistance ns
1471 namespace ClipDistanceComplementarity
1474 void initPrograms (SourceCollections& programCollection, const int numClipDistances)
1478 DE_ASSERT(numClipDistances > 0);
1479 const int clipDistanceLastNdx = numClipDistances - 1;
1481 std::ostringstream src;
1482 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1484 << "layout(location = 0) in vec4 v_position; // we are passing ClipDistance in w component\n"
1486 << "out gl_PerVertex {\n"
1487 << " vec4 gl_Position;\n"
1488 << " float gl_ClipDistance[" << numClipDistances << "];\n"
1491 << "void main (void)\n"
1493 << " gl_Position = vec4(v_position.xyz, 1.0);\n";
1494 for (int i = 0; i < clipDistanceLastNdx; ++i)
1495 src << " gl_ClipDistance[" << i << "] = 0.0;\n";
1496 src << " gl_ClipDistance[" << clipDistanceLastNdx << "] = v_position.w;\n"
1499 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1504 std::ostringstream src;
1505 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1507 << "layout(location = 0) out vec4 o_color;\n"
1509 << "void main (void)\n"
1511 << " o_color = vec4(1.0, 1.0, 1.0, 0.5);\n"
1514 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1518 tcu::TestStatus testComplementarity (Context& context, const int numClipDistances)
1520 // Check test requirements
1522 const InstanceInterface& vki = context.getInstanceInterface();
1523 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1525 requireFeatures(vki, physDevice, FEATURE_SHADER_CLIP_DISTANCE);
1528 std::vector<Shader> shaders;
1529 shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert")));
1530 shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag")));
1532 std::vector<Vec4> vertices;
1534 de::Random rnd (1234);
1535 const int numSections = 16;
1536 const int numVerticesPerSection = 4; // logical verticies, due to triangle list topology we actually use 6 per section
1538 DE_ASSERT(RENDER_SIZE_LARGE % numSections == 0);
1540 std::vector<float> clipDistances(numVerticesPerSection * numSections);
1541 for (int i = 0; i < static_cast<int>(clipDistances.size()); ++i)
1542 clipDistances[i] = rnd.getFloat(-1.0f, 1.0f);
1544 // Two sets of identical primitives, but with a different ClipDistance sign.
1545 for (int setNdx = 0; setNdx < 2; ++setNdx)
1547 const float sign = (setNdx == 0 ? 1.0f : -1.0f);
1548 const float dx = 2.0f / static_cast<float>(numSections);
1550 for (int i = 0; i < numSections; ++i)
1552 const int ndxBase = numVerticesPerSection * i;
1553 const float x = -1.0f + dx * static_cast<float>(i);
1554 const Vec4 p0 = Vec4(x, -1.0f, 0.0f, sign * clipDistances[ndxBase + 0]);
1555 const Vec4 p1 = Vec4(x, 1.0f, 0.0f, sign * clipDistances[ndxBase + 1]);
1556 const Vec4 p2 = Vec4(x + dx, 1.0f, 0.0f, sign * clipDistances[ndxBase + 2]);
1557 const Vec4 p3 = Vec4(x + dx, -1.0f, 0.0f, sign * clipDistances[ndxBase + 3]);
1559 vertices.push_back(p0);
1560 vertices.push_back(p1);
1561 vertices.push_back(p2);
1563 vertices.push_back(p2);
1564 vertices.push_back(p3);
1565 vertices.push_back(p0);
1570 tcu::TestLog& log = context.getTestContext().getLog();
1572 log << tcu::TestLog::Message << "Draw two sets of primitives with blending, differing only with ClipDistance sign." << tcu::TestLog::EndMessage
1573 << tcu::TestLog::Message << "Using " << numClipDistances << " clipping plane(s), one of them possibly having negative values." << tcu::TestLog::EndMessage
1574 << tcu::TestLog::Message << "Expecting a uniform gray area, no missing (black) nor overlapped (white) pixels." << tcu::TestLog::EndMessage;
1576 DrawContext drawContext(context, shaders, vertices, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, static_cast<deUint32>(RENDER_SIZE_LARGE), false, true);
1579 const int numGrayPixels = countPixels(drawContext.getColorPixels(), Vec4(0.5f, 0.5f, 0.5f, 1.0f), Vec4(0.02f, 0.02f, 0.02f, 0.0f));
1580 const int numExpectedPixels = RENDER_SIZE_LARGE * RENDER_SIZE_LARGE;
1582 return (numGrayPixels == numExpectedPixels ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
1585 } // ClipDistanceComplementarity ns
1587 void addClippingTests (tcu::TestCaseGroup* clippingTestsGroup)
1589 tcu::TestContext& testCtx = clippingTestsGroup->getTestContext();
1591 // Clipping against the clip volume
1593 using namespace ClipVolume;
1595 static const VkPrimitiveTopology cases[] =
1597 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1598 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
1599 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
1600 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
1601 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
1602 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1603 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
1604 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1605 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
1606 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
1609 MovePtr<tcu::TestCaseGroup> clipVolumeGroup(new tcu::TestCaseGroup(testCtx, "clip_volume", "clipping with the clip volume"));
1611 // Fully inside the clip volume
1613 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "inside", ""));
1615 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
1616 addFunctionCaseWithPrograms<VkPrimitiveTopology>(
1617 group.get(), getPrimitiveTopologyShortName(cases[caseNdx]), "", initPrograms, testPrimitivesInside, cases[caseNdx]);
1619 clipVolumeGroup->addChild(group.release());
1622 // Fully outside the clip volume
1624 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "outside", ""));
1626 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
1627 addFunctionCaseWithPrograms<VkPrimitiveTopology>(
1628 group.get(), getPrimitiveTopologyShortName(cases[caseNdx]), "", initPrograms, testPrimitivesOutside, cases[caseNdx]);
1630 clipVolumeGroup->addChild(group.release());
1635 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "depth_clamp", ""));
1637 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
1638 addFunctionCaseWithPrograms<VkPrimitiveTopology>(
1639 group.get(), getPrimitiveTopologyShortName(cases[caseNdx]), "", initPrograms, testPrimitivesDepthClamp, cases[caseNdx]);
1641 clipVolumeGroup->addChild(group.release());
1644 // Large points and wide lines
1646 // \note For both points and lines, if an unsupported size/width is selected, the nearest supported size will be chosen.
1647 // We do have to check for feature support though.
1649 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "clipped", ""));
1651 addFunctionCaseWithPrograms(group.get(), "large_points", "", initProgramsPointSize, testLargePoints);
1653 addFunctionCaseWithPrograms<LineOrientation>(group.get(), "wide_lines_axis_aligned", "", initPrograms, testWideLines, LINE_ORIENTATION_AXIS_ALIGNED);
1654 addFunctionCaseWithPrograms<LineOrientation>(group.get(), "wide_lines_diagonal", "", initPrograms, testWideLines, LINE_ORIENTATION_DIAGONAL);
1656 clipVolumeGroup->addChild(group.release());
1659 clippingTestsGroup->addChild(clipVolumeGroup.release());
1662 // User-defined clip planes
1664 MovePtr<tcu::TestCaseGroup> clipDistanceGroup(new tcu::TestCaseGroup(testCtx, "user_defined", "user-defined clip planes"));
1666 // ClipDistance, CullDistance and maxCombinedClipAndCullDistances usage
1668 using namespace ClipDistance;
1672 const char* const groupName;
1673 const char* const description;
1674 bool useCullDistance;
1677 { "clip_distance", "use ClipDistance", false },
1678 { "clip_cull_distance", "use ClipDistance and CullDistance at the same time", true },
1681 const deUint32 flagTessellation = 1u << 0;
1682 const deUint32 flagGeometry = 1u << 1;
1684 for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(caseGroups); ++groupNdx)
1685 for (int indexingMode = 0; indexingMode < 2; ++indexingMode)
1687 const bool dynamicIndexing = (indexingMode == 1);
1688 const std::string mainGroupName = de::toString(caseGroups[groupNdx].groupName) + (dynamicIndexing ? "_dynamic_index" : "");
1690 MovePtr<tcu::TestCaseGroup> mainGroup(new tcu::TestCaseGroup(testCtx, mainGroupName.c_str(), ""));
1692 for (deUint32 shaderMask = 0u; shaderMask <= (flagTessellation | flagGeometry); ++shaderMask)
1694 const bool useTessellation = (shaderMask & flagTessellation) != 0;
1695 const bool useGeometry = (shaderMask & flagGeometry) != 0;
1696 const std::string shaderGroupName = std::string("vert") + (useTessellation ? "_tess" : "") + (useGeometry ? "_geom" : "");
1698 MovePtr<tcu::TestCaseGroup> shaderGroup(new tcu::TestCaseGroup(testCtx, shaderGroupName.c_str(), ""));
1700 for (int numClipPlanes = 1; numClipPlanes <= MAX_CLIP_DISTANCES; ++numClipPlanes)
1702 const int numCullPlanes = (caseGroups[groupNdx].useCullDistance
1703 ? std::min(static_cast<int>(MAX_CULL_DISTANCES), MAX_COMBINED_CLIP_AND_CULL_DISTANCES - numClipPlanes)
1705 const std::string caseName = de::toString(numClipPlanes) + (numCullPlanes > 0 ? "_" + de::toString(numCullPlanes) : "");
1706 const VkPrimitiveTopology topology = (useTessellation ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1708 addFunctionCaseWithPrograms<CaseDefinition>(
1709 shaderGroup.get(), caseName, caseGroups[groupNdx].description, initPrograms, testClipDistance,
1710 CaseDefinition(topology, numClipPlanes, numCullPlanes, useTessellation, useGeometry, dynamicIndexing));
1712 mainGroup->addChild(shaderGroup.release());
1714 clipDistanceGroup->addChild(mainGroup.release());
1718 // Complementarity criterion (i.e. clipped and not clipped areas must add up to a complete primitive with no holes nor overlap)
1720 using namespace ClipDistanceComplementarity;
1722 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "complementarity", ""));
1724 for (int numClipDistances = 1; numClipDistances <= MAX_CLIP_DISTANCES; ++numClipDistances)
1725 addFunctionCaseWithPrograms<int>(group.get(), de::toString(numClipDistances).c_str(), "", initPrograms, testComplementarity, numClipDistances);
1727 clippingTestsGroup->addChild(group.release());
1730 clippingTestsGroup->addChild(clipDistanceGroup.release());
1736 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
1738 return createTestGroup(testCtx, "clipping", "Clipping tests", addClippingTests);