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 Binding Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktShaderObjectBindingTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkShaderObjectUtil.hpp"
30 #include "vktShaderObjectCreateUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkBufferWithMemory.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "deMath.h"
40 #include "vktCustomInstancesDevices.hpp"
41 #include "tcuCommandLine.hpp"
42 #include "vkBuilderUtil.hpp"
43
44 namespace vkt
45 {
46 namespace ShaderObject
47 {
48
49 namespace
50 {
51
52 enum TestType
53 {
54 PASSTHROUGH_GEOM,
55 SWAP,
56 DISABLED,
57 UNBIND,
58 DRAW_DISPATCH_DRAW,
59 DISPATCH_DRAW_DISPATCH,
60 };
61
62 struct BindingDrawParams
63 {
64 TestType testType;
65 vk::VkShaderStageFlagBits stage;
66 vk::VkShaderStageFlagBits unusedOutputs;
67 vk::VkShaderStageFlagBits binaryStage;
68 bool bindUnsupported;
69 bool setStateAfter;
70 bool unbindWithNullpShaders;
71 };
72
73 struct MeshBindingDrawParams
74 {
75 vk::VkShaderStageFlagBits stage;
76 };
77
78 struct BindingParams
79 {
80 bool useMeshShaders;
81 };
82
83 class ShaderObjectBindingDrawInstance : public vkt::TestInstance
84 {
85 public:
ShaderObjectBindingDrawInstance(Context & context,const BindingDrawParams & params)86 ShaderObjectBindingDrawInstance(Context &context, const BindingDrawParams ¶ms)
87 : vkt::TestInstance(context)
88 , m_params(params)
89 {
90 }
~ShaderObjectBindingDrawInstance(void)91 virtual ~ShaderObjectBindingDrawInstance(void)
92 {
93 }
94
95 tcu::TestStatus iterate(void) override;
96
97 private:
98 vk::Move<vk::VkShaderEXT> createShader(const vk::DeviceInterface &vk, const vk::VkDevice device,
99 vk::VkShaderStageFlagBits stage, const std::string &name,
100 const vk::VkDescriptorSetLayout *descriptorSetLayout = DE_NULL);
101 void createDevice(void);
getDevice(void)102 vk::VkDevice getDevice(void)
103 {
104 return (m_params.testType == DISABLED) ? m_customDevice.get() : m_context.getDevice();
105 }
106 void setDynamicStates(vk::VkCommandBuffer cmdBuffer, bool tessShader);
107
108 BindingDrawParams m_params;
109 vk::Move<vk::VkDevice> m_customDevice;
110 };
111
createDevice(void)112 void ShaderObjectBindingDrawInstance::createDevice(void)
113 {
114 if (m_params.testType != DISABLED)
115 return;
116
117 const float queuePriority = 1.0f;
118 const auto &deviceExtensions = m_context.getDeviceCreationExtensions();
119 auto features2 = m_context.getDeviceFeatures2();
120
121 if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
122 features2.features.geometryShader = VK_FALSE;
123 else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
124 features2.features.tessellationShader = VK_FALSE;
125
126 vk::VkDeviceQueueCreateInfo queueInfo = {
127 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
128 DE_NULL, // const void* pNext;
129 0u, // VkDeviceQueueCreateFlags flags;
130 0u, // uint32_t queueFamilyIndex;
131 1u, // uint32_t queueCount;
132 &queuePriority // const float* pQueuePriorities;
133 };
134
135 const vk::VkDeviceCreateInfo deviceInfo = {
136 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
137 &features2, // const void* pNext;
138 (vk::VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
139 1u, // uint32_t queueCreateInfoCount;
140 &queueInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
141 0u, // uint32_t enabledLayerCount;
142 DE_NULL, // const char* const* ppEnabledLayerNames;
143 uint32_t(deviceExtensions.size()), // uint32_t enabledExtensionCount;
144 (deviceExtensions.empty()) ? DE_NULL : deviceExtensions.data(), // const char* const* ppEnabledExtensionNames;
145 DE_NULL // const VkPhysicalDeviceFeatures* pEnabledFeatures;
146 };
147
148 m_customDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
149 m_context.getPlatformInterface(), m_context.getInstance(),
150 m_context.getInstanceInterface(), m_context.getPhysicalDevice(), &deviceInfo);
151 }
152
createShader(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::VkShaderStageFlagBits stage,const std::string & name,const vk::VkDescriptorSetLayout * descriptorSetLayout)153 vk::Move<vk::VkShaderEXT> ShaderObjectBindingDrawInstance::createShader(
154 const vk::DeviceInterface &vk, const vk::VkDevice device, vk::VkShaderStageFlagBits stage, const std::string &name,
155 const vk::VkDescriptorSetLayout *descriptorSetLayout)
156 {
157 const auto &binaries = m_context.getBinaryCollection();
158 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
159 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
160
161 if (m_params.binaryStage == stage)
162 {
163 auto shaderCreateInfo = vk::makeShaderCreateInfo(stage, binaries.get(name), tessellationSupported,
164 geometrySupported, descriptorSetLayout);
165 const auto shader = vk::createShader(vk, device, shaderCreateInfo);
166
167 size_t dataSize;
168 vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
169 std::vector<uint8_t> data(dataSize);
170 vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
171
172 shaderCreateInfo.codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT;
173 shaderCreateInfo.codeSize = dataSize;
174 shaderCreateInfo.pCode = data.data();
175
176 return vk::createShader(vk, device, shaderCreateInfo);
177 }
178
179 return vk::createShader(vk, device,
180 vk::makeShaderCreateInfo(stage, binaries.get(name), tessellationSupported,
181 geometrySupported, descriptorSetLayout));
182 }
183
setDynamicStates(vk::VkCommandBuffer cmdBuffer,bool tessShader)184 void ShaderObjectBindingDrawInstance::setDynamicStates(vk::VkCommandBuffer cmdBuffer, bool tessShader)
185 {
186 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
187 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(
188 m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
189
190 const vk::VkPrimitiveTopology topology =
191 tessShader ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
192
193 vk::setDefaultShaderObjectDynamicStates(vk, cmdBuffer, deviceExtensions, topology, false);
194
195 vk::VkBool32 colorBlendEnable = VK_TRUE;
196 vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0u, 1u, &colorBlendEnable);
197 vk::VkColorBlendEquationEXT colorBlendEquation = {
198 vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
199 vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor;
200 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
201 vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
202 vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor;
203 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
204 };
205 vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0u, 1u, &colorBlendEquation);
206 }
207
iterate(void)208 tcu::TestStatus ShaderObjectBindingDrawInstance::iterate(void)
209 {
210 const vk::VkInstance instance = m_context.getInstance();
211 const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
212 createDevice();
213 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
214 const vk::VkDevice device = getDevice();
215 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
216 const vk::VkQueue queue = getDeviceQueue(m_context.getDeviceInterface(), device, queueFamilyIndex, 0u);
217 auto alloctor = de::MovePtr<vk::Allocator>(new vk::SimpleAllocator(
218 vk, device, getPhysicalDeviceMemoryProperties(instanceDriver, m_context.getPhysicalDevice())));
219 auto &alloc = *alloctor;
220 tcu::TestLog &log = m_context.getTestContext().getLog();
221
222 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
223 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
224 const bool taskSupported = m_context.getMeshShaderFeaturesEXT().taskShader;
225 const bool meshSupported = m_context.getMeshShaderFeaturesEXT().meshShader;
226
227 vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
228 const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
229 const auto subresourceLayers = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
230 const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
231 vk::VkExtent3D extent = {renderArea.extent.width, renderArea.extent.height, 1};
232
233 const vk::VkImageCreateInfo createInfo = {
234 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
235 DE_NULL, // const void* pNext
236 0u, // VkImageCreateFlags flags
237 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType
238 colorAttachmentFormat, // VkFormat format
239 {32, 32, 1}, // VkExtent3D extent
240 1u, // uint32_t mipLevels
241 1u, // uint32_t arrayLayers
242 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
243 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
244 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
245 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
246 0, // uint32_t queueFamilyIndexCount
247 DE_NULL, // const uint32_t* pQueueFamilyIndices
248 vk::VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
249 };
250
251 de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
252 new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
253 const auto imageView =
254 vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
255
256 const vk::VkDeviceSize colorOutputBufferSize =
257 renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
258 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
259 vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
260 vk::MemoryRequirement::HostVisible));
261
262 const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 16;
263 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
264 vk::DescriptorSetLayoutBuilder()
265 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
266 .build(vk, device));
267
268 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
269 vk::DescriptorPoolBuilder()
270 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
271 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u));
272
273 const vk::Move<vk::VkCommandPool> cmdPool(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
274 const vk::Move<vk::VkCommandBuffer> cmdBuffer(
275 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
276
277 const vk::Unique<vk::VkDescriptorSet> descriptorSet1(
278 vk::makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
279 const vk::Unique<vk::VkDescriptorSet> descriptorSet2(
280 vk::makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
281 const vk::BufferWithMemory outputBuffer1(
282 vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
283 vk::MemoryRequirement::HostVisible);
284 const vk::BufferWithMemory outputBuffer2(
285 vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
286 vk::MemoryRequirement::HostVisible);
287
288 const auto computePipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout.get());
289
290 const vk::VkDescriptorBufferInfo descriptorInfo1 =
291 vk::makeDescriptorBufferInfo(*outputBuffer1, 0ull, bufferSizeBytes);
292 const vk::VkDescriptorBufferInfo descriptorInfo2 =
293 vk::makeDescriptorBufferInfo(*outputBuffer2, 0ull, bufferSizeBytes);
294 vk::DescriptorSetUpdateBuilder()
295 .writeSingle(*descriptorSet1, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
296 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo1)
297 .update(vk, device);
298 vk::DescriptorSetUpdateBuilder()
299 .writeSingle(*descriptorSet2, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
300 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo2)
301 .update(vk, device);
302
303 vk::Move<vk::VkShaderEXT> vertShader;
304 vk::Move<vk::VkShaderEXT> tescShader;
305 vk::Move<vk::VkShaderEXT> teseShader;
306 vk::Move<vk::VkShaderEXT> geomShader;
307 vk::Move<vk::VkShaderEXT> fragShader;
308 vk::Move<vk::VkShaderEXT> compShader;
309 vk::Move<vk::VkShaderEXT> passThroughGeomShader;
310 vk::Move<vk::VkShaderEXT> vertAltShader;
311 vk::Move<vk::VkShaderEXT> tescAltShader;
312 vk::Move<vk::VkShaderEXT> teseAltShader;
313 vk::Move<vk::VkShaderEXT> geomAltShader;
314 vk::Move<vk::VkShaderEXT> fragAltShader;
315
316 if (tessellationSupported && geometrySupported)
317 {
318 vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vert");
319 vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAlt");
320 }
321 else if (tessellationSupported)
322 {
323 vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoGeom");
324 vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoGeom");
325 }
326 else if (geometrySupported)
327 {
328 vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoTess");
329 vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoTess");
330 }
331 else
332 {
333 vertShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoTessGeom");
334 vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoTessGeom");
335 }
336 if (tessellationSupported &&
337 (m_params.stage != vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_params.testType != DISABLED))
338 {
339 tescShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc");
340 teseShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tese");
341 tescAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tescAlt");
342 teseAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "teseAlt");
343 }
344 if (geometrySupported && (m_params.stage != vk::VK_SHADER_STAGE_GEOMETRY_BIT || m_params.testType != DISABLED))
345 {
346 geomShader = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom");
347 geomAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geomAlt");
348 passThroughGeomShader = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "passThroughGeom");
349 }
350 fragShader = createShader(vk, device, vk::VK_SHADER_STAGE_FRAGMENT_BIT, "blendFrag");
351 compShader = createShader(vk, device, vk::VK_SHADER_STAGE_COMPUTE_BIT, "comp", &*descriptorSetLayout);
352 fragAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_FRAGMENT_BIT, "fragAlt");
353
354 const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 0.0f});
355 vk::beginCommandBuffer(vk, *cmdBuffer);
356
357 vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(
358 vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
359 vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
360 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
361 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u,
362 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
363 &preImageBarrier);
364
365 if (!m_params.setStateAfter)
366 setDynamicStates(*cmdBuffer, tessellationSupported);
367
368 vk::VkBool32 colorBlendEnable = VK_TRUE;
369 vk.cmdSetColorBlendEnableEXT(*cmdBuffer, 0u, 1u, &colorBlendEnable);
370 vk::VkColorBlendEquationEXT colorBlendEquation = {
371 vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
372 vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor;
373 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
374 vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
375 vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor;
376 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
377 };
378 vk.cmdSetColorBlendEquationEXT(*cmdBuffer, 0u, 1u, &colorBlendEquation);
379
380 if (m_params.testType != DISPATCH_DRAW_DISPATCH)
381 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
382 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
383
384 vk::VkShaderEXT nullShader = VK_NULL_HANDLE;
385
386 if (m_params.testType == PASSTHROUGH_GEOM)
387 {
388 vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *passThroughGeomShader,
389 *fragShader, taskSupported, meshSupported);
390 if (m_params.setStateAfter)
391 setDynamicStates(*cmdBuffer, tessellationSupported);
392 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
393 vk::VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
394 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &geomStage, &nullShader);
395 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
396 }
397 else if (m_params.testType == SWAP)
398 {
399 vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
400 taskSupported, meshSupported);
401 if (m_params.setStateAfter)
402 setDynamicStates(*cmdBuffer, tessellationSupported);
403 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
404 vk::VkShaderEXT shader = VK_NULL_HANDLE;
405 if (m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
406 shader = *vertAltShader;
407 else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
408 shader = *tescAltShader;
409 else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
410 shader = *teseAltShader;
411 else if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
412 shader = *geomAltShader;
413 else if (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
414 shader = *fragAltShader;
415 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &shader);
416 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
417 }
418 else if (m_params.testType == DISABLED)
419 {
420 if (taskSupported)
421 {
422 vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
423 vk::VkShaderEXT shader = VK_NULL_HANDLE;
424 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
425 }
426 if (meshSupported)
427 {
428 vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_MESH_BIT_EXT;
429 vk::VkShaderEXT shader = VK_NULL_HANDLE;
430 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
431 }
432 if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
433 {
434 vk::VkShaderStageFlagBits stages[] = {
435 vk::VK_SHADER_STAGE_VERTEX_BIT, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
436 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT};
437 vk::VkShaderEXT shaders[] = {*vertShader, *tescShader, *teseShader, *fragShader};
438 vk.cmdBindShadersEXT(*cmdBuffer, 4u, stages, shaders);
439 if (m_params.bindUnsupported)
440 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
441 if (m_params.setStateAfter)
442 setDynamicStates(*cmdBuffer, tessellationSupported);
443 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
444 }
445 else
446 {
447 vk.cmdSetPrimitiveTopology(*cmdBuffer, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
448 vk::VkShaderStageFlagBits stages[] = {vk::VK_SHADER_STAGE_VERTEX_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT,
449 vk::VK_SHADER_STAGE_FRAGMENT_BIT};
450 vk::VkShaderEXT shaders[] = {*vertShader, *geomShader, *fragShader};
451 vk.cmdBindShadersEXT(*cmdBuffer, 3u, stages, shaders);
452 if (m_params.bindUnsupported)
453 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
454 if (m_params.setStateAfter)
455 setDynamicStates(*cmdBuffer, tessellationSupported);
456 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
457 }
458 }
459 else if (m_params.testType == UNBIND)
460 {
461 vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
462 taskSupported, meshSupported);
463 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
464 if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
465 {
466 if (m_params.unbindWithNullpShaders)
467 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, DE_NULL);
468 else
469 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
470 }
471 else
472 {
473 vk::VkShaderStageFlagBits stages[] = {vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
474 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT};
475 vk::VkShaderEXT nullShaders[] = {VK_NULL_HANDLE, VK_NULL_HANDLE};
476 vk.cmdSetPrimitiveTopology(*cmdBuffer, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
477 if (m_params.unbindWithNullpShaders)
478 vk.cmdBindShadersEXT(*cmdBuffer, 2u, stages, DE_NULL);
479 else
480 vk.cmdBindShadersEXT(*cmdBuffer, 2u, stages, nullShaders);
481 }
482 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
483 }
484 else if (m_params.testType == DRAW_DISPATCH_DRAW)
485 {
486 vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
487 taskSupported, meshSupported);
488 if (m_params.setStateAfter)
489 setDynamicStates(*cmdBuffer, tessellationSupported);
490 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
491 vk::VkShaderStageFlagBits computeStage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
492 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &computeStage, &*compShader);
493 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
494 }
495 else if (m_params.testType == DISPATCH_DRAW_DISPATCH)
496 {
497 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1,
498 &descriptorSet1.get(), 0, DE_NULL);
499 vk::VkShaderStageFlagBits computeStage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
500 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &computeStage, &*compShader);
501 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
502 vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
503 taskSupported, meshSupported);
504 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1,
505 &descriptorSet2.get(), 0, DE_NULL);
506 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
507 }
508
509 if (m_params.testType != DISPATCH_DRAW_DISPATCH)
510 vk::endRendering(vk, *cmdBuffer);
511
512 vk::VkImageMemoryBarrier postImageBarrier =
513 vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
514 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
515 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
516 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
517 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
518 &postImageBarrier);
519
520 const vk::VkBufferImageCopy copyRegion = vk::makeBufferImageCopy(extent, subresourceLayers);
521 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, ©Region);
522
523 vk::endCommandBuffer(vk, *cmdBuffer);
524
525 vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
526
527 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
528 vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1,
529 (const void *)colorOutputBuffer->getAllocation().getHostPtr());
530
531 const int32_t width = resultBuffer.getWidth();
532 const int32_t height = resultBuffer.getHeight();
533 const float threshold = 1.0f / 256.0f;
534 int32_t xOffset1 = width / 8;
535 int32_t yOffset1 = height / 8;
536 int32_t xOffset2 = width / 8;
537 int32_t yOffset2 = height / 8;
538 tcu::Vec4 expectedColor1 = tcu::Vec4(0.75f, 0.75f, 0.75f, 0.75f);
539 tcu::Vec4 expectedColor2 = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
540 tcu::Vec4 blackColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
541
542 if (m_params.testType == PASSTHROUGH_GEOM)
543 {
544 yOffset1 = height / 4;
545 xOffset2 = xOffset1;
546 yOffset2 = yOffset1;
547 }
548 else if (m_params.testType == SWAP)
549 {
550 if (m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
551 {
552 xOffset2 = 0;
553 yOffset2 = 0;
554 }
555 else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
556 {
557 xOffset2 = 10;
558 yOffset2 = 10;
559 }
560 else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
561 {
562 xOffset2 = 12;
563 yOffset2 = height / 8;
564 }
565 else if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
566 {
567 xOffset2 = width / 8;
568 yOffset2 = 12;
569 }
570 else if (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
571 {
572 expectedColor1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
573 }
574 }
575 else if (m_params.testType == DISABLED)
576 {
577 if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
578 {
579 yOffset1 = height / 4;
580 xOffset2 = 16;
581 yOffset2 = 16;
582 }
583 else
584 {
585 xOffset1 = width / 4;
586 xOffset2 = 16;
587 yOffset2 = 16;
588 }
589 }
590 else if (m_params.testType == UNBIND)
591 {
592 if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
593 {
594 xOffset2 = xOffset1;
595 yOffset2 = yOffset1 * 2;
596 }
597 else
598 {
599 xOffset2 = xOffset1 * 2;
600 yOffset2 = yOffset1;
601 }
602 }
603 else if (m_params.testType == DRAW_DISPATCH_DRAW)
604 {
605 xOffset2 = xOffset1;
606 yOffset2 = yOffset1;
607 }
608
609 if (m_params.testType == DISPATCH_DRAW_DISPATCH)
610 {
611 for (uint32_t i = 0; i < 2; ++i)
612 {
613 const vk::Allocation &outputBufferAllocation =
614 i == 0 ? outputBuffer1.getAllocation() : outputBuffer2.getAllocation();
615 invalidateAlloc(vk, device, outputBufferAllocation);
616
617 const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
618
619 for (uint32_t j = 0; j < 16; ++j)
620 {
621 if (bufferPtr[j] != j)
622 return tcu::TestStatus::fail("Fail");
623 }
624 }
625 return tcu::TestStatus::pass("Pass");
626 }
627
628 for (int32_t j = 0; j < height; ++j)
629 {
630 for (int32_t i = 0; i < width; ++i)
631 {
632 const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
633
634 bool first = i >= xOffset1 && i < width - xOffset1 && j >= yOffset1 && j < height - yOffset1;
635 bool second = i >= xOffset2 && i < width - xOffset2 && j >= yOffset2 && j < height - yOffset2;
636 tcu::Vec4 expectedColor = blackColor;
637 if (first && second)
638 expectedColor = expectedColor1;
639 else if (first || second)
640 expectedColor = expectedColor2;
641
642 if (deFloatAbs(color.x() - expectedColor.x()) > threshold ||
643 deFloatAbs(color.y() - expectedColor.y()) > threshold ||
644 deFloatAbs(color.z() - expectedColor.z()) > threshold ||
645 deFloatAbs(color.w() - expectedColor.w()) > threshold)
646 {
647 log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be ("
648 << expectedColor << "), but was (" << color << ")" << tcu::TestLog::EndMessage;
649 return tcu::TestStatus::fail("Fail");
650 }
651 }
652 }
653
654 return tcu::TestStatus::pass("Pass");
655 }
656
657 class ShaderObjectBindingDrawCase : public vkt::TestCase
658 {
659 public:
ShaderObjectBindingDrawCase(tcu::TestContext & testCtx,const std::string & name,const BindingDrawParams & params)660 ShaderObjectBindingDrawCase(tcu::TestContext &testCtx, const std::string &name, const BindingDrawParams ¶ms)
661 : vkt::TestCase(testCtx, name)
662 , m_params(params)
663 {
664 }
~ShaderObjectBindingDrawCase(void)665 virtual ~ShaderObjectBindingDrawCase(void)
666 {
667 }
668
669 void checkSupport(vkt::Context &context) const override;
670 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const671 TestInstance *createInstance(Context &context) const override
672 {
673 return new ShaderObjectBindingDrawInstance(context, m_params);
674 }
675
676 private:
677 BindingDrawParams m_params;
678 };
679
checkSupport(Context & context) const680 void ShaderObjectBindingDrawCase::checkSupport(Context &context) const
681 {
682 context.requireDeviceFunctionality("VK_EXT_shader_object");
683
684 if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
685 m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ||
686 m_params.binaryStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
687 m_params.binaryStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
688 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
689
690 if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT || m_params.binaryStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
691 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
692 }
693
initPrograms(vk::SourceCollections & programCollection) const694 void ShaderObjectBindingDrawCase::initPrograms(vk::SourceCollections &programCollection) const
695 {
696 vk::addBasicShaderObjectShaders(programCollection);
697
698 std::stringstream passThroughGeom;
699 std::stringstream blendFrag;
700 std::stringstream vertAlt;
701 std::stringstream geomAlt;
702 std::stringstream tescAlt;
703 std::stringstream teseAlt;
704 std::stringstream fragAlt;
705 std::stringstream vertNoTess;
706 std::stringstream vertNoGeom;
707 std::stringstream vertNoTessGeom;
708 std::stringstream vertAltNoTess;
709 std::stringstream vertAltNoGeom;
710 std::stringstream vertAltNoTessGeom;
711
712 vertNoTess << "#version 450\n"
713 << "void main() {\n"
714 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
715 << " gl_Position = vec4((pos.x - 0.5f) * 1.5f, pos.y - 0.5f, 0.0f, 1.0f);\n"
716 << "}\n";
717
718 vertNoGeom << "#version 450\n"
719 << "void main() {\n"
720 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
721 << " gl_Position = vec4(pos.x - 0.5f, (pos.y - 0.5f) * 1.5f, 0.0f, 1.0f);\n"
722 << "}\n";
723
724 vertNoTessGeom << "#version 450\n"
725 << "void main() {\n"
726 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
727 << " gl_Position = vec4((pos - 0.5f) * 1.5f, 0.0f, 1.0f);\n"
728 << "}\n";
729
730 passThroughGeom << "#version 450\n"
731 << "layout(triangles) in;\n"
732 << "layout(triangle_strip, max_vertices = 4) out;\n"
733 << "\n"
734 << "void main(void)\n"
735 << "{\n"
736 << " gl_Position = gl_in[0].gl_Position;\n"
737 << " EmitVertex();\n"
738 << " gl_Position = gl_in[1].gl_Position;\n"
739 << " EmitVertex();\n"
740 << " gl_Position = gl_in[2].gl_Position;\n"
741 << " EmitVertex();\n"
742 << " EndPrimitive();\n"
743 << "}\n";
744
745 blendFrag << "#version 450\n"
746 << "layout (location=0) out vec4 outColor;\n"
747 << "void main() {\n"
748 << " outColor = vec4(0.5f, 0.5f, 0.5f, 0.5f);\n"
749 << "}\n";
750
751 vertAlt << "#version 450\n";
752 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
753 vertAlt << "layout (location = 0) out vec4 color;\n";
754 vertAlt << "void main() {\n"
755 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
756 << " gl_Position = vec4((pos - 0.5f) * 2, 0.0f, 1.0f);\n";
757 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
758 vertAlt << "color = vec4(1.0f);\n";
759 vertAlt << "}\n";
760
761 vertAltNoTess << "#version 450\n";
762 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
763 vertAltNoTess << "layout (location = 0) out vec4 color;\n";
764 vertAltNoTess << "void main() {\n"
765 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
766 << " gl_Position = vec4((pos.x - 0.5f) * 2.0f * 1.5f, (pos.y - 0.5f) * 2.0f, 0.0f, 1.0f);\n";
767 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
768 vertAltNoTess << " color = vec4(1.0f);\n";
769 vertAltNoTess << "}\n";
770
771 vertAltNoGeom << "#version 450\n";
772 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
773 vertAltNoGeom << "layout (location = 0) out vec4 color;\n";
774 vertAltNoGeom << "void main() {\n"
775 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
776 << " gl_Position = vec4((pos.x - 0.5f) * 2.0f, (pos.y - 0.5f) * 2.0f * 1.5f, 0.0f, 1.0f);\n";
777 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
778 vertAltNoGeom << " color = vec4(1.0f);\n";
779 vertAltNoGeom << "}\n";
780
781 vertAltNoTessGeom << "#version 450\n";
782 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
783 vertAltNoTessGeom << "layout (location = 0) out vec4 color;\n";
784 vertAltNoTessGeom << "void main() {\n"
785 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
786 << " gl_Position = vec4((pos - 0.5f) * 2 * 1.5f, 0.0f, 1.0f);\n";
787 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
788 vertAltNoTessGeom << " color = vec4(1.0f);\n";
789 vertAltNoTessGeom << "}\n";
790
791 tescAlt << "#version 450\n"
792 << "\n"
793 << "layout(vertices = 4) out;\n";
794 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
795 tescAlt << "layout (location = 0) out vec4 color[];\n";
796 tescAlt << "\n"
797 << "void main (void)\n"
798 << "{\n"
799 << " if (gl_InvocationID == 0) {\n"
800 << " gl_TessLevelInner[0] = 1.0;\n"
801 << " gl_TessLevelInner[1] = 1.0;\n"
802 << " gl_TessLevelOuter[0] = 1.0;\n"
803 << " gl_TessLevelOuter[1] = 1.0;\n"
804 << " gl_TessLevelOuter[2] = 1.0;\n"
805 << " gl_TessLevelOuter[3] = 1.0;\n"
806 << " }\n"
807 << " vec4 pos = gl_in[gl_InvocationID].gl_Position;\n"
808 << " pos.xy *= 0.5f;\n"
809 << " gl_out[gl_InvocationID].gl_Position = pos;\n";
810 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
811 tescAlt << " color[gl_InvocationID] = vec4(1.0f);\n";
812 tescAlt << "}\n";
813
814 teseAlt << "#version 450\n"
815 << "\n"
816 << "layout(quads, equal_spacing) in;\n";
817 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
818 teseAlt << "layout (location = 0) out vec4 color;\n";
819 teseAlt << "\n"
820 << "void main (void)\n"
821 << "{\n"
822 << " float u = gl_TessCoord.x;\n"
823 << " float v = gl_TessCoord.y;\n"
824 << " float omu = 1.0f - u;\n"
825 << " float omv = 1.0f - v;\n"
826 << " gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * "
827 "gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
828 << " gl_Position.x *= 0.5f;\n";
829 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
830 teseAlt << " color = vec4(1.0f);\n";
831 teseAlt << "}\n";
832
833 geomAlt << "#version 450\n"
834 << "layout(triangles) in;\n"
835 << "layout(triangle_strip, max_vertices = 4) out;\n";
836 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
837 geomAlt << "layout (location = 0) out vec4 color;\n";
838 geomAlt << "\n"
839 << "void main(void)\n"
840 << "{\n"
841 << " gl_Position = gl_in[0].gl_Position;\n"
842 << " gl_Position.y *= 0.5f;\n"
843 << " EmitVertex();\n"
844 << " gl_Position = gl_in[1].gl_Position;\n"
845 << " gl_Position.y *= 0.5f;\n"
846 << " EmitVertex();\n"
847 << " gl_Position = gl_in[2].gl_Position;\n"
848 << " gl_Position.y *= 0.5f;\n"
849 << " EmitVertex();\n"
850 << " EndPrimitive();\n";
851 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
852 geomAlt << " color = vec4(1.0f);\n";
853 geomAlt << "}\n";
854
855 fragAlt << "#version 450\n"
856 << "layout (location=0) out vec4 outColor;\n";
857 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
858 fragAlt << "layout (location = 1) out vec4 color;\n";
859 fragAlt << "void main() {\n"
860 << " outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
861 if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
862 fragAlt << "color = vec4(1.0f);\n";
863 fragAlt << "}\n";
864
865 programCollection.glslSources.add("passThroughGeom") << glu::GeometrySource(passThroughGeom.str());
866 programCollection.glslSources.add("blendFrag") << glu::FragmentSource(blendFrag.str());
867 programCollection.glslSources.add("vertAlt") << glu::VertexSource(vertAlt.str());
868 programCollection.glslSources.add("tescAlt") << glu::TessellationControlSource(tescAlt.str());
869 programCollection.glslSources.add("teseAlt") << glu::TessellationEvaluationSource(teseAlt.str());
870 programCollection.glslSources.add("geomAlt") << glu::GeometrySource(geomAlt.str());
871 programCollection.glslSources.add("fragAlt") << glu::FragmentSource(fragAlt.str());
872
873 programCollection.glslSources.add("vertNoTess") << glu::VertexSource(vertNoTess.str());
874 programCollection.glslSources.add("vertNoGeom") << glu::VertexSource(vertNoGeom.str());
875 programCollection.glslSources.add("vertNoTessGeom") << glu::VertexSource(vertNoTessGeom.str());
876 programCollection.glslSources.add("vertAltNoTess") << glu::VertexSource(vertAltNoTess.str());
877 programCollection.glslSources.add("vertAltNoGeom") << glu::VertexSource(vertAltNoGeom.str());
878 programCollection.glslSources.add("vertAltNoTessGeom") << glu::VertexSource(vertAltNoTessGeom.str());
879 }
880
881 class ShaderObjectBindingInstance : public vkt::TestInstance
882 {
883 public:
ShaderObjectBindingInstance(Context & context,const BindingParams & params)884 ShaderObjectBindingInstance(Context &context, const BindingParams ¶ms)
885 : vkt::TestInstance(context)
886 , m_params(params)
887 {
888 }
~ShaderObjectBindingInstance(void)889 virtual ~ShaderObjectBindingInstance(void)
890 {
891 }
892
893 tcu::TestStatus iterate(void) override;
894
895 private:
896 BindingParams m_params;
897 };
898
iterate(void)899 tcu::TestStatus ShaderObjectBindingInstance::iterate(void)
900 {
901 const vk::VkInstance instance = m_context.getInstance();
902 const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
903 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
904 const vk::VkDevice device = m_context.getDevice();
905 const vk::VkQueue queue = m_context.getUniversalQueue();
906 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
907
908 const auto meshShaderFeatures = m_context.getMeshShaderFeaturesEXT();
909 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
910 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
911 const auto &binaries = m_context.getBinaryCollection();
912
913 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
914 vk::DescriptorSetLayoutBuilder()
915 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
916 vk::VK_SHADER_STAGE_COMPUTE_BIT |
917 ((m_params.useMeshShaders && meshShaderFeatures.meshShader) ?
918 vk::VkShaderStageFlags{vk::VK_SHADER_STAGE_MESH_BIT_EXT} :
919 vk::VkShaderStageFlags{0}))
920 .build(vk, device));
921
922 vk::Move<vk::VkShaderEXT> vertShader =
923 vk::createShader(vk, device,
924 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vert"),
925 tessellationSupported, geometrySupported));
926 vk::Move<vk::VkShaderEXT> tescShader;
927 vk::Move<vk::VkShaderEXT> teseShader;
928 vk::Move<vk::VkShaderEXT> geomShader;
929 vk::Move<vk::VkShaderEXT> fragShader =
930 vk::createShader(vk, device,
931 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"),
932 tessellationSupported, geometrySupported));
933 vk::Move<vk::VkShaderEXT> compShader =
934 vk::createShader(vk, device,
935 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_COMPUTE_BIT, binaries.get("comp"),
936 tessellationSupported, geometrySupported, &*descriptorSetLayout));
937 vk::Move<vk::VkShaderEXT> taskShader;
938 vk::Move<vk::VkShaderEXT> meshShader;
939 if (m_context.getDeviceFeatures().tessellationShader)
940 {
941 tescShader =
942 vk::createShader(vk, device,
943 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
944 binaries.get("tesc"), tessellationSupported, geometrySupported));
945 teseShader =
946 vk::createShader(vk, device,
947 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
948 binaries.get("tese"), tessellationSupported, geometrySupported));
949 }
950 if (m_context.getDeviceFeatures().geometryShader)
951 {
952 geomShader = vk::createShader(vk, device,
953 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, binaries.get("geom"),
954 tessellationSupported, geometrySupported));
955 }
956 if (m_params.useMeshShaders)
957 {
958 if (meshShaderFeatures.taskShader)
959 taskShader =
960 vk::createShader(vk, device,
961 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task"),
962 tessellationSupported, geometrySupported));
963 if (meshShaderFeatures.meshShader)
964 meshShader = vk::createShader(vk, device,
965 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT,
966 binaries.get("mesh"), tessellationSupported,
967 geometrySupported, &*descriptorSetLayout));
968 }
969
970 const vk::Move<vk::VkCommandPool> cmdPool(
971 vk::createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
972 const vk::Move<vk::VkCommandBuffer> cmdBuffer(
973 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
974
975 const bool bind[] = {true, false};
976 for (const auto bindVert : bind)
977 {
978 for (const auto bindTesc : bind)
979 {
980 for (const auto bindTese : bind)
981 {
982 for (const auto bindGeom : bind)
983 {
984 for (const auto bindFrag : bind)
985 {
986 for (const auto bindComp : bind)
987 {
988 for (const auto bindTask : bind)
989 {
990 if (bindVert && bindTask)
991 continue;
992 for (const auto bindMesh : bind)
993 {
994 if (bindVert && bindMesh)
995 continue;
996 std::vector<vk::VkShaderStageFlagBits> stages = {
997 vk::VK_SHADER_STAGE_VERTEX_BIT,
998 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
999 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1000 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1001 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1002 vk::VK_SHADER_STAGE_COMPUTE_BIT,
1003 vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1004 vk::VK_SHADER_STAGE_TASK_BIT_EXT,
1005 };
1006 std::vector<vk::VkShaderEXT> shaders = {
1007 bindVert ? *vertShader : VK_NULL_HANDLE,
1008 (bindTesc && m_context.getDeviceFeatures().tessellationShader) ? *tescShader :
1009 VK_NULL_HANDLE,
1010 (bindTese && m_context.getDeviceFeatures().tessellationShader) ? *teseShader :
1011 VK_NULL_HANDLE,
1012 (bindGeom && m_context.getDeviceFeatures().geometryShader) ? *geomShader :
1013 VK_NULL_HANDLE,
1014 bindFrag ? *fragShader : VK_NULL_HANDLE,
1015 bindComp ? *compShader : VK_NULL_HANDLE,
1016 bindMesh ? *meshShader : VK_NULL_HANDLE,
1017 bindTask ? *taskShader : VK_NULL_HANDLE,
1018 };
1019 uint32_t count = 6u;
1020 if (meshShaderFeatures.meshShader)
1021 ++count;
1022 if (meshShaderFeatures.taskShader)
1023 ++count;
1024 vk::beginCommandBuffer(vk, *cmdBuffer);
1025 vk.cmdBindShadersEXT(*cmdBuffer, count, stages.data(), shaders.data());
1026 vk::endCommandBuffer(vk, *cmdBuffer);
1027 vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1028 }
1029 }
1030 }
1031 }
1032 }
1033 }
1034 }
1035 }
1036
1037 if (m_context.getDeviceFeatures().tessellationShader && m_context.getDeviceFeatures().geometryShader &&
1038 meshShaderFeatures.taskShader && meshShaderFeatures.meshShader)
1039 {
1040 std::vector<vk::VkShaderStageFlagBits> stages = {
1041 vk::VK_SHADER_STAGE_VERTEX_BIT,
1042 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1043 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1044 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1045 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1046 vk::VK_SHADER_STAGE_COMPUTE_BIT,
1047 vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1048 vk::VK_SHADER_STAGE_TASK_BIT_EXT,
1049 };
1050 vk::beginCommandBuffer(vk, *cmdBuffer);
1051 vk.cmdBindShadersEXT(*cmdBuffer, (uint32_t)stages.size(), stages.data(), DE_NULL);
1052 vk::endCommandBuffer(vk, *cmdBuffer);
1053 vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1054 }
1055
1056 return tcu::TestStatus::pass("pass");
1057 }
1058
1059 class MeshShaderObjectBindingInstance : public vkt::TestInstance
1060 {
1061 public:
MeshShaderObjectBindingInstance(Context & context,const MeshBindingDrawParams & params)1062 MeshShaderObjectBindingInstance(Context &context, const MeshBindingDrawParams ¶ms)
1063 : vkt::TestInstance(context)
1064 , m_params(params)
1065 {
1066 }
~MeshShaderObjectBindingInstance(void)1067 virtual ~MeshShaderObjectBindingInstance(void)
1068 {
1069 }
1070
1071 tcu::TestStatus iterate(void) override;
1072
1073 private:
1074 MeshBindingDrawParams m_params;
1075 };
1076
iterate(void)1077 tcu::TestStatus MeshShaderObjectBindingInstance::iterate(void)
1078 {
1079 const vk::VkInstance instance = m_context.getInstance();
1080 const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
1081 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1082 const vk::VkDevice device = m_context.getDevice();
1083 const vk::VkQueue queue = m_context.getUniversalQueue();
1084 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1085 auto &alloc = m_context.getDefaultAllocator();
1086 tcu::TestLog &log = m_context.getTestContext().getLog();
1087 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(
1088 m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
1089
1090 vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
1091 const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1092
1093 const vk::VkImageCreateInfo createInfo = {
1094 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
1095 DE_NULL, // const void* pNext
1096 0u, // VkImageCreateFlags flags
1097 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType
1098 colorAttachmentFormat, // VkFormat format
1099 {32, 32, 1}, // VkExtent3D extent
1100 1u, // uint32_t mipLevels
1101 1u, // uint32_t arrayLayers
1102 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1103 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
1104 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
1105 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
1106 0, // uint32_t queueFamilyIndexCount
1107 DE_NULL, // const uint32_t* pQueueFamilyIndices
1108 vk::VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
1109 };
1110
1111 de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
1112 new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
1113 const auto imageView =
1114 vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
1115 const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
1116
1117 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
1118 vk::DescriptorSetLayoutBuilder()
1119 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
1120 vk::VK_SHADER_STAGE_TASK_BIT_EXT | vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1121 .build(vk, device));
1122
1123 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
1124 vk::DescriptorPoolBuilder()
1125 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1126 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1127
1128 const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 4;
1129 const vk::Unique<vk::VkDescriptorSet> descriptorSet(
1130 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1131 const vk::BufferWithMemory outputBuffer(
1132 vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
1133 vk::MemoryRequirement::HostVisible);
1134
1135 const vk::VkDescriptorBufferInfo descriptorInfo =
1136 vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
1137 vk::DescriptorSetUpdateBuilder()
1138 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
1139 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1140 .update(vk, device);
1141
1142 const auto pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
1143
1144 const auto &binaries = m_context.getBinaryCollection();
1145 const auto taskShader1 =
1146 vk::createShader(vk, device,
1147 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task1"), false, false,
1148 &*descriptorSetLayout));
1149 const auto taskShader2 =
1150 vk::createShader(vk, device,
1151 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task2"), false, false,
1152 &*descriptorSetLayout));
1153 const auto meshShader1 =
1154 vk::createShader(vk, device,
1155 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, binaries.get("mesh1"), false, false,
1156 &*descriptorSetLayout));
1157 const auto meshShader2 =
1158 vk::createShader(vk, device,
1159 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, binaries.get("mesh2"), false, false,
1160 &*descriptorSetLayout));
1161 const auto fragShader =
1162 vk::createShader(vk, device,
1163 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"), false, false,
1164 &*descriptorSetLayout));
1165
1166 const vk::Move<vk::VkCommandPool> cmdPool(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
1167 const vk::Move<vk::VkCommandBuffer> cmdBuffer(
1168 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1169
1170 const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
1171
1172 vk::beginCommandBuffer(vk, *cmdBuffer);
1173
1174 vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(
1175 vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
1176 vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1177 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1178 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u,
1179 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
1180 &preImageBarrier);
1181
1182 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
1183 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
1184 vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1185 true);
1186 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1,
1187 &descriptorSet.get(), 0, DE_NULL);
1188
1189 std::vector<vk::VkShaderStageFlagBits> nullStages = {
1190 vk::VK_SHADER_STAGE_VERTEX_BIT,
1191 };
1192 if (m_context.getDeviceFeatures().tessellationShader)
1193 {
1194 nullStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
1195 nullStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
1196 }
1197 if (m_context.getDeviceFeatures().geometryShader)
1198 {
1199 nullStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
1200 }
1201 for (const auto &stage : nullStages)
1202 {
1203 vk::VkShaderEXT shader = VK_NULL_HANDLE;
1204 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
1205 }
1206
1207 const vk::VkShaderStageFlagBits stages[] = {
1208 vk::VK_SHADER_STAGE_TASK_BIT_EXT,
1209 vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1210 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1211 };
1212 vk::VkShaderEXT shaders[] = {
1213 *taskShader1,
1214 *meshShader1,
1215 *fragShader,
1216 };
1217 vk.cmdBindShadersEXT(*cmdBuffer, 3u, stages, shaders);
1218 vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
1219 vk::endRendering(vk, *cmdBuffer);
1220
1221 vk::VkBufferMemoryBarrier shaderBufferBarrier = vk::makeBufferMemoryBarrier(
1222 vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, *outputBuffer, 0u, bufferSizeBytes);
1223 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1224 (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier *)DE_NULL, 1u, &shaderBufferBarrier,
1225 0u, (const vk::VkImageMemoryBarrier *)DE_NULL);
1226
1227 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
1228 vk::VK_ATTACHMENT_LOAD_OP_LOAD);
1229 if (m_params.stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
1230 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stages[0], &*taskShader2);
1231 else if (m_params.stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1232 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stages[1], &*meshShader2);
1233 vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
1234
1235 vk::endRendering(vk, *cmdBuffer);
1236
1237 vk::VkImageMemoryBarrier postImageBarrier =
1238 vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
1239 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1240 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1241 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
1242 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
1243 &postImageBarrier);
1244 vk::VkBufferMemoryBarrier bufferBarrier = vk::makeBufferMemoryBarrier(
1245 vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0u, bufferSizeBytes);
1246 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
1247 (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier *)DE_NULL, 1u, &bufferBarrier, 0u,
1248 (const vk::VkImageMemoryBarrier *)DE_NULL);
1249 vk::endCommandBuffer(vk, *cmdBuffer);
1250
1251 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1252
1253 const vk::Allocation &outputBufferAllocation = outputBuffer.getAllocation();
1254 invalidateAlloc(vk, device, outputBufferAllocation);
1255
1256 const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
1257
1258 if (m_params.stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
1259 {
1260 if (bufferPtr[0] != 4u || bufferPtr[1] != 5u || bufferPtr[2] != 2u || bufferPtr[3] != 3u)
1261 {
1262 log << tcu::TestLog::Message << "Buffer values were expected to be [4, 5, 2, 3], but were[" << bufferPtr[0]
1263 << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", "
1264 << "]" << tcu::TestLog::EndMessage;
1265 return tcu::TestStatus::fail("Fail");
1266 }
1267 }
1268 else if (m_params.stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1269 {
1270 if (bufferPtr[0] != 0u || bufferPtr[1] != 1u || bufferPtr[2] != 6u || bufferPtr[3] != 7u)
1271 {
1272 log << tcu::TestLog::Message << "Buffer values were expected to be [0, 1, 6, 7], but were[" << bufferPtr[0]
1273 << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", "
1274 << "]" << tcu::TestLog::EndMessage;
1275 return tcu::TestStatus::fail("Fail");
1276 }
1277 }
1278
1279 return tcu::TestStatus::pass("pass");
1280 }
1281
1282 class MeshShaderObjectBindingCase : public vkt::TestCase
1283 {
1284 public:
MeshShaderObjectBindingCase(tcu::TestContext & testCtx,const std::string & name,const MeshBindingDrawParams & params)1285 MeshShaderObjectBindingCase(tcu::TestContext &testCtx, const std::string &name, const MeshBindingDrawParams ¶ms)
1286 : vkt::TestCase(testCtx, name)
1287 , m_params(params)
1288 {
1289 }
~MeshShaderObjectBindingCase(void)1290 virtual ~MeshShaderObjectBindingCase(void)
1291 {
1292 }
1293
1294 void checkSupport(vkt::Context &context) const override;
1295 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1296 TestInstance *createInstance(Context &context) const override
1297 {
1298 return new MeshShaderObjectBindingInstance(context, m_params);
1299 }
1300
1301 private:
1302 MeshBindingDrawParams m_params;
1303 };
1304
checkSupport(vkt::Context & context) const1305 void MeshShaderObjectBindingCase::checkSupport(vkt::Context &context) const
1306 {
1307 context.requireDeviceFunctionality("VK_EXT_shader_object");
1308 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1309 const auto &features = context.getMeshShaderFeaturesEXT();
1310 if (!features.taskShader)
1311 TCU_THROW(NotSupportedError, "Task shaders not supported");
1312 if (!features.meshShader)
1313 TCU_THROW(NotSupportedError, "Mesh shaders not supported");
1314 }
1315
initPrograms(vk::SourceCollections & programCollection) const1316 void MeshShaderObjectBindingCase::initPrograms(vk::SourceCollections &programCollection) const
1317 {
1318 std::stringstream task1;
1319 std::stringstream task2;
1320 std::stringstream mesh1;
1321 std::stringstream mesh2;
1322 std::stringstream frag;
1323
1324 task1 << "#version 450\n"
1325 << "#extension GL_EXT_mesh_shader : enable\n"
1326 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1327 << "layout(set = 0, binding = 0) buffer Output {\n"
1328 << " uint values[4];\n"
1329 << "} buffer_out;\n\n"
1330 << "void main ()\n"
1331 << "{\n"
1332 << " buffer_out.values[0] = 0u;\n"
1333 << " buffer_out.values[1] = 1u;\n"
1334 << " EmitMeshTasksEXT(1u, 1u, 1u);\n"
1335 << "}\n";
1336
1337 task2 << "#version 450\n"
1338 << "#extension GL_EXT_mesh_shader : enable\n"
1339 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1340 << "layout(set = 0, binding = 0) buffer Output {\n"
1341 << " uint values[4];\n"
1342 << "} buffer_out;\n\n"
1343 << "void main ()\n"
1344 << "{\n"
1345 << " buffer_out.values[0] = 4u;\n"
1346 << " buffer_out.values[1] = 5u;\n"
1347 << " EmitMeshTasksEXT(1u, 1u, 1u);\n"
1348 << "}\n";
1349
1350 mesh1 << "#version 460\n"
1351 << "#extension GL_EXT_mesh_shader : require\n"
1352 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1353 << "layout(max_vertices = 3) out;\n"
1354 << "layout(max_primitives = 1) out;\n"
1355 << "layout(triangles) out;\n"
1356 << "layout(set = 0, binding = 0) buffer Output {\n"
1357 << " uint values[4];\n"
1358 << "} buffer_out;\n\n"
1359 << "void main() {\n"
1360 << " SetMeshOutputsEXT(3, 1);\n"
1361 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1362 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1363 << " gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0, 3.0, 0.0f, 1.0f);\n"
1364 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1365 << " buffer_out.values[2] = 2u;\n"
1366 << " buffer_out.values[3] = 3u;\n"
1367 << "}\n";
1368
1369 mesh2 << "#version 460\n"
1370 << "#extension GL_EXT_mesh_shader : require\n"
1371 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1372 << "layout(max_vertices = 3) out;\n"
1373 << "layout(max_primitives = 1) out;\n"
1374 << "layout(triangles) out;\n"
1375 << "layout(set = 0, binding = 0) buffer Output {\n"
1376 << " uint values[4];\n"
1377 << "} buffer_out;\n\n"
1378 << "void main() {\n"
1379 << " SetMeshOutputsEXT(3, 1);\n"
1380 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1381 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1382 << " gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0, 3.0, 0.0f, 1.0f);\n"
1383 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1384 << " buffer_out.values[2] = 6u;\n"
1385 << " buffer_out.values[3] = 7u;\n"
1386 << "}\n";
1387
1388 frag << "#version 450\n"
1389 << "layout (location=0) out vec4 outColor;\n"
1390 << "void main() {\n"
1391 << " outColor = vec4(1.0f);\n"
1392 << "}\n";
1393
1394 programCollection.glslSources.add("task1")
1395 << glu::TaskSource(task1.str())
1396 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1397 programCollection.glslSources.add("task2")
1398 << glu::TaskSource(task2.str())
1399 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1400 programCollection.glslSources.add("mesh1")
1401 << glu::MeshSource(mesh1.str())
1402 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1403 programCollection.glslSources.add("mesh2")
1404 << glu::MeshSource(mesh2.str())
1405 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1406 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1407 }
1408
1409 class ShaderObjectBindingCase : public vkt::TestCase
1410 {
1411 public:
ShaderObjectBindingCase(tcu::TestContext & testCtx,const std::string & name,const BindingParams & params)1412 ShaderObjectBindingCase(tcu::TestContext &testCtx, const std::string &name, const BindingParams ¶ms)
1413 : vkt::TestCase(testCtx, name)
1414 , m_params(params)
1415 {
1416 }
~ShaderObjectBindingCase(void)1417 virtual ~ShaderObjectBindingCase(void)
1418 {
1419 }
1420
1421 void checkSupport(vkt::Context &context) const override;
1422 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1423 TestInstance *createInstance(Context &context) const override
1424 {
1425 return new ShaderObjectBindingInstance(context, m_params);
1426 }
1427
1428 private:
1429 BindingParams m_params;
1430 };
1431
checkSupport(Context & context) const1432 void ShaderObjectBindingCase::checkSupport(Context &context) const
1433 {
1434 context.requireDeviceFunctionality("VK_EXT_shader_object");
1435 if (m_params.useMeshShaders)
1436 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1437 }
1438
initPrograms(vk::SourceCollections & programCollection) const1439 void ShaderObjectBindingCase::initPrograms(vk::SourceCollections &programCollection) const
1440 {
1441 vk::addBasicShaderObjectShaders(programCollection);
1442
1443 if (m_params.useMeshShaders)
1444 {
1445 std::stringstream task;
1446 std::stringstream mesh;
1447
1448 task << "#version 450\n"
1449 << "#extension GL_EXT_mesh_shader : enable\n"
1450 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1451 << "void main ()\n"
1452 << "{\n"
1453 << " EmitMeshTasksEXT(1u, 1u, 1u);\n"
1454 << "}\n";
1455
1456 mesh << "#version 460\n"
1457 << "#extension GL_EXT_mesh_shader : require\n"
1458 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1459 << "layout(max_vertices = 3) out;\n"
1460 << "layout(max_primitives = 1) out;\n"
1461 << "layout(triangles) out;\n"
1462 << "layout(set = 0, binding = 0) buffer Output {\n"
1463 << " uint values[4];\n"
1464 << "} buffer_out;\n\n"
1465 << "void main() {\n"
1466 << " SetMeshOutputsEXT(3, 1);\n"
1467 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1468 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1469 << " gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0, 3.0, 0.0f, 1.0f);\n"
1470 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1471 << " buffer_out.values[0] = 0u;\n"
1472 << " buffer_out.values[1] = 1u;\n"
1473 << " buffer_out.values[2] = 2u;\n"
1474 << " buffer_out.values[3] = 3u;\n"
1475 << "}\n";
1476
1477 programCollection.glslSources.add("task")
1478 << glu::TaskSource(task.str())
1479 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1480 programCollection.glslSources.add("mesh")
1481 << glu::MeshSource(mesh.str())
1482 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1483 }
1484 }
1485
1486 } // namespace
1487
createShaderObjectBindingTests(tcu::TestContext & testCtx)1488 tcu::TestCaseGroup *createShaderObjectBindingTests(tcu::TestContext &testCtx)
1489 {
1490 de::MovePtr<tcu::TestCaseGroup> bindingGroup(new tcu::TestCaseGroup(testCtx, "binding"));
1491
1492 BindingDrawParams params;
1493 params.testType = PASSTHROUGH_GEOM;
1494 params.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1495 params.unusedOutputs = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
1496 params.binaryStage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
1497 params.bindUnsupported = false;
1498 params.setStateAfter = false;
1499 params.unbindWithNullpShaders = false;
1500
1501 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "unbind_passthrough_geom", params));
1502
1503 const struct
1504 {
1505 vk::VkShaderStageFlagBits stage;
1506 const char *name;
1507 } stageTest[] = {
1508 {vk::VK_SHADER_STAGE_VERTEX_BIT, "vert"},
1509 {vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc"},
1510 {vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tese"},
1511 {vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom"},
1512 {vk::VK_SHADER_STAGE_FRAGMENT_BIT, "frag"},
1513 };
1514 params.testType = SWAP;
1515 for (const auto &stage : stageTest)
1516 {
1517 params.stage = stage.stage;
1518 params.unusedOutputs = vk::VK_SHADER_STAGE_ALL; // Unused
1519 params.binaryStage = vk::VK_SHADER_STAGE_ALL; // Unused
1520 params.setStateAfter = false;
1521 std::string name = "swap_" + std::string(stage.name);
1522 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name.c_str(), params));
1523 for (const auto &unusedOutputs : stageTest)
1524 {
1525 for (const auto &binaryStage : stageTest)
1526 {
1527 for (uint32_t i = 0; i < 2; ++i)
1528 {
1529 params.stage = stage.stage;
1530 params.unusedOutputs = unusedOutputs.stage;
1531 params.binaryStage = binaryStage.stage;
1532 params.setStateAfter = (bool)i;
1533 std::string name2 = "swap_" + std::string(stage.name) + "_unused_output_" +
1534 std::string(unusedOutputs.name) + "_binary_" + std::string(binaryStage.name) +
1535 "_" + ((i == 0) ? "before" : "after");
1536 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name2.c_str(), params));
1537 }
1538 }
1539 }
1540 }
1541
1542 params.unusedOutputs = vk::VK_SHADER_STAGE_ALL;
1543 params.binaryStage = vk::VK_SHADER_STAGE_ALL;
1544
1545 const struct
1546 {
1547 vk::VkShaderStageFlagBits stage;
1548 const char *name;
1549 } unbindStageTest[] = {
1550 {vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc"},
1551 {vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom"},
1552 };
1553 params.testType = UNBIND;
1554 params.setStateAfter = false;
1555 for (const auto &stage : unbindStageTest)
1556 {
1557 for (uint32_t i = 0; i < 2; ++i)
1558 {
1559 params.stage = stage.stage;
1560 params.unbindWithNullpShaders = (bool)i;
1561 std::string name = "unbind_" + std::string(stage.name) +
1562 (params.unbindWithNullpShaders ? "_null_pshaders" : "_null_handle");
1563 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name.c_str(), params));
1564 }
1565 }
1566
1567 const struct
1568 {
1569 vk::VkShaderStageFlagBits stage;
1570 const char *name;
1571 } meshStageTest[] = {
1572 {vk::VK_SHADER_STAGE_TASK_BIT_EXT, "task"},
1573 {vk::VK_SHADER_STAGE_MESH_BIT_EXT, "mesh"},
1574 };
1575
1576 for (const auto &stage : meshStageTest)
1577 {
1578 MeshBindingDrawParams meshParams;
1579 meshParams.stage = stage.stage;
1580 std::string name = "mesh_swap_" + std::string(stage.name);
1581 bindingGroup->addChild(new MeshShaderObjectBindingCase(testCtx, name.c_str(), meshParams));
1582 }
1583
1584 params.testType = DISABLED;
1585 params.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1586 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_geom", params));
1587 params.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1588 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_tess", params));
1589 params.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1590 params.bindUnsupported = true;
1591 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_geom_bind", params));
1592 params.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1593 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_tess_bind", params));
1594 params.testType = DRAW_DISPATCH_DRAW;
1595 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "draw_dispatch_draw", params));
1596 params.testType = DISPATCH_DRAW_DISPATCH;
1597 bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "dispatch_draw_dispatch", params));
1598
1599 BindingParams bindingParams;
1600 bindingParams.useMeshShaders = false;
1601 bindingGroup->addChild(new ShaderObjectBindingCase(testCtx, "bindings", bindingParams));
1602 bindingParams.useMeshShaders = true;
1603 bindingGroup->addChild(new ShaderObjectBindingCase(testCtx, "bindings_mesh_shaders", bindingParams));
1604
1605 return bindingGroup.release();
1606 }
1607
1608 } // namespace ShaderObject
1609 } // namespace vkt
1610