1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 LunarG, Inc.
6 * Copyright (c) 2023 Nintendo
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 Shader Object Link Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktShaderObjectCreateTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vktShaderObjectCreateUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deRandom.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36
37 namespace vkt
38 {
39 namespace ShaderObject
40 {
41
42 namespace
43 {
44
45 enum ShaderType {
46 UNUSED,
47 LINKED,
48 UNLINKED,
49 };
50
51 struct Shaders {
52 ShaderType vertex;
53 ShaderType tesellation_control;
54 ShaderType tesellation_evaluation;
55 ShaderType geometry;
56 ShaderType fragment;
57 };
58
59 struct MeshShaders {
60 ShaderType task;
61 ShaderType mesh;
62 ShaderType fragment;
63 };
64
65 struct NextStages {
66 vk::VkShaderStageFlags vertNextStage;
67 vk::VkShaderStageFlags tescNextStage;
68 vk::VkShaderStageFlags teseNextStage;
69 vk::VkShaderStageFlags geomNextStage;
70 };
71
72 struct MeshNextStages {
73 vk::VkShaderStageFlags taskNextStage;
74 vk::VkShaderStageFlags meshNextStage;
75 };
76
77 enum BindType {
78 SEPARATE,
79 ONE_LINKED_UNLINKED,
80 ALL,
81 };
82
83 struct TestParams {
84 Shaders shaders;
85 bool randomOrder;
86 NextStages nextStages;
87 bool separateLinked;
88 BindType separateBind;
89 };
90
91 struct MeshParams {
92 MeshShaders shaders;
93 bool randomOrder;
94 MeshNextStages nextStages;
95 };
96
97 class ShaderObjectLinkInstance : public vkt::TestInstance
98 {
99 public:
ShaderObjectLinkInstance(Context& context, const TestParams& params)100 ShaderObjectLinkInstance (Context& context, const TestParams& params)
101 : vkt::TestInstance (context)
102 , m_params (params)
103 {}
~ShaderObjectLinkInstance(void)104 virtual ~ShaderObjectLinkInstance (void) {}
105
106 tcu::TestStatus iterate (void) override;
107 private:
108 vk::VkShaderStageFlags getNextStage (vk::VkShaderStageFlagBits currentStage);
109
110 TestParams m_params;
111 };
112
getNextStage(vk::VkShaderStageFlagBits currentStage)113 vk::VkShaderStageFlags ShaderObjectLinkInstance::getNextStage (vk::VkShaderStageFlagBits currentStage)
114 {
115 if (currentStage == vk::VK_SHADER_STAGE_VERTEX_BIT && m_params.shaders.vertex == LINKED)
116 {
117 if (m_params.shaders.tesellation_control != UNUSED)
118 {
119 if (m_params.shaders.tesellation_control == LINKED)
120 return vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
121 }
122 else if (m_params.shaders.geometry != UNUSED)
123 {
124 if (m_params.shaders.geometry == LINKED)
125 return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
126 }
127 else if (m_params.shaders.fragment != UNUSED)
128 {
129 if (m_params.shaders.fragment == LINKED)
130 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
131 }
132 }
133 else if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT && m_params.shaders.tesellation_control == LINKED && m_params.shaders.tesellation_evaluation == LINKED)
134 {
135 return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
136 }
137 else if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT && m_params.shaders.tesellation_evaluation == LINKED)
138 {
139 if (m_params.shaders.geometry != UNUSED)
140 {
141 if (m_params.shaders.geometry == LINKED)
142 return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
143 }
144 else if (m_params.shaders.fragment != UNUSED)
145 {
146 if (m_params.shaders.fragment == LINKED)
147 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
148 }
149 }
150 else if (currentStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT && m_params.shaders.geometry == LINKED)
151 {
152 if (m_params.shaders.fragment != UNUSED)
153 {
154 if (m_params.shaders.fragment == LINKED)
155 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
156 }
157 }
158
159 if (currentStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
160 return m_params.nextStages.vertNextStage;
161
162 if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
163 return m_params.nextStages.tescNextStage;
164
165 if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
166 return m_params.nextStages.teseNextStage;
167
168 if (currentStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
169 return m_params.nextStages.geomNextStage;
170
171 return 0;
172 }
173
iterate(void)174 tcu::TestStatus ShaderObjectLinkInstance::iterate (void)
175 {
176 const vk::VkInstance instance = m_context.getInstance();
177 const vk::InstanceDriver instanceDriver (m_context.getPlatformInterface(), instance);
178 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
179 const vk::VkDevice device = m_context.getDevice();
180 const vk::VkQueue queue = m_context.getUniversalQueue();
181 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
182 auto& alloc = m_context.getDefaultAllocator();
183 tcu::TestLog& log = m_context.getTestContext().getLog();
184 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
185 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
186 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
187 const bool taskSupported = m_context.getMeshShaderFeatures().taskShader;
188 const bool meshSupported = m_context.getMeshShaderFeatures().meshShader;
189
190 vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
191 const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
192
193 const vk::VkImageCreateInfo createInfo =
194 {
195 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
196 DE_NULL, // const void* pNext
197 0u, // VkImageCreateFlags flags
198 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType
199 colorAttachmentFormat, // VkFormat format
200 { 32, 32, 1 }, // VkExtent3D extent
201 1u, // uint32_t mipLevels
202 1u, // uint32_t arrayLayers
203 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
204 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
205 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
206 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
207 0, // uint32_t queueFamilyIndexCount
208 DE_NULL, // const uint32_t* pQueueFamilyIndices
209 vk::VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
210 };
211
212 de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
213 const auto imageView = vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
214 const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
215
216 const vk::VkDeviceSize colorOutputBufferSize = renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
217 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
218 vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
219
220 const auto& binaries = m_context.getBinaryCollection();
221 const auto& vert = binaries.get("vert");
222 const auto& tesc = binaries.get("tesc");
223 const auto& tese = binaries.get("tese");
224 const auto& geom = binaries.get("geom");
225 const auto& frag = binaries.get("frag");
226
227 vk::VkShaderEXT vertShader;
228 vk::VkShaderEXT tescShader;
229 vk::VkShaderEXT teseShader;
230 vk::VkShaderEXT geomShader;
231 vk::VkShaderEXT fragShader;
232
233 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos;
234
235 vk::VkShaderCreateInfoEXT vertShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert, tessellationSupported, geometrySupported);
236 vertShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_VERTEX_BIT);
237
238 if (m_params.shaders.vertex == LINKED)
239 {
240 vertShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
241 shaderCreateInfos.push_back(vertShaderCreateInfo);
242 }
243 else if (m_params.shaders.vertex == UNLINKED)
244 {
245 vk.createShadersEXT(device, 1, &vertShaderCreateInfo, DE_NULL, &vertShader);
246 }
247
248 vk::VkShaderCreateInfoEXT tescShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tesc, tessellationSupported, geometrySupported);
249 tescShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
250
251 if (m_params.shaders.tesellation_control == LINKED)
252 {
253 tescShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
254 shaderCreateInfos.push_back(tescShaderCreateInfo);
255 }
256 else if (m_params.shaders.tesellation_control == UNLINKED)
257 {
258 vk.createShadersEXT(device, 1, &tescShaderCreateInfo, DE_NULL, &tescShader);
259 }
260
261 vk::VkShaderCreateInfoEXT teseShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tese, tessellationSupported, geometrySupported);
262 teseShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
263
264 if (m_params.shaders.tesellation_evaluation == LINKED)
265 {
266 teseShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
267 shaderCreateInfos.push_back(teseShaderCreateInfo);
268 }
269 else if (m_params.shaders.tesellation_evaluation == UNLINKED)
270 {
271 vk.createShadersEXT(device, 1, &teseShaderCreateInfo, DE_NULL, &teseShader);
272 }
273
274 vk::VkShaderCreateInfoEXT geomShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, geom, tessellationSupported, geometrySupported);
275 geomShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
276
277 if (m_params.shaders.geometry == LINKED)
278 {
279 geomShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
280 shaderCreateInfos.push_back(geomShaderCreateInfo);
281 }
282 else if (m_params.shaders.geometry == UNLINKED)
283 {
284 vk.createShadersEXT(device, 1, &geomShaderCreateInfo, DE_NULL, &geomShader);
285 }
286
287 vk::VkShaderCreateInfoEXT fragShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag, tessellationSupported, geometrySupported);
288 fragShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
289
290 if (m_params.shaders.fragment == LINKED)
291 {
292 fragShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
293 shaderCreateInfos.push_back(fragShaderCreateInfo);
294 }
295 else if (m_params.shaders.fragment == UNLINKED)
296 {
297 vk.createShadersEXT(device, 1, &fragShaderCreateInfo, DE_NULL, &fragShader);
298 }
299
300 vk::VkPrimitiveTopology primitiveTopology = m_params.shaders.tesellation_control != UNUSED ?
301 vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
302 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
303
304 if (!shaderCreateInfos.empty())
305 {
306 std::vector<vk::VkShaderEXT> shaders(shaderCreateInfos.size());
307 deUint32 i = 0u;
308 deUint32 j = 0u;
309 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
310 {
311 de::Random random(102030);
312 i = random.getUint32() % (deUint32)shaders.size();
313 do {
314 j = random.getUint32() % (deUint32)shaders.size();
315 } while (i == j);
316 std::swap(shaderCreateInfos[i], shaderCreateInfos[j]);
317 }
318 if (m_params.separateLinked)
319 {
320 for (deUint32 k = 0; k < (deUint32)shaders.size(); ++k)
321 vk.createShadersEXT(device, 1u, &shaderCreateInfos[k], DE_NULL, &shaders[k]);
322 }
323 else
324 {
325 vk.createShadersEXT(device, (deUint32)shaders.size(), &shaderCreateInfos[0], DE_NULL, &shaders[0]);
326 }
327 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
328 {
329 std::swap(shaders[i], shaders[j]);
330 }
331 deUint32 n = 0;
332 if (m_params.shaders.vertex == LINKED)
333 {
334 vertShader = shaders[n++];
335 }
336 if (m_params.shaders.tesellation_control == LINKED)
337 {
338 tescShader = shaders[n++];
339 }
340 if (m_params.shaders.tesellation_evaluation == LINKED)
341 {
342 teseShader = shaders[n++];
343 }
344 if (m_params.shaders.geometry == LINKED)
345 {
346 geomShader = shaders[n++];
347 }
348 if (m_params.shaders.fragment == LINKED)
349 {
350 fragShader = shaders[n++];
351 }
352 }
353
354 const vk::VkCommandPoolCreateInfo cmdPoolInfo =
355 {
356 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
357 DE_NULL, // pNext
358 vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
359 queueFamilyIndex, // queuefamilyindex
360 };
361
362 const vk::Move<vk::VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolInfo));
363 const vk::Move<vk::VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
364
365 // Draw
366 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
367
368 vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
369 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preImageBarrier);
370
371 if (m_params.separateBind == SEPARATE)
372 {
373 vk::VkShaderStageFlagBits vertStage = vk::VK_SHADER_STAGE_VERTEX_BIT;
374 vk::VkShaderStageFlagBits tescStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
375 vk::VkShaderStageFlagBits teseStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
376 vk::VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
377 vk::VkShaderStageFlagBits fragStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
378 vk::VkShaderEXT bindVertShader = (m_params.shaders.vertex != UNUSED) ? vertShader : VK_NULL_HANDLE;
379 vk::VkShaderEXT bindTescShader = (m_params.shaders.tesellation_control != UNUSED) ? tescShader : VK_NULL_HANDLE;
380 vk::VkShaderEXT bindTeseShader = (m_params.shaders.tesellation_evaluation!= UNUSED) ? teseShader : VK_NULL_HANDLE;
381 vk::VkShaderEXT bindGeomShader = (m_params.shaders.geometry != UNUSED) ? geomShader : VK_NULL_HANDLE;
382 vk::VkShaderEXT bindFragShader = (m_params.shaders.fragment != UNUSED) ? fragShader : VK_NULL_HANDLE;
383 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &vertStage, &bindVertShader);
384 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &tescStage, &bindTescShader);
385 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &teseStage, &bindTeseShader);
386 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &geomStage, &bindGeomShader);
387 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &fragStage, &bindFragShader);
388 }
389 else if (m_params.separateBind == ONE_LINKED_UNLINKED)
390 {
391 std::vector<vk::VkShaderStageFlagBits> separateStages;
392 std::vector<vk::VkShaderStageFlagBits> togetherStages;
393 std::vector<vk::VkShaderEXT> separateShaders;
394 std::vector<vk::VkShaderEXT> togetherShaders;
395
396 bool linkedAdded = false;
397 if ((!linkedAdded && m_params.shaders.vertex == LINKED) || m_params.shaders.vertex == UNLINKED)
398 {
399 togetherStages.push_back(vk::VK_SHADER_STAGE_VERTEX_BIT);
400 togetherShaders.push_back(vertShader);
401 linkedAdded = true;
402 }
403 else if (m_params.shaders.vertex == LINKED)
404 {
405 separateStages.push_back(vk::VK_SHADER_STAGE_VERTEX_BIT);
406 togetherShaders.push_back(vertShader);
407 }
408
409 if ((!linkedAdded && m_params.shaders.tesellation_control == LINKED) || m_params.shaders.tesellation_control == UNLINKED)
410 {
411 togetherStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
412 togetherShaders.push_back(tescShader);
413 linkedAdded = true;
414 }
415 else if (m_params.shaders.tesellation_control == LINKED)
416 {
417 separateStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
418 separateShaders.push_back(tescShader);
419 }
420
421 if ((!linkedAdded && m_params.shaders.tesellation_evaluation == LINKED) || m_params.shaders.tesellation_evaluation == UNLINKED)
422 {
423 togetherStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
424 togetherShaders.push_back(teseShader);
425 linkedAdded = true;
426 }
427 else if (m_params.shaders.tesellation_evaluation == LINKED)
428 {
429 separateStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
430 separateShaders.push_back(teseShader);
431 }
432
433 if ((!linkedAdded && m_params.shaders.geometry == LINKED) || m_params.shaders.geometry == UNLINKED)
434 {
435 togetherStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
436 togetherShaders.push_back(geomShader);
437 linkedAdded = true;
438 }
439 else if (m_params.shaders.geometry == LINKED)
440 {
441 separateStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
442 separateShaders.push_back(geomShader);
443 }
444
445 if ((!linkedAdded && m_params.shaders.fragment == LINKED) || m_params.shaders.fragment == UNLINKED)
446 {
447 togetherStages.push_back(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
448 togetherShaders.push_back(fragShader);
449 linkedAdded = true;
450 }
451 else if (m_params.shaders.fragment == LINKED)
452 {
453 separateStages.push_back(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
454 separateShaders.push_back(fragShader);
455 }
456
457 vk::bindGraphicsShaders(vk, *cmdBuffer, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, taskSupported, meshSupported);
458 if (!togetherShaders.empty())
459 vk.cmdBindShadersEXT(*cmdBuffer, (deUint32)togetherShaders.size(), togetherStages.data(), togetherShaders.data());
460 if (!separateShaders.empty())
461 vk.cmdBindShadersEXT(*cmdBuffer, (deUint32)separateShaders.size(), separateStages.data(), separateShaders.data());
462 }
463 else
464 {
465 vk::bindGraphicsShaders(vk, *cmdBuffer,
466 m_params.shaders.vertex != UNUSED ? vertShader : VK_NULL_HANDLE,
467 m_params.shaders.tesellation_control != UNUSED ? tescShader : VK_NULL_HANDLE,
468 m_params.shaders.tesellation_evaluation != UNUSED ? teseShader : VK_NULL_HANDLE,
469 m_params.shaders.geometry != UNUSED ? geomShader : VK_NULL_HANDLE,
470 m_params.shaders.fragment != UNUSED ? fragShader : VK_NULL_HANDLE,
471 taskSupported,
472 meshSupported);
473 }
474 vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, primitiveTopology, false);
475
476 bindNullTaskMeshShaders(vk, *cmdBuffer, m_context.getMeshShaderFeaturesEXT());
477
478 const vk::VkClearValue clearValue = vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
479 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
480 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
481 vk::endRendering(vk, *cmdBuffer);
482
483 vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
484 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
485
486 const vk::VkBufferImageCopy copyRegion =
487 {
488 0u, // VkDeviceSize bufferOffset;
489 0u, // deUint32 bufferRowLength;
490 0u, // deUint32 bufferImageHeight;
491 {
492 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
493 0u, // deUint32 mipLevel;
494 0u, // deUint32 baseArrayLayer;
495 1u, // deUint32 layerCount;
496 }, // VkImageSubresourceLayers imageSubresource;
497 { 0, 0, 0 }, // VkOffset3D imageOffset;
498 {renderArea.extent.width, renderArea.extent.height, 1} // VkExtent3D imageExtent;
499 };
500 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, ©Region);
501
502 vk::endCommandBuffer(vk, *cmdBuffer);
503
504 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
505
506 // Cleanup
507 if (m_params.shaders.vertex != UNUSED)
508 vk.destroyShaderEXT(device, vertShader, DE_NULL);
509
510 if (m_params.shaders.tesellation_control != UNUSED)
511 vk.destroyShaderEXT(device, tescShader, DE_NULL);
512
513 if (m_params.shaders.tesellation_evaluation != UNUSED)
514 vk.destroyShaderEXT(device, teseShader, DE_NULL);
515
516 if (m_params.shaders.geometry != UNUSED)
517 vk.destroyShaderEXT(device, geomShader, DE_NULL);
518
519 if (m_params.shaders.fragment != UNUSED)
520 vk.destroyShaderEXT(device, fragShader, DE_NULL);
521
522 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1, (const void*)colorOutputBuffer->getAllocation().getHostPtr());
523
524 const tcu::Vec4 black = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
525 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
526 const deInt32 width = resultBuffer.getWidth();
527 const deInt32 height = resultBuffer.getHeight();
528 const deInt32 xOffset = m_params.shaders.tesellation_control != UNUSED ? 4 : 8;
529 const deInt32 yOffset = m_params.shaders.geometry != UNUSED ? 4 : 8;
530
531 for (deInt32 j = 0; j < height; ++j)
532 {
533 for (deInt32 i = 0; i < width; ++i)
534 {
535 const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
536 if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
537 {
538 if (color != white)
539 {
540 log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be (1.0, 1.0, 1.0, 1.0), but was (" << color << ")" << tcu::TestLog::EndMessage;
541 return tcu::TestStatus::fail("Fail");
542 }
543 }
544 else
545 {
546 if (color != black)
547 {
548 log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be (0.0, 0.0, 0.0, 0.0), but was (" << color << ")" << tcu::TestLog::EndMessage;
549 return tcu::TestStatus::fail("Fail");
550 }
551 }
552 }
553 }
554
555 return tcu::TestStatus::pass("Pass");
556 }
557
558 class ShaderObjectLinkCase : public vkt::TestCase
559 {
560 public:
ShaderObjectLinkCase(tcu::TestContext& testCtx, const std::string& name, const TestParams& params)561 ShaderObjectLinkCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
562 : vkt::TestCase (testCtx, name)
563 , m_params (params)
564 {}
~ShaderObjectLinkCase(void)565 virtual ~ShaderObjectLinkCase (void) {}
566
567 void checkSupport (vkt::Context& context) const override;
568 virtual void initPrograms (vk::SourceCollections& programCollection) const override;
569 TestInstance* createInstance (Context& context) const override { return new ShaderObjectLinkInstance(context, m_params); }
570 private:
571 TestParams m_params;
572 };
573
checkSupport(Context& context) const574 void ShaderObjectLinkCase::checkSupport (Context& context) const
575 {
576 context.requireDeviceFunctionality("VK_EXT_shader_object");
577
578 if (m_params.shaders.tesellation_control != UNUSED || m_params.shaders.tesellation_evaluation != UNUSED
579 || (m_params.nextStages.vertNextStage | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) > 0)
580 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
581
582 if (m_params.shaders.geometry != UNUSED
583 || (m_params.nextStages.vertNextStage | vk::VK_SHADER_STAGE_GEOMETRY_BIT) > 0
584 || (m_params.nextStages.teseNextStage | vk::VK_SHADER_STAGE_GEOMETRY_BIT) > 0)
585 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
586 }
587
initPrograms(vk::SourceCollections& programCollection) const588 void ShaderObjectLinkCase::initPrograms (vk::SourceCollections& programCollection) const
589 {
590 vk::addBasicShaderObjectShaders(programCollection);
591 }
592
593
594 class MeshShaderObjectLinkInstance : public vkt::TestInstance
595 {
596 public:
MeshShaderObjectLinkInstance(Context& context, const MeshParams& params)597 MeshShaderObjectLinkInstance (Context& context, const MeshParams& params)
598 : vkt::TestInstance (context)
599 , m_params (params)
600 {}
~MeshShaderObjectLinkInstance(void)601 virtual ~MeshShaderObjectLinkInstance (void) {}
602
603 tcu::TestStatus iterate (void) override;
604 private:
605 vk::VkShaderStageFlags getNextStage (vk::VkShaderStageFlagBits currentStage);
606
607 MeshParams m_params;
608 };
609
getNextStage(vk::VkShaderStageFlagBits currentStage)610 vk::VkShaderStageFlags MeshShaderObjectLinkInstance::getNextStage (vk::VkShaderStageFlagBits currentStage)
611 {
612 if (currentStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
613 {
614 if (m_params.shaders.task == LINKED)
615 return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
616 return m_params.nextStages.taskNextStage;
617 }
618
619 if (currentStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
620 {
621 if (m_params.shaders.mesh == LINKED)
622 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
623 return m_params.nextStages.meshNextStage;
624 }
625
626 return 0;
627 }
628
iterate(void)629 tcu::TestStatus MeshShaderObjectLinkInstance::iterate (void)
630 {
631 const vk::VkInstance instance = m_context.getInstance();
632 const vk::InstanceDriver instanceDriver (m_context.getPlatformInterface(), instance);
633 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
634 const vk::VkDevice device = m_context.getDevice();
635 const vk::VkQueue queue = m_context.getUniversalQueue();
636 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
637 auto& alloc = m_context.getDefaultAllocator();
638 tcu::TestLog& log = m_context.getTestContext().getLog();
639 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
640
641 vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
642 const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
643
644 const vk::VkImageCreateInfo createInfo =
645 {
646 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
647 DE_NULL, // const void* pNext
648 0u, // VkImageCreateFlags flags
649 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType
650 colorAttachmentFormat, // VkFormat format
651 { 32, 32, 1 }, // VkExtent3D extent
652 1u, // uint32_t mipLevels
653 1u, // uint32_t arrayLayers
654 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
655 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
656 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
657 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
658 0, // uint32_t queueFamilyIndexCount
659 DE_NULL, // const uint32_t* pQueueFamilyIndices
660 vk::VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
661 };
662
663 de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
664 const auto imageView = vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
665 const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
666
667 const vk::VkDeviceSize colorOutputBufferSize = renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
668 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
669 vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
670
671 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
672 vk::DescriptorSetLayoutBuilder()
673 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_MESH_BIT_EXT)
674 .build(vk, device));
675
676 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
677 vk::DescriptorPoolBuilder()
678 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
679 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
680
681 const vk::VkDeviceSize bufferSizeBytes = sizeof(deUint32) * 4;
682 const vk::Unique<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
683 const vk::BufferWithMemory outputBuffer (vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
684
685 const vk::VkDescriptorBufferInfo descriptorInfo = vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
686 vk::DescriptorSetUpdateBuilder()
687 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
688 .update(vk, device);
689
690 const auto pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
691
692 const auto& binaries = m_context.getBinaryCollection();
693 const auto& task = binaries.get("task");
694 const auto& mesh = binaries.get("mesh");
695 const auto& frag = binaries.get("frag");
696
697 vk::VkShaderEXT taskShader;
698 vk::VkShaderEXT meshShader;
699 vk::VkShaderEXT fragShader;
700
701 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos;
702
703 vk::VkShaderCreateInfoEXT taskShaderCreateInfo =
704 {
705 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
706 DE_NULL, // const void* pNext;
707 0u, // VkShaderCreateFlagsEXT flags;
708 vk::VK_SHADER_STAGE_TASK_BIT_EXT, // VkShaderStageFlagBits stage;
709 getNextStage(vk::VK_SHADER_STAGE_TASK_BIT_EXT), // VkShaderStageFlags nextStage;
710 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
711 task.getSize(), // size_t codeSize;
712 task.getBinary(), // const void* pCode;
713 "main", // const char* pName;
714 1u, // uint32_t setLayoutCount;
715 &*descriptorSetLayout, // VkDescriptorSetLayout* pSetLayouts;
716 0u, // uint32_t pushConstantRangeCount;
717 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
718 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
719 };
720
721 if (m_params.shaders.task == LINKED)
722 {
723 taskShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
724 shaderCreateInfos.push_back(taskShaderCreateInfo);
725 }
726 else if (m_params.shaders.task == UNLINKED)
727 {
728 vk.createShadersEXT(device, 1, &taskShaderCreateInfo, DE_NULL, &taskShader);
729 }
730
731 vk::VkShaderCreateInfoEXT meshShaderCreateInfo =
732 {
733 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
734 DE_NULL, // const void* pNext;
735 (m_params.shaders.task == UNUSED) ? (vk::VkShaderCreateFlagsEXT)vk::VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT : (vk::VkShaderCreateFlagsEXT)0u,
736 // VkShaderCreateFlagsEXT flags;
737 vk::VK_SHADER_STAGE_MESH_BIT_EXT, // VkShaderStageFlagBits stage;
738 getNextStage(vk::VK_SHADER_STAGE_MESH_BIT_EXT), // VkShaderStageFlags nextStage;
739 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
740 mesh.getSize(), // size_t codeSize;
741 mesh.getBinary(), // const void* pCode;
742 "main", // const char* pName;
743 1u, // uint32_t setLayoutCount;
744 &*descriptorSetLayout, // VkDescriptorSetLayout* pSetLayouts;
745 0u, // uint32_t pushConstantRangeCount;
746 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
747 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
748 };
749
750 if (m_params.shaders.mesh == LINKED)
751 {
752 meshShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
753 shaderCreateInfos.push_back(meshShaderCreateInfo);
754 }
755 else if (m_params.shaders.mesh == UNLINKED)
756 {
757 vk.createShadersEXT(device, 1, &meshShaderCreateInfo, DE_NULL, &meshShader);
758 }
759
760 vk::VkShaderCreateInfoEXT fragShaderCreateInfo =
761 {
762 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
763 DE_NULL, // const void* pNext;
764 0u, // VkShaderCreateFlagsEXT flags;
765 vk::VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
766 getNextStage(vk::VK_SHADER_STAGE_FRAGMENT_BIT), // VkShaderStageFlags nextStage;
767 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
768 frag.getSize(), // size_t codeSize;
769 frag.getBinary(), // const void* pCode;
770 "main", // const char* pName;
771 1u, // uint32_t setLayoutCount;
772 &*descriptorSetLayout, // VkDescriptorSetLayout* pSetLayouts;
773 0u, // uint32_t pushConstantRangeCount;
774 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
775 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
776 };
777
778 if (m_params.shaders.fragment == LINKED)
779 {
780 fragShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
781 shaderCreateInfos.push_back(fragShaderCreateInfo);
782 }
783 else if (m_params.shaders.fragment == UNLINKED)
784 {
785 vk.createShadersEXT(device, 1, &fragShaderCreateInfo, DE_NULL, &fragShader);
786 }
787
788 if (!shaderCreateInfos.empty())
789 {
790 std::vector<vk::VkShaderEXT> shaders(shaderCreateInfos.size());
791 deUint32 i = 0u;
792 deUint32 j = 0u;
793 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
794 {
795 de::Random random(102030);
796 i = random.getUint32() % (deUint32)shaders.size();
797 do {
798 j = random.getUint32() % (deUint32)shaders.size();
799 } while (i == j);
800 std::swap(shaderCreateInfos[i], shaderCreateInfos[j]);
801 }
802 vk.createShadersEXT(device, (deUint32)shaders.size(), &shaderCreateInfos[0], DE_NULL, &shaders[0]);
803 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
804 {
805 std::swap(shaders[i], shaders[j]);
806 }
807 deUint32 n = 0;
808 if (m_params.shaders.task == LINKED)
809 {
810 taskShader = shaders[n++];
811 }
812 if (m_params.shaders.mesh == LINKED)
813 {
814 meshShader = shaders[n++];
815 }
816 if (m_params.shaders.fragment == LINKED)
817 {
818 fragShader = shaders[n++];
819 }
820 }
821
822 const vk::VkCommandPoolCreateInfo cmdPoolInfo =
823 {
824 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
825 DE_NULL, // pNext
826 vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
827 queueFamilyIndex, // queuefamilyindex
828 };
829
830 const vk::Move<vk::VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolInfo));
831 const vk::Move<vk::VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
832
833 // Draw
834 vk::beginCommandBuffer(vk, *cmdBuffer);
835
836 vk::VkImageMemoryBarrier preImageBarrier =
837 {
838 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
839 DE_NULL, // const void* pNext
840 vk::VK_ACCESS_NONE, // VkAccessFlags srcAccessMask
841 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
842 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
843 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
844 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
845 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
846 **image, // VkImage image
847 {
848 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
849 0u, // uint32_t baseMipLevel
850 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
851 0u, // uint32_t baseArray
852 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
853 }
854 };
855
856 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preImageBarrier);
857
858 const vk::VkClearValue clearValue = vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
859 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
860 vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true);
861 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
862
863 bindNullRasterizationShaders(vk, *cmdBuffer, m_context.getDeviceFeatures());
864 vk::VkShaderStageFlagBits stages[] = {
865 vk::VK_SHADER_STAGE_TASK_BIT_EXT,
866 vk::VK_SHADER_STAGE_MESH_BIT_EXT,
867 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
868 };
869 vk::VkShaderEXT shaders[] = {
870 m_params.shaders.task != UNUSED ? taskShader : VK_NULL_HANDLE,
871 m_params.shaders.mesh != UNUSED ? meshShader : VK_NULL_HANDLE,
872 m_params.shaders.fragment != UNUSED ? fragShader : VK_NULL_HANDLE,
873 };
874 vk.cmdBindShadersEXT(*cmdBuffer, 3, stages, shaders);
875
876 vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
877
878 vk::endRendering(vk, *cmdBuffer);
879
880 vk::VkImageMemoryBarrier postImageBarrier =
881 {
882 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
883 DE_NULL, // const void* pNext
884 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
885 vk::VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
886 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
887 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
888 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
889 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
890 **image, // VkImage image
891 {
892 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
893 0u, // uint32_t baseMipLevel
894 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
895 0u, // uint32_t baseArray
896 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
897 }
898 };
899
900 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
901
902 const vk::VkBufferImageCopy copyRegion =
903 {
904 0u, // VkDeviceSize bufferOffset;
905 0u, // deUint32 bufferRowLength;
906 0u, // deUint32 bufferImageHeight;
907 {
908 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
909 0u, // deUint32 mipLevel;
910 0u, // deUint32 baseArrayLayer;
911 1u, // deUint32 layerCount;
912 }, // VkImageSubresourceLayers imageSubresource;
913 { 0, 0, 0 }, // VkOffset3D imageOffset;
914 {renderArea.extent.width, renderArea.extent.height, 1} // VkExtent3D imageExtent;
915 };
916 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, ©Region);
917
918 vk::endCommandBuffer(vk, *cmdBuffer);
919
920 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
921
922 // Cleanup
923 if (m_params.shaders.task != UNUSED)
924 vk.destroyShaderEXT(device, taskShader, DE_NULL);
925
926 if (m_params.shaders.mesh != UNUSED)
927 vk.destroyShaderEXT(device, meshShader, DE_NULL);
928
929 if (m_params.shaders.fragment != UNUSED)
930 vk.destroyShaderEXT(device, fragShader, DE_NULL);
931
932 if (m_params.shaders.fragment != UNUSED)
933 {
934 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1, (const void*)colorOutputBuffer->getAllocation().getHostPtr());
935
936 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
937 const deInt32 width = resultBuffer.getWidth();
938 const deInt32 height = resultBuffer.getHeight();
939
940 for (deInt32 j = 0; j < height; ++j)
941 {
942 for (deInt32 i = 0; i < width; ++i)
943 {
944 const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
945 if (color != white)
946 {
947 log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be (1.0, 1.0, 1.0, 1.0), but was (" << color << ")" << tcu::TestLog::EndMessage;
948 return tcu::TestStatus::fail("Fail");
949 }
950 }
951 }
952 }
953 if (m_params.shaders.mesh != UNUSED)
954 {
955 const vk::Allocation& outputBufferAllocation = outputBuffer.getAllocation();
956 invalidateAlloc(vk, device, outputBufferAllocation);
957
958 const deUint32* bufferPtr = static_cast<deUint32*>(outputBufferAllocation.getHostPtr());
959
960 if (bufferPtr[0] != 0u || bufferPtr[1] != 1u || bufferPtr[2] != 2u || bufferPtr[3] != 3u)
961 {
962 log << tcu::TestLog::Message << "Buffer values were expected to be [0, 1, 2, 3], but were[" << bufferPtr[0] << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", " << "]" << tcu::TestLog::EndMessage;
963 return tcu::TestStatus::fail("Fail");
964 }
965 }
966
967 return tcu::TestStatus::pass("Pass");
968 }
969
970 class MeshShaderObjectLinkCase : public vkt::TestCase
971 {
972 public:
MeshShaderObjectLinkCase(tcu::TestContext& testCtx, const std::string& name, const MeshParams& params)973 MeshShaderObjectLinkCase (tcu::TestContext& testCtx, const std::string& name, const MeshParams& params)
974 : vkt::TestCase (testCtx, name)
975 , m_params (params)
976 {}
~MeshShaderObjectLinkCase(void)977 virtual ~MeshShaderObjectLinkCase (void) {}
978
979 void checkSupport (vkt::Context& context) const override;
980 virtual void initPrograms (vk::SourceCollections& programCollection) const override;
981 TestInstance* createInstance (Context& context) const override { return new MeshShaderObjectLinkInstance(context, m_params); }
982 private:
983 MeshParams m_params;
984 };
985
initPrograms(vk::SourceCollections& programCollection) const986 void MeshShaderObjectLinkCase::initPrograms (vk::SourceCollections& programCollection) const
987 {
988 std::stringstream task;
989 std::stringstream mesh;
990 std::stringstream frag;
991
992 task
993 << "#version 450\n"
994 << "#extension GL_EXT_mesh_shader : enable\n"
995 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
996 << "void main ()\n"
997 << "{\n"
998 << " EmitMeshTasksEXT(1u, 1u, 1u);\n"
999 << "}\n";
1000
1001 mesh
1002 << "#version 460\n"
1003 << "#extension GL_EXT_mesh_shader : require\n"
1004 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1005 << "layout(max_vertices = 3) out;\n"
1006 << "layout(max_primitives = 1) out;\n"
1007 << "layout(triangles) out;\n"
1008 << "layout(set = 0, binding = 0) buffer Output {\n"
1009 << " uint values[4];\n"
1010 << "} buffer_out;\n\n"
1011 << "void main() {\n"
1012 << " SetMeshOutputsEXT(3, 1);\n"
1013 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1014 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1015 << " gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0, 3.0, 0.0f, 1.0f);\n"
1016 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1017 << " buffer_out.values[0] = 0u;\n"
1018 << " buffer_out.values[1] = 1u;\n"
1019 << " buffer_out.values[2] = 2u;\n"
1020 << " buffer_out.values[3] = 3u;\n"
1021 << "}\n";
1022
1023 frag
1024 << "#version 450\n"
1025 << "layout (location=0) out vec4 outColor;\n"
1026 << "void main() {\n"
1027 << " outColor = vec4(1.0f);\n"
1028 << "}\n";
1029
1030 programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1031 programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1032 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1033 }
1034
checkSupport(Context& context) const1035 void MeshShaderObjectLinkCase::checkSupport (Context& context) const
1036 {
1037 context.requireDeviceFunctionality("VK_EXT_shader_object");
1038
1039 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1040 const auto& features = context.getMeshShaderFeaturesEXT();
1041 if (!features.taskShader)
1042 TCU_THROW(NotSupportedError, "Task shaders not supported");
1043 if (!features.meshShader)
1044 TCU_THROW(NotSupportedError, "Mesh shaders not supported");
1045 }
1046
typeToString(ShaderType type)1047 std::string typeToString(ShaderType type) {
1048 if (type == UNUSED)
1049 return "unused";
1050
1051 if (type == LINKED)
1052 return "linked";
1053
1054 if (type == UNLINKED)
1055 return "unlinked";
1056
1057 return {};
1058 }
1059
1060 }
1061
createShaderObjectLinkTests(tcu::TestContext& testCtx)1062 tcu::TestCaseGroup* createShaderObjectLinkTests (tcu::TestContext& testCtx)
1063 {
1064 de::MovePtr<tcu::TestCaseGroup> linkGroup(new tcu::TestCaseGroup(testCtx, "link"));
1065
1066 const Shaders shaderTests[] =
1067 {
1068 { LINKED, LINKED, UNLINKED, UNUSED, UNLINKED, },
1069 { LINKED, LINKED, LINKED, UNUSED, UNLINKED, },
1070 { LINKED, LINKED, LINKED, LINKED, UNLINKED, },
1071 { LINKED, LINKED, LINKED, LINKED, LINKED, },
1072 { LINKED, UNUSED, UNUSED, LINKED, UNLINKED, },
1073 { LINKED, UNUSED, UNUSED, LINKED, LINKED, },
1074 { LINKED, UNUSED, UNUSED, UNUSED, LINKED, },
1075 { UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED },
1076 { UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED },
1077 { UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED },
1078 { UNLINKED, LINKED, LINKED, UNUSED, UNLINKED },
1079 { UNLINKED, LINKED, LINKED, LINKED, UNLINKED },
1080 { UNLINKED, LINKED, LINKED, UNUSED, LINKED },
1081 { UNLINKED, LINKED, LINKED, LINKED, LINKED },
1082 { UNLINKED, UNUSED, UNUSED, LINKED, LINKED },
1083 };
1084
1085 const bool randomOrderTests[] =
1086 {
1087 false,
1088 true,
1089 };
1090
1091 const struct
1092 {
1093 BindType bindType;
1094 const char* name;
1095 } bindTypeTests[] =
1096 {
1097 { SEPARATE, "separate" },
1098 { ONE_LINKED_UNLINKED, "one_linked_unlinked" },
1099 { ALL, "all" },
1100 };
1101
1102 for (const auto& shaders : shaderTests)
1103 {
1104 std::string shadersName = "";
1105 shadersName += typeToString(shaders.vertex) + "_";
1106 shadersName += typeToString(shaders.tesellation_control) + "_";
1107 shadersName += typeToString(shaders.tesellation_evaluation) + "_";
1108 shadersName += typeToString(shaders.geometry) + "_";
1109 shadersName += typeToString(shaders.fragment);
1110 de::MovePtr<tcu::TestCaseGroup> shadersGroup(new tcu::TestCaseGroup(testCtx, shadersName.c_str()));
1111
1112 for (const auto& bindType : bindTypeTests)
1113 {
1114 de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, bindType.name));
1115 for (const auto& randomOrder : randomOrderTests)
1116 {
1117 NextStages nextStages = {};
1118 if (shaders.tesellation_control != UNUSED) {
1119 nextStages.vertNextStage |= vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1120 nextStages.tescNextStage |= vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1121 }
1122 if (shaders.geometry != UNUSED) {
1123 nextStages.vertNextStage |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1124 nextStages.teseNextStage |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1125 }
1126 if (shaders.fragment != UNUSED) {
1127 nextStages.vertNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1128 nextStages.teseNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1129 nextStages.geomNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1130 }
1131
1132 TestParams params = {
1133 shaders, // Shaders shaders;
1134 randomOrder, // bool randomOrder;
1135 nextStages, // NextStages nextStages;
1136 false, // bool separateLinked;
1137 bindType.bindType, // bool separateBind;
1138 };
1139
1140 std::string randomOrderName = randomOrder ? "random_order" : "default";
1141
1142 bindGroup->addChild(new ShaderObjectLinkCase(testCtx, randomOrderName, params));
1143 }
1144
1145 if (shaders.vertex == LINKED || shaders.tesellation_control == LINKED || shaders.tesellation_evaluation == LINKED || shaders.geometry == LINKED || shaders.fragment == LINKED)
1146 {
1147 TestParams params = {
1148 shaders, // Shaders shaders;
1149 false, // bool randomOrder;
1150 {
1151 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1152 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1153 vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1154 vk::VK_SHADER_STAGE_FRAGMENT_BIT, }, // NextStages nextStages;
1155 true, // bool separateLinked;
1156 ALL, // BindType separateBind
1157 };
1158
1159 bindGroup->addChild(new ShaderObjectLinkCase(testCtx, "separate_link", params));
1160 }
1161 shadersGroup->addChild(bindGroup.release());
1162 }
1163 linkGroup->addChild(shadersGroup.release());
1164 }
1165
1166 const struct
1167 {
1168 Shaders shaders;
1169 NextStages nextStages;
1170 const char* name;
1171 } nextStageTests[] =
1172 {
1173 {
1174 { UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED },
1175 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1176 "vert_t"
1177 },
1178 {
1179 { UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED },
1180 { vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0u, 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1181 "vert_g"
1182 },
1183 {
1184 { UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED },
1185 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1186 "vert_tg"
1187 },
1188 {
1189 { UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED },
1190 { vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 0u, 0u, },
1191 "vert_f"
1192 },
1193 {
1194 { UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED },
1195 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1196 "vert_tf"
1197 },
1198 {
1199 { UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED },
1200 { vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1201 "vert_gf"
1202 },
1203 {
1204 { UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED },
1205 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1206 "vert_tgf"
1207 },
1208 {
1209 { UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED },
1210 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1211 "tesc_t"
1212 },
1213 {
1214 { UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED },
1215 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1216 "tese_g"
1217 },
1218 {
1219 { UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED },
1220 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1221 "tese_f"
1222 },
1223 {
1224 { UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED },
1225 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1226 "tese_gf"
1227 },
1228 {
1229 { UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED },
1230 { vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0u, 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1231 "geom_f"
1232 },
1233 };
1234
1235 de::MovePtr<tcu::TestCaseGroup> nextStageGroup(new tcu::TestCaseGroup(testCtx, "next_stage"));
1236 for (const auto& nextStage : nextStageTests)
1237 {
1238 TestParams params = {
1239 nextStage.shaders,
1240 false,
1241 nextStage.nextStages,
1242 false,
1243 ALL,
1244 };
1245 nextStageGroup->addChild(new ShaderObjectLinkCase(testCtx, nextStage.name, params));
1246 }
1247 linkGroup->addChild(nextStageGroup.release());
1248
1249 const MeshShaders meshShaderTests[] =
1250 {
1251 { UNLINKED, UNLINKED, UNLINKED, },
1252 { UNLINKED, UNLINKED, UNUSED, },
1253 { LINKED, LINKED, UNLINKED, },
1254 { UNLINKED, LINKED, LINKED, },
1255 { LINKED, LINKED, LINKED, },
1256 };
1257
1258 for (const auto& meshShaders : meshShaderTests)
1259 {
1260 std::string name = "mesh_";
1261 name += typeToString(meshShaders.task) + "_";
1262 name += typeToString(meshShaders.mesh) + "_";
1263 name += typeToString(meshShaders.fragment);
1264 de::MovePtr<tcu::TestCaseGroup> meshGroup(new tcu::TestCaseGroup(testCtx, name.c_str()));
1265
1266 for (const auto& randomOrder : randomOrderTests)
1267 {
1268 MeshParams params = {
1269 meshShaders,
1270 randomOrder,
1271 { 0u, 0u, },
1272 };
1273
1274 std::string randomOrderName = (randomOrder) ? "random_order" : "default";
1275
1276 meshGroup->addChild(new MeshShaderObjectLinkCase(testCtx, randomOrderName, params));
1277 }
1278 linkGroup->addChild(meshGroup.release());
1279 }
1280
1281 const struct
1282 {
1283 MeshNextStages nextStages;
1284 const char* name;
1285 } meshNextStageTests[] =
1286 {
1287 { { vk::VK_SHADER_STAGE_MESH_BIT_EXT, 0u, }, "mesh" },
1288 { { 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, }, "frag" },
1289 };
1290
1291 de::MovePtr<tcu::TestCaseGroup> meshNextStageGroup(new tcu::TestCaseGroup(testCtx, "meshnext_stage"));
1292 for (const auto& meshNextStage : meshNextStageTests)
1293 {
1294 MeshParams params = {
1295 { UNLINKED, UNLINKED, UNLINKED },
1296 false,
1297 meshNextStage.nextStages,
1298 };
1299 meshNextStageGroup->addChild(new MeshShaderObjectLinkCase(testCtx, meshNextStage.name, params));
1300 }
1301 linkGroup->addChild(meshNextStageGroup.release());
1302
1303 return linkGroup.release();
1304 }
1305
1306 } // ShaderObject
1307 } // vkt
1308