1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 ARM Limited.
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 PushConstant Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelinePushConstantTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vktTestCase.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "tcuImageCompare.hpp"
40 #include "deMemory.h"
41 #include "deRandom.hpp"
42 #include "deStringUtil.hpp"
43 #include "deUniquePtr.hpp"
44
45 #include <algorithm>
46 #include <sstream>
47 #include <vector>
48
49 namespace vkt
50 {
51 namespace pipeline
52 {
53
54 using namespace vk;
55
56 namespace
57 {
58
59 enum
60 {
61 TRIANGLE_COUNT = 2,
62 MAX_RANGE_COUNT = 5
63 };
64
65 enum RangeSizeCase
66 {
67 SIZE_CASE_4 = 0,
68 SIZE_CASE_16,
69 SIZE_CASE_32,
70 SIZE_CASE_48,
71 SIZE_CASE_128,
72 SIZE_CASE_UNSUPPORTED
73 };
74
75 struct PushConstantData
76 {
77 struct PushConstantRange
78 {
79 VkShaderStageFlags shaderStage;
80 deUint32 offset;
81 deUint32 size;
82 } range;
83 struct PushConstantUpdate
84 {
85 deUint32 offset;
86 deUint32 size;
87 } update;
88 };
89
90 class PushConstantGraphicsTest : public vkt::TestCase
91 {
92 public:
93 PushConstantGraphicsTest (tcu::TestContext& testContext,
94 const std::string& name,
95 const std::string& description,
96 const deUint32 rangeCount,
97 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
98 const deBool multipleUpdate);
99 virtual ~PushConstantGraphicsTest (void);
100 virtual void initPrograms (SourceCollections& sourceCollections) const;
101 virtual TestInstance* createInstance (Context& context) const;
102 RangeSizeCase getRangeSizeCase (deUint32 rangeSize) const;
103
104 private:
105 const deUint32 m_rangeCount;
106 PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
107 const deBool m_multipleUpdate;
108 };
109
110 class PushConstantGraphicsTestInstance : public vkt::TestInstance
111 {
112 public:
113 PushConstantGraphicsTestInstance (Context& context,
114 const deUint32 rangeCount,
115 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
116 const deBool multipleUpdate);
117 virtual ~PushConstantGraphicsTestInstance (void);
118 virtual tcu::TestStatus iterate (void);
119
120 void createShaderStage (const DeviceInterface& vk,
121 VkDevice device,
122 const BinaryCollection& programCollection,
123 const char* name,
124 VkShaderStageFlagBits stage,
125 Move<VkShaderModule>* module);
126 std::vector<Vertex4RGBA> createQuad (const float size);
127
128 private:
129 tcu::TestStatus verifyImage (void);
130
131 private:
132 const tcu::UVec2 m_renderSize;
133 const VkFormat m_colorFormat;
134 const deUint32 m_rangeCount;
135 PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
136 const deBool m_multipleUpdate;
137
138 VkImageCreateInfo m_colorImageCreateInfo;
139 Move<VkImage> m_colorImage;
140 de::MovePtr<Allocation> m_colorImageAlloc;
141 Move<VkImageView> m_colorAttachmentView;
142 Move<VkRenderPass> m_renderPass;
143 Move<VkFramebuffer> m_framebuffer;
144
145 Move<VkShaderModule> m_vertexShaderModule;
146 Move<VkShaderModule> m_fragmentShaderModule;
147 Move<VkShaderModule> m_geometryShaderModule;
148 Move<VkShaderModule> m_tessControlShaderModule;
149 Move<VkShaderModule> m_tessEvaluationShaderModule;
150
151 VkShaderStageFlags m_shaderFlags;
152 std::vector<VkPipelineShaderStageCreateInfo> m_shaderStage;
153
154 Move<VkBuffer> m_vertexBuffer;
155 std::vector<Vertex4RGBA> m_vertices;
156 de::MovePtr<Allocation> m_vertexBufferAlloc;
157
158 Move<VkBuffer> m_uniformBuffer;
159 de::MovePtr<Allocation> m_uniformBufferAlloc;
160 Move<VkDescriptorPool> m_descriptorPool;
161 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
162 Move<VkDescriptorSet> m_descriptorSet;
163
164 Move<VkPipelineLayout> m_pipelineLayout;
165 Move<VkPipeline> m_graphicsPipelines;
166
167 Move<VkCommandPool> m_cmdPool;
168 Move<VkCommandBuffer> m_cmdBuffer;
169
170 Move<VkFence> m_fence;
171 };
172
PushConstantGraphicsTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const deBool multipleUpdate)173 PushConstantGraphicsTest::PushConstantGraphicsTest (tcu::TestContext& testContext,
174 const std::string& name,
175 const std::string& description,
176 const deUint32 rangeCount,
177 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
178 const deBool multipleUpdate)
179 : vkt::TestCase (testContext, name, description)
180 , m_rangeCount (rangeCount)
181 , m_multipleUpdate (multipleUpdate)
182 {
183 deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
184 }
185
~PushConstantGraphicsTest(void)186 PushConstantGraphicsTest::~PushConstantGraphicsTest (void)
187 {
188 }
189
createInstance(Context & context) const190 TestInstance* PushConstantGraphicsTest::createInstance (Context& context) const
191 {
192 return new PushConstantGraphicsTestInstance(context, m_rangeCount, m_pushConstantRange, m_multipleUpdate);
193 }
194
getRangeSizeCase(deUint32 rangeSize) const195 RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase (deUint32 rangeSize) const
196 {
197 switch (rangeSize)
198 {
199 case 4:
200 return SIZE_CASE_4;
201 case 16:
202 return SIZE_CASE_16;
203 case 32:
204 return SIZE_CASE_32;
205 case 48:
206 return SIZE_CASE_48;
207 case 128:
208 return SIZE_CASE_128;
209 default:
210 DE_FATAL("Range size unsupported yet");
211 return SIZE_CASE_UNSUPPORTED;
212 }
213 }
214
initPrograms(SourceCollections & sourceCollections) const215 void PushConstantGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
216 {
217 std::ostringstream vertexSrc;
218 std::ostringstream fragmentSrc;
219 std::ostringstream geometrySrc;
220 std::ostringstream tessControlSrc;
221 std::ostringstream tessEvaluationSrc;
222
223 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
224 {
225 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
226 {
227 vertexSrc << "#version 450\n"
228 << "layout(location = 0) in highp vec4 position;\n"
229 << "layout(location = 1) in highp vec4 color;\n"
230 << "layout(location = 0) out highp vec4 vtxColor;\n"
231 << "layout(push_constant) uniform Material {\n";
232
233 switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
234 {
235 case SIZE_CASE_4:
236 vertexSrc << "int kind;\n"
237 << "} matInst;\n";
238 break;
239 case SIZE_CASE_16:
240 vertexSrc << "vec4 color;\n"
241 << "} matInst;\n"
242 << "layout(std140, binding = 0) uniform UniformBuf {\n"
243 << "vec4 element;\n"
244 << "} uniformBuf;\n";
245 break;
246 case SIZE_CASE_32:
247 vertexSrc << "vec4 color[2];\n"
248 << "} matInst;\n";
249 break;
250 case SIZE_CASE_48:
251 vertexSrc << "int dummy1;\n"
252 << "vec4 dummy2;\n"
253 << "vec4 color;\n"
254 << "} matInst;\n";
255 break;
256 case SIZE_CASE_128:
257 vertexSrc << "vec4 color[8];\n"
258 << "} matInst;\n";
259 break;
260 default:
261 DE_FATAL("Not implemented yet");
262 break;
263 }
264
265 vertexSrc << "void main()\n"
266 << "{\n"
267 << " gl_Position = position;\n";
268
269 switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
270 {
271 case SIZE_CASE_4:
272 vertexSrc << "switch (matInst.kind) {\n"
273 << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
274 << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
275 << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
276 << "default: vtxColor = color; break;}\n"
277 << "}\n";
278 break;
279 case SIZE_CASE_16:
280 vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
281 << "}\n";
282 break;
283 case SIZE_CASE_32:
284 vertexSrc << "vtxColor = (matInst.color[0] + matInst.color[1]) * 0.5;\n"
285 << "}\n";
286 break;
287 case SIZE_CASE_48:
288 vertexSrc << "vtxColor = matInst.color;\n"
289 << "}\n";
290 break;
291 case SIZE_CASE_128:
292 vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
293 << "for (int i = 0; i < 8; i++)\n"
294 << "{\n"
295 << " color = color + matInst.color[i];\n"
296 << "}\n"
297 << "vtxColor = color * 0.125;\n"
298 << "}\n";
299 break;
300 default:
301 DE_FATAL("Not implemented yet");
302 break;
303 }
304
305 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
306 }
307
308 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
309 {
310 tessControlSrc << "#version 450\n"
311 << "layout (vertices = 3) out;\n"
312 << "layout(push_constant) uniform TessLevel {\n"
313 << " layout(offset = 24) int level;\n"
314 << "} tessLevel;\n"
315 << "layout(location = 0) in highp vec4 color[];\n"
316 << "layout(location = 0) out highp vec4 vtxColor[];\n"
317 << "void main()\n"
318 << "{\n"
319 << " gl_TessLevelInner[0] = tessLevel.level;\n"
320 << " gl_TessLevelOuter[0] = tessLevel.level;\n"
321 << " gl_TessLevelOuter[1] = tessLevel.level;\n"
322 << " gl_TessLevelOuter[2] = tessLevel.level;\n"
323 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
324 << " vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
325 << "}\n";
326
327 sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
328 }
329
330 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
331 {
332 tessEvaluationSrc << "#version 450\n"
333 << "layout (triangles) in;\n"
334 << "layout(push_constant) uniform Material {\n"
335 << " layout(offset = 32) vec4 color;\n"
336 << "} matInst;\n"
337 << "layout(location = 0) in highp vec4 color[];\n"
338 << "layout(location = 0) out highp vec4 vtxColor;\n"
339 << "void main()\n"
340 << "{\n"
341 << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
342 << " vtxColor = matInst.color;\n"
343 << "}\n";
344
345 sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
346 }
347
348 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
349 {
350 geometrySrc << "#version 450\n"
351 << "layout(triangles) in;\n"
352 << "layout(triangle_strip, max_vertices=3) out;\n"
353 << "layout(push_constant) uniform Material {\n"
354 << " layout(offset = 20) int kind;\n"
355 << "} matInst;\n"
356 << "layout(location = 0) in highp vec4 color[];\n"
357 << "layout(location = 0) out highp vec4 vtxColor;\n"
358 << "void main()\n"
359 << "{\n"
360 << " for(int i=0; i<3; i++)\n"
361 << " {\n"
362 << " gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n"
363 << " gl_Position.w = gl_in[i].gl_Position.w;\n"
364 << " vtxColor = color[i];\n"
365 << " EmitVertex();\n"
366 << " }\n"
367 << " EndPrimitive();\n"
368 << "}\n";
369
370 sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
371 }
372
373 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
374 {
375 fragmentSrc << "#version 450\n"
376 << "layout(location = 0) in highp vec4 vtxColor;\n"
377 << "layout(location = 0) out highp vec4 fragColor;\n"
378 << "layout(push_constant) uniform Material {\n";
379
380 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
381 {
382 fragmentSrc << " layout(offset = 0) int kind;\n"
383 << "} matInst;\n";
384 }
385 else
386 {
387 fragmentSrc << " layout(offset = 16) int kind;\n"
388 << "} matInst;\n";
389 }
390
391 fragmentSrc << "void main (void)\n"
392 << "{\n"
393 << " switch (matInst.kind) {\n"
394 << " case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
395 << " case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
396 << " case 2: fragColor = vtxColor; break;\n"
397 << " default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
398 << "}\n";
399
400 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
401 }
402 }
403
404 // add a pass through fragment shader if it's not activated in push constant ranges
405 if (fragmentSrc.str().empty())
406 {
407 fragmentSrc << "#version 450\n"
408 << "layout(location = 0) in highp vec4 vtxColor;\n"
409 << "layout(location = 0) out highp vec4 fragColor;\n"
410 << "void main (void)\n"
411 << "{\n"
412 << " fragColor = vtxColor;\n"
413 << "}\n";
414
415 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
416 }
417 }
418
createShaderStage(const DeviceInterface & vk,VkDevice device,const BinaryCollection & programCollection,const char * name,VkShaderStageFlagBits stage,Move<VkShaderModule> * module)419 void PushConstantGraphicsTestInstance::createShaderStage (const DeviceInterface& vk,
420 VkDevice device,
421 const BinaryCollection& programCollection,
422 const char* name,
423 VkShaderStageFlagBits stage,
424 Move<VkShaderModule>* module)
425 {
426 *module = createShaderModule(vk, device, programCollection.get(name), 0);
427
428 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
429 {
430 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
431 DE_NULL, // const void* pNext;
432 0u, // VkPipelineShaderStageCreateFlags flags;
433 stage, // VkShaderStageFlagBits stage;
434 **module, // VkShaderModule module;
435 "main", // const char* pName;
436 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
437 };
438
439 m_shaderStage.push_back(stageCreateInfo);
440 }
441
createQuad(const float size)442 std::vector<Vertex4RGBA> PushConstantGraphicsTestInstance::createQuad(const float size)
443 {
444 std::vector<Vertex4RGBA> vertices;
445
446 const tcu::Vec4 color = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
447 const Vertex4RGBA lowerLeftVertex = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
448 const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
449 const Vertex4RGBA UpperLeftVertex = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
450 const Vertex4RGBA UpperRightVertex = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
451
452 vertices.push_back(lowerLeftVertex);
453 vertices.push_back(lowerRightVertex);
454 vertices.push_back(UpperLeftVertex);
455 vertices.push_back(UpperLeftVertex);
456 vertices.push_back(lowerRightVertex);
457 vertices.push_back(UpperRightVertex);
458
459 return vertices;
460 }
461
PushConstantGraphicsTestInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate)462 PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance (Context& context,
463 const deUint32 rangeCount,
464 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
465 deBool multipleUpdate)
466 : vkt::TestInstance (context)
467 , m_renderSize (32, 32)
468 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
469 , m_rangeCount (rangeCount)
470 , m_multipleUpdate (multipleUpdate)
471 , m_shaderFlags (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
472 {
473 const DeviceInterface& vk = context.getDeviceInterface();
474 const VkDevice vkDevice = context.getDevice();
475 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
476 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
477 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
478
479 deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
480
481 // Create color image
482 {
483 const VkImageCreateInfo colorImageParams =
484 {
485 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
486 DE_NULL, // const void* pNext;
487 0u, // VkImageCreateFlags flags;
488 VK_IMAGE_TYPE_2D, // VkImageType imageType;
489 m_colorFormat, // VkFormat format;
490 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
491 1u, // deUint32 mipLevels;
492 1u, // deUint32 arrayLayers;
493 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
494 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
495 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
496 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
497 1u, // deUint32 queueFamilyIndexCount;
498 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
499 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
500 };
501
502 m_colorImageCreateInfo = colorImageParams;
503 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
504
505 // Allocate and bind color image memory
506 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
507 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
508 }
509
510 // Create color attachment view
511 {
512 const VkImageViewCreateInfo colorAttachmentViewParams =
513 {
514 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
515 DE_NULL, // const void* pNext;
516 0u, // VkImageViewCreateFlags flags;
517 *m_colorImage, // VkImage image;
518 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
519 m_colorFormat, // VkFormat format;
520 componentMappingRGBA, // VkChannelMapping channels;
521 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
522 };
523
524 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
525 }
526
527 // Create render pass
528 {
529 const VkAttachmentDescription colorAttachmentDescription =
530 {
531 0u, // VkAttachmentDescriptionFlags flags;
532 m_colorFormat, // VkFormat format;
533 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
534 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
535 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
536 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
537 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
538 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
539 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
540 };
541
542 const VkAttachmentDescription attachments[1] =
543 {
544 colorAttachmentDescription
545 };
546
547 const VkAttachmentReference colorAttachmentReference =
548 {
549 0u, // deUint32 attachment;
550 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
551 };
552
553 const VkAttachmentReference depthAttachmentReference =
554 {
555 VK_ATTACHMENT_UNUSED, // deUint32 attachment;
556 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout;
557 };
558
559 const VkSubpassDescription subpassDescription =
560 {
561 0u, // VkSubpassDescriptionFlags flags;
562 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
563 0u, // deUint32 inputAttachmentCount;
564 DE_NULL, // const VkAttachmentReference* pInputAttachments;
565 1u, // deUint32 colorAttachmentCount;
566 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
567 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
568 &depthAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
569 0u, // deUint32 preserveAttachmentCount;
570 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
571 };
572
573 const VkRenderPassCreateInfo renderPassParams =
574 {
575 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
576 DE_NULL, // const void* pNext;
577 0u, // VkRenderPassCreateFlags flags;
578 1u, // deUint32 attachmentCount;
579 attachments, // const VkAttachmentDescription* pAttachments;
580 1u, // deUint32 subpassCount;
581 &subpassDescription, // const VkSubpassDescription* pSubpasses;
582 0u, // deUint32 dependencyCount;
583 DE_NULL // const VkSubpassDependency* pDependencies;
584 };
585
586 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
587 }
588
589 // Create framebuffer
590 {
591 const VkImageView attachmentBindInfos[1] =
592 {
593 *m_colorAttachmentView
594 };
595
596 const VkFramebufferCreateInfo framebufferParams =
597 {
598 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
599 DE_NULL, // const void* pNext;
600 0u, // VkFramebufferCreateFlags flags;
601 *m_renderPass, // VkRenderPass renderPass;
602 1u, // deUint32 attachmentCount;
603 attachmentBindInfos, // const VkImageView* pAttachments;
604 (deUint32)m_renderSize.x(), // deUint32 width;
605 (deUint32)m_renderSize.y(), // deUint32 height;
606 1u // deUint32 layers;
607 };
608
609 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
610 }
611
612 // Create pipeline layout
613 {
614 // create push constant range
615 VkPushConstantRange pushConstantRanges[MAX_RANGE_COUNT];
616 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
617 {
618 pushConstantRanges[rangeNdx].stageFlags = m_pushConstantRange[rangeNdx].range.shaderStage;
619 pushConstantRanges[rangeNdx].offset = m_pushConstantRange[rangeNdx].range.offset;
620 pushConstantRanges[rangeNdx].size = m_pushConstantRange[rangeNdx].range.size;
621 }
622
623 // create descriptor set layout
624 m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT).build(vk, vkDevice);
625
626 // create descriptor pool
627 m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
628
629 // create uniform buffer
630 const VkBufferCreateInfo uniformBufferCreateInfo =
631 {
632 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
633 DE_NULL, // const void* pNext;
634 0u, // VkBufferCreateFlags flags
635 16u, // VkDeviceSize size;
636 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, // VkBufferUsageFlags usage;
637 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
638 1u, // deUint32 queueFamilyCount;
639 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
640 };
641
642 m_uniformBuffer = createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
643 m_uniformBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
644 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset()));
645
646 tcu::Vec4 value = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
647 deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
648 flushMappedMemoryRange(vk, vkDevice, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset(), 16u);
649
650 // create and update descriptor set
651 const VkDescriptorSetAllocateInfo allocInfo =
652 {
653 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
654 DE_NULL, // const void* pNext;
655 *m_descriptorPool, // VkDescriptorPool descriptorPool;
656 1u, // uint32_t setLayoutCount;
657 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
658 };
659 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
660
661 const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
662
663 DescriptorSetUpdateBuilder()
664 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
665 .update(vk, vkDevice);
666
667 // create pipeline layout
668 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
669 {
670 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
671 DE_NULL, // const void* pNext;
672 0u, // VkPipelineLayoutCreateFlags flags;
673 1u, // deUint32 descriptorSetCount;
674 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
675 m_rangeCount, // deUint32 pushConstantRangeCount;
676 pushConstantRanges // const VkPushConstantRange* pPushConstantRanges;
677 };
678
679 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
680 }
681
682 // Create shaders
683 {
684 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
685 {
686 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
687 {
688 m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
689 }
690 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
691 {
692 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
693 }
694 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
695 {
696 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
697 }
698 }
699
700 VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
701
702 createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", VK_SHADER_STAGE_VERTEX_BIT , &m_vertexShaderModule);
703 if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
704 {
705 if (features.tessellationShader == VK_FALSE)
706 {
707 TCU_THROW(NotSupportedError, "Tessellation Not Supported");
708 }
709 createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &m_tessControlShaderModule);
710 createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tese", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvaluationShaderModule);
711 }
712 if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
713 {
714 if (features.geometryShader == VK_FALSE)
715 {
716 TCU_THROW(NotSupportedError, "Geometry Not Supported");
717 }
718 createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", VK_SHADER_STAGE_GEOMETRY_BIT, &m_geometryShaderModule);
719 }
720 createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", VK_SHADER_STAGE_FRAGMENT_BIT, &m_fragmentShaderModule);
721 }
722
723 // Create pipeline
724 {
725 const VkVertexInputBindingDescription vertexInputBindingDescription =
726 {
727 0u, // deUint32 binding;
728 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
729 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
730 };
731
732 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
733 {
734 {
735 0u, // deUint32 location;
736 0u, // deUint32 binding;
737 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
738 0u // deUint32 offsetInBytes;
739 },
740 {
741 1u, // deUint32 location;
742 0u, // deUint32 binding;
743 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
744 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset;
745 }
746 };
747
748 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
749 {
750 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
751 DE_NULL, // const void* pNext;
752 0u, // vkPipelineVertexInputStateCreateFlags flags;
753 1u, // deUint32 bindingCount;
754 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
755 2u, // deUint32 attributeCount;
756 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
757 };
758
759 const VkPrimitiveTopology topology = (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
760 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
761 {
762 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
763 DE_NULL, // const void* pNext;
764 (VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags flags;
765 topology, // VkPrimitiveTopology topology;
766 false // VkBool32 primitiveRestartEnable;
767 };
768
769 const VkViewport viewport =
770 {
771 0.0f, // float originX;
772 0.0f, // float originY;
773 (float)m_renderSize.x(), // float width;
774 (float)m_renderSize.y(), // float height;
775 0.0f, // float minDepth;
776 1.0f // float maxDepth;
777 };
778
779 const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
780
781 const VkPipelineViewportStateCreateInfo viewportStateParams =
782 {
783 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
784 DE_NULL, // const void* pNext;
785 (VkPipelineViewportStateCreateFlags)0u, // VkPipelineViewportStateCreateFlags flags;
786 1u, // deUint32 viewportCount;
787 &viewport, // const VkViewport* pViewports;
788 1u, // deUint32 scissorCount;
789 &scissor, // const VkRect2D* pScissors;
790 };
791
792 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
793 {
794 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
795 DE_NULL, // const void* pNext;
796 0u, // VkPipelineRasterizationStateCreateFlags flags;
797 false, // VkBool32 depthClampEnable;
798 false, // VkBool32 rasterizerDiscardEnable;
799 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
800 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
801 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
802 VK_FALSE, // VkBool32 depthBiasEnable;
803 0.0f, // float depthBiasConstantFactor;
804 0.0f, // float depthBiasClamp;
805 0.0f, // float depthBiasSlopeFactor;
806 1.0f, // float lineWidth;
807 };
808
809 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
810 {
811 false, // VkBool32 blendEnable;
812 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
813 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
814 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
815 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
816 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
817 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
818 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
819 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
820 };
821
822 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
823 {
824 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
825 DE_NULL, // const void* pNext;
826 0, // VkPipelineColorBlendStateCreateFlags flags;
827 false, // VkBool32 logicOpEnable;
828 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
829 1u, // deUint32 attachmentCount;
830 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
831 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
832 };
833
834 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
835 {
836 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
837 DE_NULL, // const void* pNext;
838 0u, // VkPipelineMultisampleStateCreateFlags flags;
839 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
840 false, // VkBool32 sampleShadingEnable;
841 0.0f, // float minSampleShading;
842 DE_NULL, // const VkSampleMask* pSampleMask;
843 false, // VkBool32 alphaToCoverageEnable;
844 false // VkBool32 alphaToOneEnable;
845 };
846
847 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
848 {
849 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
850 DE_NULL, // const void* pNext;
851 0u, // VkPipelineDepthStencilStateCreateFlags flags;
852 false, // VkBool32 depthTestEnable;
853 false, // VkBool32 depthWriteEnable;
854 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
855 false, // VkBool32 depthBoundsTestEnable;
856 false, // VkBool32 stencilTestEnable;
857 // VkStencilOpState front;
858 {
859 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
860 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
861 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
862 VK_COMPARE_OP_NEVER, // VkCompareOp stencilCompareOp;
863 0u, // deUint32 stencilCompareMask;
864 0u, // deUint32 stencilWriteMask;
865 0u, // deUint32 stencilReference;
866 },
867 // VkStencilOpState back;
868 {
869 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
870 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
871 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
872 VK_COMPARE_OP_NEVER, // VkCompareOp stencilCompareOp;
873 0u, // deUint32 stencilCompareMask;
874 0u, // deUint32 stencilWriteMask;
875 0u, // deUint32 stencilReference;
876 },
877 0.0f, // float minDepthBounds;
878 1.0f, // float maxDepthBounds;
879 };
880
881 const VkPipelineTessellationStateCreateInfo tessellationStateParams =
882 {
883 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
884 DE_NULL, // const void* pNext;
885 0u, // VkPipelineTessellationStateCreateFlags flags;
886 3u, // uint32_t patchControlPoints;
887 };
888
889 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
890 {
891 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
892 DE_NULL, // const void* pNext;
893 0u, // VkPipelineCreateFlags flags;
894 (deUint32)m_shaderStage.size(), // deUint32 stageCount;
895 &m_shaderStage[0], // const VkPipelineShaderStageCreateInfo* pStages;
896 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
897 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
898 (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &tessellationStateParams: DE_NULL), // const VkPipelineTessellationStateCreateInfo* pTessellationState;
899 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
900 &rasterStateParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
901 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
902 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
903 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
904 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
905 *m_pipelineLayout, // VkPipelineLayout layout;
906 *m_renderPass, // VkRenderPass renderPass;
907 0u, // deUint32 subpass;
908 0u, // VkPipeline basePipelineHandle;
909 0u // deInt32 basePipelineIndex;
910 };
911
912 m_graphicsPipelines = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
913 }
914
915 // Create vertex buffer
916 {
917 m_vertices = createQuad(1.0f);
918
919 const VkBufferCreateInfo vertexBufferParams =
920 {
921 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
922 DE_NULL, // const void* pNext;
923 0u, // VkBufferCreateFlags flags;
924 (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
925 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
926 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
927 1u, // deUint32 queueFamilyCount;
928 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
929 };
930
931 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
932 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
933
934 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
935
936 // Load vertices into vertex buffer
937 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
938 flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
939 }
940
941 // Create command pool
942 {
943 const VkCommandPoolCreateInfo cmdPoolParams =
944 {
945 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
946 DE_NULL, // const void* pNext;
947 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
948 queueFamilyIndex // deUint32 queueFamilyIndex;
949 };
950 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
951 }
952
953 // Create command buffer
954 {
955 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
956 {
957 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
958 DE_NULL, // const void* pNext;
959 *m_cmdPool, // VkCommandPool commandPool;
960 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
961 1u // deUint32 bufferCount;
962 };
963
964 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
965 {
966 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
967 DE_NULL, // const void* pNext;
968 0u, // VkCommandBufferUsageFlags flags;
969 (const VkCommandBufferInheritanceInfo*)DE_NULL,
970 };
971
972 const VkClearValue attachmentClearValues[] =
973 {
974 defaultClearValue(m_colorFormat)
975 };
976
977 const VkRenderPassBeginInfo renderPassBeginInfo =
978 {
979 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
980 DE_NULL, // const void* pNext;
981 *m_renderPass, // VkRenderPass renderPass;
982 *m_framebuffer, // VkFramebuffer framebuffer;
983 { { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
984 1, // deUint32 clearValueCount;
985 attachmentClearValues // const VkClearValue* pClearValues;
986 };
987
988 const VkImageMemoryBarrier attachmentLayoutBarrier =
989 {
990 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
991 DE_NULL, // const void* pNext;
992 0u, // VkAccessFlags srcAccessMask;
993 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
994 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
995 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
996 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
997 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
998 *m_colorImage, // VkImage image;
999 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1000 };
1001
1002 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1003
1004 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1005
1006 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
1007 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1008
1009 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1010
1011 // update push constant
1012 std::vector<tcu::Vec4> color(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1013 std::vector<tcu::Vec4> allOnes(8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1014
1015 const deUint32 kind = 2u;
1016 const void* value = DE_NULL;
1017 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1018 {
1019 value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void*)(&kind) : (void*)(&color[0]);
1020
1021 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value);
1022
1023 if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
1024 {
1025 value = (void*)(&allOnes[0]);
1026 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value);
1027 }
1028 }
1029
1030 // draw quad
1031 const VkDeviceSize triangleOffset = (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
1032 for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
1033 {
1034 VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
1035
1036 if (m_multipleUpdate)
1037 {
1038 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset, m_pushConstantRange[0].range.size, &triangleNdx);
1039 }
1040
1041 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
1042 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1043 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1044
1045 vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
1046 }
1047
1048 vk.cmdEndRenderPass(*m_cmdBuffer);
1049 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1050 }
1051
1052 // Create fence
1053 {
1054 const VkFenceCreateInfo fenceParams =
1055 {
1056 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
1057 DE_NULL, // const void* pNext;
1058 0u // VkFenceCreateFlags flags;
1059 };
1060
1061 m_fence = createFence(vk, vkDevice, &fenceParams);
1062 }
1063 }
1064
~PushConstantGraphicsTestInstance(void)1065 PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance (void)
1066 {
1067 }
1068
iterate(void)1069 tcu::TestStatus PushConstantGraphicsTestInstance::iterate (void)
1070 {
1071 const DeviceInterface& vk = m_context.getDeviceInterface();
1072 const VkDevice vkDevice = m_context.getDevice();
1073 const VkQueue queue = m_context.getUniversalQueue();
1074 const VkSubmitInfo submitInfo =
1075 {
1076 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1077 DE_NULL, // const void* pNext;
1078 0u, // deUint32 waitSemaphoreCount;
1079 DE_NULL, // const VkSemaphore* pWaitSemaphores;
1080 (const VkPipelineStageFlags*)DE_NULL,
1081 1u, // deUint32 commandBufferCount;
1082 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
1083 0u, // deUint32 signalSemaphoreCount;
1084 DE_NULL // const VkSemaphore* pSignalSemaphores;
1085 };
1086
1087 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1088 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1089 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1090
1091 return verifyImage();
1092 }
1093
verifyImage(void)1094 tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage (void)
1095 {
1096 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
1097 const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
1098 const ColorVertexShader vertexShader;
1099 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat);
1100 const rr::Program program (&vertexShader, &fragmentShader);
1101 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1102 bool compareOk = false;
1103
1104 // Render reference image
1105 {
1106 if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
1107 {
1108 m_vertices = createQuad(0.5f);
1109 }
1110
1111 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1112 {
1113 if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
1114 {
1115 for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
1116 {
1117 m_vertices[vertexNdx].color.xyzw() = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1118 }
1119 }
1120 }
1121
1122 if (m_multipleUpdate)
1123 {
1124 for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
1125 {
1126 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
1127 }
1128 for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
1129 {
1130 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
1131 }
1132 }
1133
1134 for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
1135 {
1136 rr::RenderState renderState(refRenderer.getViewportState());
1137
1138 refRenderer.draw(renderState,
1139 rr::PRIMITIVETYPE_TRIANGLES,
1140 std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
1141 m_vertices.begin() + (triangleNdx + 1) * 3));
1142 }
1143 }
1144
1145 // Compare result with reference image
1146 {
1147 const DeviceInterface& vk = m_context.getDeviceInterface();
1148 const VkDevice vkDevice = m_context.getDevice();
1149 const VkQueue queue = m_context.getUniversalQueue();
1150 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1151 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1152 de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1153
1154 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1155 "IntImageCompare",
1156 "Image comparison",
1157 refRenderer.getAccess(),
1158 result->getAccess(),
1159 tcu::UVec4(2, 2, 2, 2),
1160 tcu::IVec3(1, 1, 0),
1161 true,
1162 tcu::COMPARE_LOG_RESULT);
1163 }
1164
1165 if (compareOk)
1166 return tcu::TestStatus::pass("Result image matches reference");
1167 else
1168 return tcu::TestStatus::fail("Image mismatch");
1169 }
1170
1171 class PushConstantComputeTest : public vkt::TestCase
1172 {
1173 public:
1174 PushConstantComputeTest (tcu::TestContext& testContext,
1175 const std::string& name,
1176 const std::string& description,
1177 const PushConstantData pushConstantRange);
1178 virtual ~PushConstantComputeTest (void);
1179 virtual void initPrograms (SourceCollections& sourceCollections) const;
1180 virtual TestInstance* createInstance (Context& context) const;
1181
1182 private:
1183 const PushConstantData m_pushConstantRange;
1184 };
1185
1186 class PushConstantComputeTestInstance : public vkt::TestInstance
1187 {
1188 public:
1189 PushConstantComputeTestInstance (Context& context,
1190 const PushConstantData pushConstantRange);
1191 virtual ~PushConstantComputeTestInstance (void);
1192 virtual tcu::TestStatus iterate (void);
1193
1194 private:
1195 const PushConstantData m_pushConstantRange;
1196
1197 Move<VkBuffer> m_outBuffer;
1198 de::MovePtr<Allocation> m_outBufferAlloc;
1199 Move<VkDescriptorPool> m_descriptorPool;
1200 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1201 Move<VkDescriptorSet> m_descriptorSet;
1202
1203 Move<VkPipelineLayout> m_pipelineLayout;
1204 Move<VkPipeline> m_computePipelines;
1205
1206 Move<VkShaderModule> m_computeShaderModule;
1207
1208 Move<VkCommandPool> m_cmdPool;
1209 Move<VkCommandBuffer> m_cmdBuffer;
1210
1211 Move<VkFence> m_fence;
1212 };
1213
PushConstantComputeTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const PushConstantData pushConstantRange)1214 PushConstantComputeTest::PushConstantComputeTest (tcu::TestContext& testContext,
1215 const std::string& name,
1216 const std::string& description,
1217 const PushConstantData pushConstantRange)
1218 : vkt::TestCase (testContext, name, description)
1219 , m_pushConstantRange (pushConstantRange)
1220 {
1221 }
1222
~PushConstantComputeTest(void)1223 PushConstantComputeTest::~PushConstantComputeTest (void)
1224 {
1225 }
1226
createInstance(Context & context) const1227 TestInstance* PushConstantComputeTest::createInstance (Context& context) const
1228 {
1229 return new PushConstantComputeTestInstance(context, m_pushConstantRange);
1230 }
1231
initPrograms(SourceCollections & sourceCollections) const1232 void PushConstantComputeTest::initPrograms (SourceCollections& sourceCollections) const
1233 {
1234 std::ostringstream computeSrc;
1235
1236 computeSrc << "#version 450\n"
1237 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1238 << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
1239 << " vec4 elements[];\n"
1240 << "} outData;\n"
1241 << "layout(push_constant) uniform Material{\n"
1242 << " vec4 element;\n"
1243 << "} matInst;\n"
1244 << "void main (void)\n"
1245 << "{\n"
1246 << " outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
1247 << "}\n";
1248
1249 sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
1250 }
1251
PushConstantComputeTestInstance(Context & context,const PushConstantData pushConstantRange)1252 PushConstantComputeTestInstance::PushConstantComputeTestInstance (Context& context,
1253 const PushConstantData pushConstantRange)
1254 : vkt::TestInstance (context)
1255 , m_pushConstantRange (pushConstantRange)
1256 {
1257 const DeviceInterface& vk = context.getDeviceInterface();
1258 const VkDevice vkDevice = context.getDevice();
1259 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1260 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1261
1262 // Create pipeline layout
1263 {
1264 // create push constant range
1265 VkPushConstantRange pushConstantRanges;
1266 pushConstantRanges.stageFlags = m_pushConstantRange.range.shaderStage;
1267 pushConstantRanges.offset = m_pushConstantRange.range.offset;
1268 pushConstantRanges.size = m_pushConstantRange.range.size;
1269
1270 // create descriptor set layout
1271 m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
1272
1273 // create descriptor pool
1274 m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1275
1276 // create uniform buffer
1277 const VkDeviceSize bufferSize = sizeof(tcu::Vec4) * 8;
1278 const VkBufferCreateInfo bufferCreateInfo =
1279 {
1280 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1281 DE_NULL, // const void* pNext;
1282 0u, // VkBufferCreateFlags flags
1283 bufferSize, // VkDeviceSize size;
1284 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
1285 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1286 1u, // deUint32 queueFamilyCount;
1287 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1288 };
1289
1290 m_outBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1291 m_outBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
1292 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
1293
1294 // create and update descriptor set
1295 const VkDescriptorSetAllocateInfo allocInfo =
1296 {
1297 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
1298 DE_NULL, // const void* pNext;
1299 *m_descriptorPool, // VkDescriptorPool descriptorPool;
1300 1u, // uint32_t setLayoutCount;
1301 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
1302 };
1303 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1304
1305 const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
1306
1307 DescriptorSetUpdateBuilder()
1308 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1309 .update(vk, vkDevice);
1310
1311 // create pipeline layout
1312 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1313 {
1314 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1315 DE_NULL, // const void* pNext;
1316 0u, // VkPipelineLayoutCreateFlags flags;
1317 1u, // deUint32 descriptorSetCount;
1318 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
1319 1u, // deUint32 pushConstantRangeCount;
1320 &pushConstantRanges // const VkPushConstantRange* pPushConstantRanges;
1321 };
1322
1323 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1324 }
1325
1326 // create pipeline
1327 {
1328 m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
1329
1330 const VkPipelineShaderStageCreateInfo stageCreateInfo =
1331 {
1332 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1333 DE_NULL, // const void* pNext;
1334 0u, // VkPipelineShaderStageCreateFlags flags;
1335 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
1336 *m_computeShaderModule, // VkShaderModule module;
1337 "main", // const char* pName;
1338 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
1339 };
1340
1341 const VkComputePipelineCreateInfo createInfo =
1342 {
1343 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
1344 DE_NULL, // const void* pNext;
1345 0u, // VkPipelineCreateFlags flags;
1346 stageCreateInfo, // VkPipelineShaderStageCreateInfo stage;
1347 *m_pipelineLayout, // VkPipelineLayout layout;
1348 (VkPipeline)0, // VkPipeline basePipelineHandle;
1349 0u, // int32_t basePipelineIndex;
1350 };
1351
1352 m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
1353 }
1354
1355 // Create command pool
1356 {
1357 const VkCommandPoolCreateInfo cmdPoolParams =
1358 {
1359 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
1360 DE_NULL, // const void* pNext;
1361 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
1362 queueFamilyIndex // deUint32 queueFamilyIndex;
1363 };
1364 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1365 }
1366
1367 // Create command buffer
1368 {
1369 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
1370 {
1371 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1372 DE_NULL, // const void* pNext;
1373 *m_cmdPool, // VkCommandPool commandPool;
1374 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
1375 1u // deUint32 bufferCount;
1376 };
1377
1378 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1379
1380 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1381 {
1382 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1383 DE_NULL, // const void* pNext;
1384 0u, // VkCommandBufferUsageFlags flags;
1385 (const VkCommandBufferInheritanceInfo*)DE_NULL,
1386 };
1387
1388 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1389
1390 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
1391 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1392
1393 // update push constant
1394 tcu::Vec4 value = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1395 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage, m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
1396
1397 vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
1398
1399 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1400 }
1401
1402 // Create fence
1403 {
1404 const VkFenceCreateInfo fenceParams =
1405 {
1406 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
1407 DE_NULL, // const void* pNext;
1408 0u // VkFenceCreateFlags flags;
1409 };
1410
1411 m_fence = createFence(vk, vkDevice, &fenceParams);
1412 }
1413 }
1414
~PushConstantComputeTestInstance(void)1415 PushConstantComputeTestInstance::~PushConstantComputeTestInstance (void)
1416 {
1417 }
1418
iterate(void)1419 tcu::TestStatus PushConstantComputeTestInstance::iterate (void)
1420 {
1421 const DeviceInterface& vk = m_context.getDeviceInterface();
1422 const VkDevice vkDevice = m_context.getDevice();
1423 const VkQueue queue = m_context.getUniversalQueue();
1424 const VkSubmitInfo submitInfo =
1425 {
1426 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1427 DE_NULL, // const void* pNext;
1428 0u, // deUint32 waitSemaphoreCount;
1429 DE_NULL, // const VkSemaphore* pWaitSemaphores;
1430 (const VkPipelineStageFlags*)DE_NULL,
1431 1u, // deUint32 commandBufferCount;
1432 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
1433 0u, // deUint32 signalSemaphoreCount;
1434 DE_NULL // const VkSemaphore* pSignalSemaphores;
1435 };
1436
1437 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1438 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1439 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1440
1441 // verify result
1442 std::vector<tcu::Vec4> expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1443 if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
1444 {
1445 return tcu::TestStatus::fail("Image mismatch");
1446 }
1447 return tcu::TestStatus::pass("result image matches with reference");
1448 }
1449
1450 } // anonymous
1451
createPushConstantTests(tcu::TestContext & testCtx)1452 tcu::TestCaseGroup* createPushConstantTests (tcu::TestContext& testCtx)
1453 {
1454 static const struct
1455 {
1456 const char* name;
1457 const char* description;
1458 deUint32 count;
1459 PushConstantData range[MAX_RANGE_COUNT];
1460 deBool hasMultipleUpdates;
1461 } graphicsParams[] =
1462 {
1463 // test range size from minimum valid size to maximum
1464 {
1465 "range_size_4",
1466 "test range size is 4 bytes(minimum valid size)",
1467 1u,
1468 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 } , { 0, 4 } } },
1469 false
1470 },
1471 {
1472 "range_size_16",
1473 "test range size is 16 bytes, and together with a normal uniform",
1474 1u,
1475 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } } },
1476 false
1477 },
1478 {
1479 "range_size_128",
1480 "test range size is 128 bytes(maximum valid size)",
1481 1u,
1482 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 128 }, { 0, 128 } } },
1483 false
1484 },
1485 // test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
1486 {
1487 "count_2_shader_VF",
1488 "test range count is 2, use vertex and fragment shaders",
1489 2u,
1490 {
1491 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1492 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1493 },
1494 false
1495 },
1496 {
1497 "count_3shader_VGF",
1498 "test range count is 3, use vertex, geometry and fragment shaders",
1499 3u,
1500 {
1501 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1502 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1503 { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1504 },
1505 false
1506 },
1507 {
1508 "count_5_shader_VTGF",
1509 "test range count is 5, use vertex, tessellation, geometry and fragment shaders",
1510 5u,
1511 {
1512 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1513 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1514 { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1515 { { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4 }, { 24, 4 } },
1516 { { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16 }, { 32, 16 } },
1517 },
1518 false
1519 },
1520 {
1521 "count_1_shader_VF",
1522 "test range count is 1, vertex and fragment shaders share one range",
1523 1u,
1524 { { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, { 0, 4 } } },
1525 false
1526 },
1527 // test data partial update and multiple times update
1528 {
1529 "data_update_partial_1",
1530 "test partial update of the values",
1531 1u,
1532 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 32 }, { 4, 24 } } },
1533 false
1534 },
1535 {
1536 "data_update_partial_2",
1537 "test partial update of the values",
1538 1u,
1539 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 48 }, { 32, 16 } } },
1540 false
1541 },
1542 {
1543 "data_update_multiple",
1544 "test multiple times update of the values",
1545 1u,
1546 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 }, { 0, 4 } } },
1547 true
1548 },
1549 };
1550
1551 static const struct
1552 {
1553 const char* name;
1554 const char* description;
1555 PushConstantData range;
1556 } computeParams[] =
1557 {
1558 {
1559 "simple_test",
1560 "test compute pipeline",
1561 { { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
1562 },
1563 };
1564
1565 de::MovePtr<tcu::TestCaseGroup> pushConstantTests (new tcu::TestCaseGroup(testCtx, "push_constant", "PushConstant tests"));
1566
1567 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_pipeline", "graphics pipeline"));
1568 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
1569 {
1570 graphicsTests->addChild(new PushConstantGraphicsTest(testCtx, graphicsParams[ndx].name, graphicsParams[ndx].description, graphicsParams[ndx].count, graphicsParams[ndx].range, graphicsParams[ndx].hasMultipleUpdates));
1571 }
1572 pushConstantTests->addChild(graphicsTests.release());
1573
1574 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_pipeline", "compute pipeline"));
1575 computeTests->addChild(new PushConstantComputeTest(testCtx, computeParams[0].name, computeParams[0].description, computeParams[0].range));
1576 pushConstantTests->addChild(computeTests.release());
1577
1578 return pushConstantTests.release();
1579 }
1580
1581 } // pipeline
1582 } // vkt
1583