1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2014 The Android Open Source Project
6 * Copyright (c) 2016 The Khronos Group Inc.
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 Tessellation Utilities
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktTessellationUtil.hpp"
26 #include "vkTypeUtil.hpp"
27 #include "vkCmdUtil.hpp"
28 #include "deMath.h"
29
30 namespace vkt
31 {
32 namespace tessellation
33 {
34
35 using namespace vk;
36
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)37 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize,
38 const VkBufferUsageFlags usage)
39 {
40 const VkBufferCreateInfo bufferCreateInfo =
41 {
42 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
43 DE_NULL, // const void* pNext;
44 (VkBufferCreateFlags)0, // VkBufferCreateFlags flags;
45 bufferSize, // VkDeviceSize size;
46 usage, // VkBufferUsageFlags usage;
47 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
48 0u, // deUint32 queueFamilyIndexCount;
49 DE_NULL, // const deUint32* pQueueFamilyIndices;
50 };
51 return bufferCreateInfo;
52 }
53
makeCommandPool(const DeviceInterface & vk,const VkDevice device,const deUint32 queueFamilyIndex)54 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
55 {
56 const VkCommandPoolCreateInfo info =
57 {
58 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
59 DE_NULL, // const void* pNext;
60 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
61 queueFamilyIndex, // deUint32 queueFamilyIndex;
62 };
63 return createCommandPool(vk, device, &info);
64 }
65
66
makeDescriptorSet(const DeviceInterface & vk,const VkDevice device,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)67 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface& vk,
68 const VkDevice device,
69 const VkDescriptorPool descriptorPool,
70 const VkDescriptorSetLayout setLayout)
71 {
72 const VkDescriptorSetAllocateInfo info =
73 {
74 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
75 DE_NULL, // const void* pNext;
76 descriptorPool, // VkDescriptorPool descriptorPool;
77 1u, // deUint32 descriptorSetCount;
78 &setLayout, // const VkDescriptorSetLayout* pSetLayouts;
79 };
80 return allocateDescriptorSet(vk, device, &info);
81 }
82
makePipelineLayout(const DeviceInterface & vk,const VkDevice device,const VkDescriptorSetLayout descriptorSetLayout)83 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
84 const VkDevice device,
85 const VkDescriptorSetLayout descriptorSetLayout)
86 {
87 const VkPipelineLayoutCreateInfo info =
88 {
89 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
90 DE_NULL, // const void* pNext;
91 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
92 1u, // deUint32 setLayoutCount;
93 &descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
94 0u, // deUint32 pushConstantRangeCount;
95 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
96 };
97 return createPipelineLayout(vk, device, &info);
98 }
99
makePipelineLayoutWithoutDescriptors(const DeviceInterface & vk,const VkDevice device)100 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface& vk,
101 const VkDevice device)
102 {
103 const VkPipelineLayoutCreateInfo info =
104 {
105 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
106 DE_NULL, // const void* pNext;
107 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
108 0u, // deUint32 setLayoutCount;
109 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
110 0u, // deUint32 pushConstantRangeCount;
111 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
112 };
113 return createPipelineLayout(vk, device, &info);
114 }
115
makeComputePipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkShaderModule shaderModule,const VkSpecializationInfo * specInfo)116 Move<VkPipeline> makeComputePipeline (const DeviceInterface& vk,
117 const VkDevice device,
118 const VkPipelineLayout pipelineLayout,
119 const VkShaderModule shaderModule,
120 const VkSpecializationInfo* specInfo)
121 {
122 const VkPipelineShaderStageCreateInfo shaderStageInfo =
123 {
124 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
125 DE_NULL, // const void* pNext;
126 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
127 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
128 shaderModule, // VkShaderModule module;
129 "main", // const char* pName;
130 specInfo, // const VkSpecializationInfo* pSpecializationInfo;
131 };
132 const VkComputePipelineCreateInfo pipelineInfo =
133 {
134 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
135 DE_NULL, // const void* pNext;
136 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
137 shaderStageInfo, // VkPipelineShaderStageCreateInfo stage;
138 pipelineLayout, // VkPipelineLayout layout;
139 DE_NULL, // VkPipeline basePipelineHandle;
140 0, // deInt32 basePipelineIndex;
141 };
142 return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
143 }
144
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage,const deUint32 numArrayLayers)145 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers)
146 {
147 const VkImageCreateInfo imageInfo =
148 {
149 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
150 DE_NULL, // const void* pNext;
151 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
152 VK_IMAGE_TYPE_2D, // VkImageType imageType;
153 format, // VkFormat format;
154 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
155 1u, // uint32_t mipLevels;
156 numArrayLayers, // uint32_t arrayLayers;
157 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
158 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
159 usage, // VkImageUsageFlags usage;
160 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
161 0u, // uint32_t queueFamilyIndexCount;
162 DE_NULL, // const uint32_t* pQueueFamilyIndices;
163 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
164 };
165 return imageInfo;
166 }
167
makeImageView(const DeviceInterface & vk,const VkDevice vkDevice,const VkImage image,const VkImageViewType viewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)168 Move<VkImageView> makeImageView (const DeviceInterface& vk,
169 const VkDevice vkDevice,
170 const VkImage image,
171 const VkImageViewType viewType,
172 const VkFormat format,
173 const VkImageSubresourceRange subresourceRange)
174 {
175 const VkImageViewCreateInfo imageViewParams =
176 {
177 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
178 DE_NULL, // const void* pNext;
179 (VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags;
180 image, // VkImage image;
181 viewType, // VkImageViewType viewType;
182 format, // VkFormat format;
183 makeComponentMappingRGBA(), // VkComponentMapping components;
184 subresourceRange, // VkImageSubresourceRange subresourceRange;
185 };
186 return createImageView(vk, vkDevice, &imageViewParams);
187 }
188
makeBufferImageCopy(const VkExtent3D extent,const VkImageSubresourceLayers subresourceLayers)189 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D extent,
190 const VkImageSubresourceLayers subresourceLayers)
191 {
192 const VkBufferImageCopy copyParams =
193 {
194 0ull, // VkDeviceSize bufferOffset;
195 0u, // deUint32 bufferRowLength;
196 0u, // deUint32 bufferImageHeight;
197 subresourceLayers, // VkImageSubresourceLayers imageSubresource;
198 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
199 extent, // VkExtent3D imageExtent;
200 };
201 return copyParams;
202 }
203
beginRenderPassWithRasterizationDisabled(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const VkFramebuffer framebuffer)204 void beginRenderPassWithRasterizationDisabled (const DeviceInterface& vk,
205 const VkCommandBuffer commandBuffer,
206 const VkRenderPass renderPass,
207 const VkFramebuffer framebuffer)
208 {
209 beginRenderPass(vk, commandBuffer, renderPass, framebuffer, makeRect2D(0, 0, 0u, 0u));
210 }
211
makeRenderPassWithoutAttachments(const DeviceInterface & vk,const VkDevice device)212 Move<VkRenderPass> makeRenderPassWithoutAttachments (const DeviceInterface& vk,
213 const VkDevice device)
214 {
215 const VkAttachmentReference unusedAttachment =
216 {
217 VK_ATTACHMENT_UNUSED, // deUint32 attachment;
218 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout;
219 };
220
221 const VkSubpassDescription subpassDescription =
222 {
223 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
224 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
225 0u, // deUint32 inputAttachmentCount;
226 DE_NULL, // const VkAttachmentReference* pInputAttachments;
227 0u, // deUint32 colorAttachmentCount;
228 DE_NULL, // const VkAttachmentReference* pColorAttachments;
229 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
230 &unusedAttachment, // const VkAttachmentReference* pDepthStencilAttachment;
231 0u, // deUint32 preserveAttachmentCount;
232 DE_NULL // const deUint32* pPreserveAttachments;
233 };
234
235 const VkRenderPassCreateInfo renderPassInfo =
236 {
237 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
238 DE_NULL, // const void* pNext;
239 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
240 0u, // deUint32 attachmentCount;
241 DE_NULL, // const VkAttachmentDescription* pAttachments;
242 1u, // deUint32 subpassCount;
243 &subpassDescription, // const VkSubpassDescription* pSubpasses;
244 0u, // deUint32 dependencyCount;
245 DE_NULL // const VkSubpassDependency* pDependencies;
246 };
247
248 return createRenderPass(vk, device, &renderPassInfo);
249 }
250
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const VkImageView colorAttachment,const deUint32 width,const deUint32 height,const deUint32 layers)251 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk,
252 const VkDevice device,
253 const VkRenderPass renderPass,
254 const VkImageView colorAttachment,
255 const deUint32 width,
256 const deUint32 height,
257 const deUint32 layers)
258 {
259 const VkFramebufferCreateInfo framebufferInfo = {
260 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
261 DE_NULL, // const void* pNext;
262 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
263 renderPass, // VkRenderPass renderPass;
264 1u, // uint32_t attachmentCount;
265 &colorAttachment, // const VkImageView* pAttachments;
266 width, // uint32_t width;
267 height, // uint32_t height;
268 layers, // uint32_t layers;
269 };
270
271 return createFramebuffer(vk, device, &framebufferInfo);
272 }
273
makeFramebufferWithoutAttachments(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)274 Move<VkFramebuffer> makeFramebufferWithoutAttachments (const DeviceInterface& vk,
275 const VkDevice device,
276 const VkRenderPass renderPass)
277 {
278 const VkFramebufferCreateInfo framebufferInfo = {
279 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
280 DE_NULL, // const void* pNext;
281 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
282 renderPass, // VkRenderPass renderPass;
283 0u, // uint32_t attachmentCount;
284 DE_NULL, // const VkImageView* pAttachments;
285 1u, // uint32_t width;
286 1u, // uint32_t height;
287 1u, // uint32_t layers;
288 };
289
290 return createFramebuffer(vk, device, &framebufferInfo);
291 }
292
setShader(const DeviceInterface & vk,const VkDevice device,const VkShaderStageFlagBits stage,const ProgramBinary & binary,const VkSpecializationInfo * specInfo)293 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface& vk,
294 const VkDevice device,
295 const VkShaderStageFlagBits stage,
296 const ProgramBinary& binary,
297 const VkSpecializationInfo* specInfo)
298 {
299 VkShaderModule module;
300 switch (stage)
301 {
302 case (VK_SHADER_STAGE_VERTEX_BIT):
303 DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
304 m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
305 module = *m_vertexShaderModule;
306 break;
307
308 case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
309 DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
310 m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
311 module = *m_tessControlShaderModule;
312 break;
313
314 case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
315 DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
316 m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
317 module = *m_tessEvaluationShaderModule;
318 break;
319
320 case (VK_SHADER_STAGE_GEOMETRY_BIT):
321 DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
322 m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
323 module = *m_geometryShaderModule;
324 break;
325
326 case (VK_SHADER_STAGE_FRAGMENT_BIT):
327 DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
328 m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
329 module = *m_fragmentShaderModule;
330 break;
331
332 default:
333 DE_FATAL("Invalid shader stage");
334 return *this;
335 }
336
337 const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
338 {
339 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
340 DE_NULL, // const void* pNext;
341 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
342 stage, // VkShaderStageFlagBits stage;
343 module, // VkShaderModule module;
344 "main", // const char* pName;
345 specInfo, // const VkSpecializationInfo* pSpecializationInfo;
346 };
347
348 m_shaderStageFlags |= stage;
349 m_shaderStages.push_back(pipelineShaderStageInfo);
350
351 return *this;
352 }
353
setVertexInputSingleAttribute(const VkFormat vertexFormat,const deUint32 stride)354 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
355 {
356 const VkVertexInputBindingDescription bindingDesc =
357 {
358 0u, // uint32_t binding;
359 stride, // uint32_t stride;
360 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
361 };
362 const VkVertexInputAttributeDescription attributeDesc =
363 {
364 0u, // uint32_t location;
365 0u, // uint32_t binding;
366 vertexFormat, // VkFormat format;
367 0u, // uint32_t offset;
368 };
369
370 m_vertexInputBindings.clear();
371 m_vertexInputBindings.push_back(bindingDesc);
372
373 m_vertexInputAttributes.clear();
374 m_vertexInputAttributes.push_back(attributeDesc);
375
376 return *this;
377 }
378
379 template<typename T>
dataPointer(const std::vector<T> & vec)380 inline const T* dataPointer (const std::vector<T>& vec)
381 {
382 return (vec.size() != 0 ? &vec[0] : DE_NULL);
383 }
384
build(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass)385 Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface& vk,
386 const VkDevice device,
387 const VkPipelineLayout pipelineLayout,
388 const VkRenderPass renderPass)
389 {
390 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
391 {
392 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
393 DE_NULL, // const void* pNext;
394 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
395 static_cast<deUint32>(m_vertexInputBindings.size()), // uint32_t vertexBindingDescriptionCount;
396 dataPointer(m_vertexInputBindings), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
397 static_cast<deUint32>(m_vertexInputAttributes.size()), // uint32_t vertexAttributeDescriptionCount;
398 dataPointer(m_vertexInputAttributes), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
399 };
400
401 const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
402 : m_primitiveTopology;
403 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
404 {
405 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
406 DE_NULL, // const void* pNext;
407 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
408 topology, // VkPrimitiveTopology topology;
409 VK_FALSE, // VkBool32 primitiveRestartEnable;
410 };
411
412 const VkPipelineTessellationDomainOriginStateCreateInfo tessellationDomainOriginStateInfo =
413 {
414 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO,
415 DE_NULL,
416 (!m_tessellationDomainOrigin ? VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT : *m_tessellationDomainOrigin)
417 };
418 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
419 {
420 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
421 (!m_tessellationDomainOrigin ? DE_NULL : &tessellationDomainOriginStateInfo),
422 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
423 m_patchControlPoints, // uint32_t patchControlPoints;
424 };
425
426 const VkViewport viewport = makeViewport(m_renderSize);
427 const VkRect2D scissor = makeRect2D(m_renderSize);
428
429 const bool haveRenderSize = m_renderSize.x() > 0 && m_renderSize.y() > 0;
430
431 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
432 {
433 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
434 DE_NULL, // const void* pNext;
435 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
436 1u, // uint32_t viewportCount;
437 haveRenderSize ? &viewport : DE_NULL, // const VkViewport* pViewports;
438 1u, // uint32_t scissorCount;
439 haveRenderSize ? &scissor : DE_NULL, // const VkRect2D* pScissors;
440 };
441
442 const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
443 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
444 {
445 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
446 DE_NULL, // const void* pNext;
447 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
448 VK_FALSE, // VkBool32 depthClampEnable;
449 isRasterizationDisabled, // VkBool32 rasterizerDiscardEnable;
450 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
451 m_cullModeFlags, // VkCullModeFlags cullMode;
452 m_frontFace, // VkFrontFace frontFace;
453 VK_FALSE, // VkBool32 depthBiasEnable;
454 0.0f, // float depthBiasConstantFactor;
455 0.0f, // float depthBiasClamp;
456 0.0f, // float depthBiasSlopeFactor;
457 1.0f, // float lineWidth;
458 };
459
460 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
461 {
462 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
463 DE_NULL, // const void* pNext;
464 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
465 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
466 VK_FALSE, // VkBool32 sampleShadingEnable;
467 0.0f, // float minSampleShading;
468 DE_NULL, // const VkSampleMask* pSampleMask;
469 VK_FALSE, // VkBool32 alphaToCoverageEnable;
470 VK_FALSE // VkBool32 alphaToOneEnable;
471 };
472
473 const VkStencilOpState stencilOpState = makeStencilOpState(
474 VK_STENCIL_OP_KEEP, // stencil fail
475 VK_STENCIL_OP_KEEP, // depth & stencil pass
476 VK_STENCIL_OP_KEEP, // depth only fail
477 VK_COMPARE_OP_NEVER, // compare op
478 0u, // compare mask
479 0u, // write mask
480 0u); // reference
481
482 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
483 {
484 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
485 DE_NULL, // const void* pNext;
486 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
487 VK_FALSE, // VkBool32 depthTestEnable;
488 VK_FALSE, // VkBool32 depthWriteEnable;
489 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
490 VK_FALSE, // VkBool32 depthBoundsTestEnable;
491 VK_FALSE, // VkBool32 stencilTestEnable;
492 stencilOpState, // VkStencilOpState front;
493 stencilOpState, // VkStencilOpState back;
494 0.0f, // float minDepthBounds;
495 1.0f, // float maxDepthBounds;
496 };
497
498 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
499 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
500 {
501 m_blendEnable, // VkBool32 blendEnable;
502 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor;
503 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor;
504 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
505 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor;
506 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor;
507 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
508 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
509 };
510
511 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
512 {
513 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
514 DE_NULL, // const void* pNext;
515 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
516 VK_FALSE, // VkBool32 logicOpEnable;
517 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
518 1u, // deUint32 attachmentCount;
519 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
520 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
521 };
522
523 std::vector<VkDynamicState> dynamicStates;
524 if (!haveRenderSize && !isRasterizationDisabled)
525 {
526 dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
527 dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
528 }
529
530 const VkPipelineDynamicStateCreateInfo pipelineDynamicStateInfo =
531 {
532 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
533 DE_NULL, // const void* pNext;
534 0, // VkPipelineDynamicStateCreateFlags flags;
535 static_cast<deUint32>(dynamicStates.size()), // uint32_t dynamicStateCount;
536 (dynamicStates.empty() ? DE_NULL : &dynamicStates[0]), // const VkDynamicState* pDynamicStates;
537 };
538
539 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
540 {
541 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
542 DE_NULL, // const void* pNext;
543 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
544 static_cast<deUint32>(m_shaderStages.size()), // deUint32 stageCount;
545 &m_shaderStages[0], // const VkPipelineShaderStageCreateInfo* pStages;
546 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
547 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
548 (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo* pTessellationState;
549 (isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo), // const VkPipelineViewportStateCreateInfo* pViewportState;
550 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
551 (isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo), // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
552 (isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo), // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
553 (isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo), // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
554 (dynamicStates.empty() ? DE_NULL : &pipelineDynamicStateInfo), // const VkPipelineDynamicStateCreateInfo* pDynamicState;
555 pipelineLayout, // VkPipelineLayout layout;
556 renderPass, // VkRenderPass renderPass;
557 0u, // deUint32 subpass;
558 DE_NULL, // VkPipeline basePipelineHandle;
559 0, // deInt32 basePipelineIndex;
560 };
561
562 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
563 }
564
getClampedTessLevel(const SpacingMode mode,const float tessLevel)565 float getClampedTessLevel (const SpacingMode mode, const float tessLevel)
566 {
567 switch (mode)
568 {
569 case SPACINGMODE_EQUAL: return de::max(1.0f, tessLevel);
570 case SPACINGMODE_FRACTIONAL_ODD: return de::max(1.0f, tessLevel);
571 case SPACINGMODE_FRACTIONAL_EVEN: return de::max(2.0f, tessLevel);
572 default:
573 DE_ASSERT(false);
574 return 0.0f;
575 }
576 }
577
getRoundedTessLevel(const SpacingMode mode,const float clampedTessLevel)578 int getRoundedTessLevel (const SpacingMode mode, const float clampedTessLevel)
579 {
580 static const int minimumMaxTessGenLevel = 64; //!< Minimum maxTessellationGenerationLevel defined by the spec.
581
582 int result = (int)deFloatCeil(clampedTessLevel);
583
584 switch (mode)
585 {
586 case SPACINGMODE_EQUAL: break;
587 case SPACINGMODE_FRACTIONAL_ODD: result += 1 - result % 2; break;
588 case SPACINGMODE_FRACTIONAL_EVEN: result += result % 2; break;
589 default:
590 DE_ASSERT(false);
591 }
592 DE_ASSERT(de::inRange<int>(result, 1, minimumMaxTessGenLevel));
593 DE_UNREF(minimumMaxTessGenLevel);
594
595 return result;
596 }
597
getClampedRoundedTessLevel(const SpacingMode mode,const float tessLevel)598 int getClampedRoundedTessLevel (const SpacingMode mode, const float tessLevel)
599 {
600 return getRoundedTessLevel(mode, getClampedTessLevel(mode, tessLevel));
601 }
602
getClampedRoundedTriangleTessLevels(const SpacingMode spacingMode,const float * innerSrc,const float * outerSrc,int * innerDst,int * outerDst)603 void getClampedRoundedTriangleTessLevels (const SpacingMode spacingMode,
604 const float* innerSrc,
605 const float* outerSrc,
606 int* innerDst,
607 int* outerDst)
608 {
609 innerDst[0] = getClampedRoundedTessLevel(spacingMode, innerSrc[0]);
610 for (int i = 0; i < 3; i++)
611 outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
612 }
613
getClampedRoundedQuadTessLevels(const SpacingMode spacingMode,const float * innerSrc,const float * outerSrc,int * innerDst,int * outerDst)614 void getClampedRoundedQuadTessLevels (const SpacingMode spacingMode,
615 const float* innerSrc,
616 const float* outerSrc,
617 int* innerDst,
618 int* outerDst)
619 {
620 for (int i = 0; i < 2; i++)
621 innerDst[i] = getClampedRoundedTessLevel(spacingMode, innerSrc[i]);
622 for (int i = 0; i < 4; i++)
623 outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
624 }
625
getClampedRoundedIsolineTessLevels(const SpacingMode spacingMode,const float * outerSrc,int * outerDst)626 void getClampedRoundedIsolineTessLevels (const SpacingMode spacingMode,
627 const float* outerSrc,
628 int* outerDst)
629 {
630 outerDst[0] = getClampedRoundedTessLevel(SPACINGMODE_EQUAL, outerSrc[0]);
631 outerDst[1] = getClampedRoundedTessLevel(spacingMode, outerSrc[1]);
632 }
633
numOuterTessellationLevels(const TessPrimitiveType primType)634 int numOuterTessellationLevels (const TessPrimitiveType primType)
635 {
636 switch (primType)
637 {
638 case TESSPRIMITIVETYPE_TRIANGLES: return 3;
639 case TESSPRIMITIVETYPE_QUADS: return 4;
640 case TESSPRIMITIVETYPE_ISOLINES: return 2;
641 default:
642 DE_ASSERT(false);
643 return 0;
644 }
645 }
646
isPatchDiscarded(const TessPrimitiveType primitiveType,const float * outerLevels)647 bool isPatchDiscarded (const TessPrimitiveType primitiveType, const float* outerLevels)
648 {
649 const int numOuterLevels = numOuterTessellationLevels(primitiveType);
650 for (int i = 0; i < numOuterLevels; i++)
651 if (outerLevels[i] <= 0.0f)
652 return true;
653 return false;
654 }
655
getTessellationLevelsString(const TessLevels & tessLevels,const TessPrimitiveType primitiveType)656 std::string getTessellationLevelsString (const TessLevels& tessLevels, const TessPrimitiveType primitiveType)
657 {
658 std::ostringstream str;
659 switch (primitiveType)
660 {
661 case TESSPRIMITIVETYPE_ISOLINES:
662 str << "inner: { }, "
663 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << " }";
664 break;
665
666 case TESSPRIMITIVETYPE_TRIANGLES:
667 str << "inner: { " << tessLevels.inner[0] << " }, "
668 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << " }";
669 break;
670
671 case TESSPRIMITIVETYPE_QUADS:
672 str << "inner: { " << tessLevels.inner[0] << ", " << tessLevels.inner[1] << " }, "
673 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << ", " << tessLevels.outer[3] << " }";
674 break;
675
676 default:
677 DE_ASSERT(false);
678 }
679
680 return str.str();
681 }
682
683 //! Assumes array sizes inner[2] and outer[4].
getTessellationLevelsString(const float * inner,const float * outer)684 std::string getTessellationLevelsString (const float* inner, const float* outer)
685 {
686 const TessLevels tessLevels =
687 {
688 { inner[0], inner[1] },
689 { outer[0], outer[1], outer[2], outer[3] }
690 };
691 return getTessellationLevelsString(tessLevels, TESSPRIMITIVETYPE_QUADS);
692 }
693
694 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
695 // (e.g. it may not exactly hold that u+v+w == 1.0f, or [uvw] + (1.0f-[uvw]) == 1.0f).
generateReferenceTriangleTessCoords(const SpacingMode spacingMode,const int inner,const int outer0,const int outer1,const int outer2)696 std::vector<tcu::Vec3> generateReferenceTriangleTessCoords (const SpacingMode spacingMode,
697 const int inner,
698 const int outer0,
699 const int outer1,
700 const int outer2)
701 {
702 std::vector<tcu::Vec3> tessCoords;
703
704 if (inner == 1)
705 {
706 if (outer0 == 1 && outer1 == 1 && outer2 == 1)
707 {
708 tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
709 tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
710 tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 1.0f));
711 return tessCoords;
712 }
713 else
714 return generateReferenceTriangleTessCoords(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
715 outer0, outer1, outer2);
716 }
717 else
718 {
719 for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3( 0.0f, v, 1.0f - v)); }
720 for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v, 0.0f, v)); }
721 for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3( v, 1.0f - v, 0.0f)); }
722
723 const int numInnerTriangles = inner/2;
724 for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
725 {
726 const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
727
728 if (curInnerTriangleLevel == 0)
729 tessCoords.push_back(tcu::Vec3(1.0f/3.0f));
730 else
731 {
732 const float minUVW = (float)(2 * (innerTriangleNdx + 1)) / (float)(3 * inner);
733 const float maxUVW = 1.0f - 2.0f*minUVW;
734 const tcu::Vec3 corners[3] =
735 {
736 tcu::Vec3(maxUVW, minUVW, minUVW),
737 tcu::Vec3(minUVW, maxUVW, minUVW),
738 tcu::Vec3(minUVW, minUVW, maxUVW)
739 };
740
741 for (int i = 0; i < curInnerTriangleLevel; i++)
742 {
743 const float f = (float)i / (float)curInnerTriangleLevel;
744 for (int j = 0; j < 3; j++)
745 tessCoords.push_back((1.0f - f)*corners[j] + f*corners[(j+1)%3]);
746 }
747 }
748 }
749
750 return tessCoords;
751 }
752 }
753
754 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
755 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
generateReferenceQuadTessCoords(const SpacingMode spacingMode,const int inner0,const int inner1,const int outer0,const int outer1,const int outer2,const int outer3)756 std::vector<tcu::Vec3> generateReferenceQuadTessCoords (const SpacingMode spacingMode,
757 const int inner0,
758 const int inner1,
759 const int outer0,
760 const int outer1,
761 const int outer2,
762 const int outer3)
763 {
764 std::vector<tcu::Vec3> tessCoords;
765
766 if (inner0 == 1 || inner1 == 1)
767 {
768 if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
769 {
770 tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 0.0f));
771 tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
772 tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
773 tessCoords.push_back(tcu::Vec3(1.0f, 1.0f, 0.0f));
774 return tessCoords;
775 }
776 else
777 return generateReferenceQuadTessCoords(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
778 inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
779 outer0, outer1, outer2, outer3);
780 }
781 else
782 {
783 for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3( 0.0f, v, 0.0f)); }
784 for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v, 0.0f, 0.0f)); }
785 for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3( 1.0f, 1.0f - v, 0.0f)); }
786 for (int i = 0; i < outer3; i++) { const float v = (float)i / (float)outer3; tessCoords.push_back(tcu::Vec3( v, 1.0f, 0.0f)); }
787
788 for (int innerVtxY = 0; innerVtxY < inner1-1; innerVtxY++)
789 for (int innerVtxX = 0; innerVtxX < inner0-1; innerVtxX++)
790 tessCoords.push_back(tcu::Vec3((float)(innerVtxX + 1) / (float)inner0,
791 (float)(innerVtxY + 1) / (float)inner1,
792 0.0f));
793
794 return tessCoords;
795 }
796 }
797
798 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
799 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
generateReferenceIsolineTessCoords(const int outer0,const int outer1)800 std::vector<tcu::Vec3> generateReferenceIsolineTessCoords (const int outer0, const int outer1)
801 {
802 std::vector<tcu::Vec3> tessCoords;
803
804 for (int y = 0; y < outer0; y++)
805 for (int x = 0; x < outer1+1; x++)
806 tessCoords.push_back(tcu::Vec3((float)x / (float)outer1,
807 (float)y / (float)outer0,
808 0.0f));
809
810 return tessCoords;
811 }
812
referencePointModePrimitiveCount(const TessPrimitiveType primitiveType,const SpacingMode spacingMode,const float * innerLevels,const float * outerLevels)813 static int referencePointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
814 {
815 if (isPatchDiscarded(primitiveType, outerLevels))
816 return 0;
817
818 switch (primitiveType)
819 {
820 case TESSPRIMITIVETYPE_TRIANGLES:
821 {
822 int inner;
823 int outer[3];
824 getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
825 return static_cast<int>(generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]).size());
826 }
827
828 case TESSPRIMITIVETYPE_QUADS:
829 {
830 int inner[2];
831 int outer[4];
832 getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
833 return static_cast<int>(generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]).size());
834 }
835
836 case TESSPRIMITIVETYPE_ISOLINES:
837 {
838 int outer[2];
839 getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
840 return static_cast<int>(generateReferenceIsolineTessCoords(outer[0], outer[1]).size());
841 }
842
843 default:
844 DE_ASSERT(false);
845 return 0;
846 }
847 }
848
referenceTriangleNonPointModePrimitiveCount(const SpacingMode spacingMode,const int inner,const int outer0,const int outer1,const int outer2)849 static int referenceTriangleNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner, const int outer0, const int outer1, const int outer2)
850 {
851 if (inner == 1)
852 {
853 if (outer0 == 1 && outer1 == 1 && outer2 == 1)
854 return 1;
855 else
856 return referenceTriangleNonPointModePrimitiveCount(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
857 outer0, outer1, outer2);
858 }
859 else
860 {
861 int result = outer0 + outer1 + outer2;
862
863 const int numInnerTriangles = inner/2;
864 for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
865 {
866 const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
867
868 if (curInnerTriangleLevel == 1)
869 result += 4;
870 else
871 result += 2*3*curInnerTriangleLevel;
872 }
873
874 return result;
875 }
876 }
877
referenceQuadNonPointModePrimitiveCount(const SpacingMode spacingMode,const int inner0,const int inner1,const int outer0,const int outer1,const int outer2,const int outer3)878 static int referenceQuadNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner0, const int inner1, const int outer0, const int outer1, const int outer2, const int outer3)
879 {
880 if (inner0 == 1 || inner1 == 1)
881 {
882 if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
883 return 2;
884 else
885 return referenceQuadNonPointModePrimitiveCount(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
886 inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
887 outer0, outer1, outer2, outer3);
888 }
889 else
890 return 2*(inner0-2)*(inner1-2) + 2*(inner0-2) + 2*(inner1-2) + outer0+outer1+outer2+outer3;
891 }
892
referenceIsolineNonPointModePrimitiveCount(const int outer0,const int outer1)893 static inline int referenceIsolineNonPointModePrimitiveCount (const int outer0, const int outer1)
894 {
895 return outer0*outer1;
896 }
897
referenceNonPointModePrimitiveCount(const TessPrimitiveType primitiveType,const SpacingMode spacingMode,const float * innerLevels,const float * outerLevels)898 static int referenceNonPointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
899 {
900 if (isPatchDiscarded(primitiveType, outerLevels))
901 return 0;
902
903 switch (primitiveType)
904 {
905 case TESSPRIMITIVETYPE_TRIANGLES:
906 {
907 int inner;
908 int outer[3];
909 getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
910 return referenceTriangleNonPointModePrimitiveCount(spacingMode, inner, outer[0], outer[1], outer[2]);
911 }
912
913 case TESSPRIMITIVETYPE_QUADS:
914 {
915 int inner[2];
916 int outer[4];
917 getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
918 return referenceQuadNonPointModePrimitiveCount(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]);
919 }
920
921 case TESSPRIMITIVETYPE_ISOLINES:
922 {
923 int outer[2];
924 getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
925 return referenceIsolineNonPointModePrimitiveCount(outer[0], outer[1]);
926 }
927
928 default:
929 DE_ASSERT(false);
930 return 0;
931 }
932 }
933
numVerticesPerPrimitive(const TessPrimitiveType primitiveType,const bool usePointMode)934 int numVerticesPerPrimitive (const TessPrimitiveType primitiveType, const bool usePointMode)
935 {
936 if (usePointMode)
937 return 1;
938
939 switch (primitiveType)
940 {
941 case TESSPRIMITIVETYPE_TRIANGLES: return 3;
942 case TESSPRIMITIVETYPE_QUADS: return 3; // quads are composed of two triangles
943 case TESSPRIMITIVETYPE_ISOLINES: return 2;
944 default:
945 DE_ASSERT(false);
946 return 0;
947 }
948 }
949
referencePrimitiveCount(const TessPrimitiveType primitiveType,const SpacingMode spacingMode,const bool usePointMode,const float * innerLevels,const float * outerLevels)950 int referencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
951 {
952 return usePointMode ? referencePointModePrimitiveCount (primitiveType, spacingMode, innerLevels, outerLevels)
953 : referenceNonPointModePrimitiveCount (primitiveType, spacingMode, innerLevels, outerLevels);
954 }
955
956 //! In point mode this should return the number of unique vertices, while in non-point mode the maximum theoretical number of verticies.
957 //! Actual implementation will likely return a much smaller number because the shader isn't required to be run for duplicate coordinates.
referenceVertexCount(const TessPrimitiveType primitiveType,const SpacingMode spacingMode,const bool usePointMode,const float * innerLevels,const float * outerLevels)958 int referenceVertexCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
959 {
960 return referencePrimitiveCount(primitiveType, spacingMode, usePointMode, innerLevels, outerLevels)
961 * numVerticesPerPrimitive(primitiveType, usePointMode);
962 }
963
requireFeatures(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const FeatureFlags flags)964 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
965 {
966 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
967
968 if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
969 throw tcu::NotSupportedError("Tessellation shader not supported");
970
971 if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
972 throw tcu::NotSupportedError("Geometry shader not supported");
973
974 if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
975 throw tcu::NotSupportedError("Double-precision floats not supported");
976
977 if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
978 throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
979
980 if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
981 throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
982
983 if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
984 throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
985 }
986
987 } // tessellation
988 } // vkt
989