1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group Inc.
6 * Copyright (c) 2021 Valve Corporation.
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 Dynamic State tests mixing it with compute and transfer.
23 *//*--------------------------------------------------------------------*/
24 #include "vktDynamicStateComputeTests.hpp"
25 #include "vktCustomInstancesDevices.hpp"
26
27 #include "vkBufferWithMemory.hpp"
28 #include "vkObjUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkBarrierUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkTypeUtil.hpp"
33
34 #include "tcuCommandLine.hpp"
35 #include "tcuVector.hpp"
36
37 #include <vector>
38 #include <string>
39 #include <functional>
40 #include <map>
41 #include <sstream>
42 #include <cstring>
43 #include <iterator>
44 #include <numeric>
45 #include <memory>
46
47 namespace vkt
48 {
49 namespace DynamicState
50 {
51
52 namespace
53 {
54
55 using namespace vk;
56
57 // Additional objects needed to set a given dynamic state that need to exist beyond the state-setting call. Empty by default.
58 struct DynamicStateData
59 {
~DynamicStateDatavkt::DynamicState::__anond426403c0111::DynamicStateData60 virtual ~DynamicStateData() {}
61 };
62
63 // A vertex buffer and graphics pipeline are needed for vkCmdBindVertexBuffers2EXT().
64 struct BindVertexBuffersData : public DynamicStateData
65 {
66 private:
67 using BufferPtr = de::MovePtr<BufferWithMemory>;
68 using RenderPassPtr = Move<VkRenderPass>;
69 using LayoutPtr = Move<VkPipelineLayout>;
70 using ModulePtr = Move<VkShaderModule>;
71 using PipelinePtr = Move<VkPipeline>;
72
73 static constexpr deUint32 kWidth = 16u;
74 static constexpr deUint32 kHeight = 16u;
75
getExtentvkt::DynamicState::__anond426403c0111::BindVertexBuffersData76 VkExtent3D getExtent (void)
77 {
78 return makeExtent3D(kWidth, kHeight, 1u);
79 }
80
81 public:
BindVertexBuffersDatavkt::DynamicState::__anond426403c0111::BindVertexBuffersData82 BindVertexBuffersData(Context& ctx, VkDevice device)
83 : m_vertexBuffer ()
84 , m_dataSize (0u)
85 , m_vertexBufferSize (0ull)
86 , m_renderPass ()
87 , m_pipelineLayout ()
88 , m_vertexShader ()
89 , m_graphicsPipeline ()
90 {
91 const auto& vki = ctx.getInstanceInterface();
92 const auto phyDev = ctx.getPhysicalDevice();
93 const auto& vkd = ctx.getDeviceInterface();
94 auto& alloc = ctx.getDefaultAllocator();
95
96 // Vertex buffer.
97 tcu::Vec4 vertex (0.f, 0.f, 0.f, 1.f);
98 m_dataSize = sizeof(vertex);
99 m_vertexBufferSize = de::roundUp(static_cast<VkDeviceSize>(m_dataSize), getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
100 const auto bufferInfo = makeBufferCreateInfo(m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
101
102 m_vertexBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, bufferInfo, MemoryRequirement::HostVisible));
103 auto& bufferAlloc = m_vertexBuffer->getAllocation();
104
105 deMemcpy(bufferAlloc.getHostPtr(), &vertex, m_dataSize);
106 flushAlloc(vkd, device, bufferAlloc);
107
108 // Empty render pass.
109 m_renderPass = makeRenderPass(vkd, device);
110
111 // Empty pipeline layout.
112 m_pipelineLayout = makePipelineLayout(vkd, device);
113
114 // Passthrough vertex shader.
115 m_vertexShader = createShaderModule(vkd, device, ctx.getBinaryCollection().get("vert"), 0u);
116
117 const auto extent = getExtent();
118 const std::vector<VkViewport> viewports (1, makeViewport(extent));
119 const std::vector<VkRect2D> scissors (1, makeRect2D(extent));
120 const VkDynamicState state = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;
121
122 const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
123 {
124 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
125 nullptr, // const void* pNext;
126 0u, // VkPipelineDynamicStateCreateFlags flags;
127 1u, // deUint32 dynamicStateCount;
128 &state, // const VkDynamicState* pDynamicStates;
129 };
130
131 // Graphics pipeline.
132 m_graphicsPipeline = makeGraphicsPipeline(vkd, device, m_pipelineLayout.get(),
133 m_vertexShader.get(), DE_NULL, DE_NULL, DE_NULL, DE_NULL,
134 m_renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
135 nullptr, nullptr, nullptr, nullptr, nullptr, &dynamicStateInfo);
136 }
137
getVertexBuffervkt::DynamicState::__anond426403c0111::BindVertexBuffersData138 const BufferWithMemory* getVertexBuffer () const
139 {
140 return m_vertexBuffer.get();
141 }
142
getDataSizevkt::DynamicState::__anond426403c0111::BindVertexBuffersData143 size_t getDataSize () const
144 {
145 return m_dataSize;
146 }
147
getPipelinevkt::DynamicState::__anond426403c0111::BindVertexBuffersData148 VkPipeline getPipeline () const
149 {
150 return m_graphicsPipeline.get();
151 }
152
~BindVertexBuffersDatavkt::DynamicState::__anond426403c0111::BindVertexBuffersData153 virtual ~BindVertexBuffersData() {}
154
155 private:
156 BufferPtr m_vertexBuffer;
157 size_t m_dataSize;
158 VkDeviceSize m_vertexBufferSize;
159 RenderPassPtr m_renderPass;
160 LayoutPtr m_pipelineLayout;
161 ModulePtr m_vertexShader;
162 PipelinePtr m_graphicsPipeline;
163 };
164
165 // Function that records a state-setting command in the given command buffer.
166 using RecordStateFunction = std::function<void(const DeviceInterface*, VkCommandBuffer, const DynamicStateData*)>;
167
168 // State-setting functions
setViewport(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)169 void setViewport (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
170 {
171 const VkViewport viewport =
172 {
173 0.0f, // float x;
174 0.0f, // float y;
175 1.0f, // float width;
176 1.0f, // float height;
177 0.0f, // float minDepth;
178 1.0f, // float maxDepth;
179 };
180 vkd->cmdSetViewport(cmdBuffer, 0u, 1u, &viewport);
181 }
182
setScissor(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)183 void setScissor (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
184 {
185 const VkRect2D scissor =
186 {
187 { 0, 0 }, // VkOffset2D offset;
188 { 1u, 1u }, // VkExtent2D extent;
189 };
190 vkd->cmdSetScissor(cmdBuffer, 0u, 1u, &scissor);
191 }
192
setLineWidth(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)193 void setLineWidth (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
194 {
195 vkd->cmdSetLineWidth(cmdBuffer, 1.0f);
196 }
197
setDepthBias(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)198 void setDepthBias (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
199 {
200 vkd->cmdSetDepthBias(cmdBuffer, 0.0f, 0.0f, 0.0f);
201 }
202
setBlendConstants(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)203 void setBlendConstants (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
204 {
205 const float blendConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
206 vkd->cmdSetBlendConstants(cmdBuffer, blendConstants);
207 }
208
setDepthBounds(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)209 void setDepthBounds (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
210 {
211 vkd->cmdSetDepthBounds(cmdBuffer, 0.0f, 1.0f);
212 }
213
setStencilCompareMask(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)214 void setStencilCompareMask (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
215 {
216 vkd->cmdSetStencilCompareMask(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
217 }
218
setStencilWriteMask(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)219 void setStencilWriteMask (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
220 {
221 vkd->cmdSetStencilWriteMask(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
222 }
223
setStencilReference(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)224 void setStencilReference (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
225 {
226 vkd->cmdSetStencilReference(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
227 }
228
setDiscardRectangle(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)229 void setDiscardRectangle (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
230 {
231 const VkRect2D rectangle =
232 {
233 { 0, 0 }, // VkOffset2D offset;
234 { 1u, 1u }, // VkExtent2D extent;
235 };
236 vkd->cmdSetDiscardRectangleEXT(cmdBuffer, 0u, 1u, &rectangle);
237 }
238
setSampleLocations(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)239 void setSampleLocations (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
240 {
241 const VkSampleLocationEXT locations[] =
242 {
243 { 0.5f, 0.5f },
244 { 0.5f, 1.5f },
245 { 1.5f, 0.5f },
246 { 1.5f, 1.5f },
247 };
248 const VkSampleLocationsInfoEXT info =
249 {
250 VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, // VkStructureType sType;
251 nullptr, // const void* pNext;
252 VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits sampleLocationsPerPixel;
253 { 1u, 1u }, // VkExtent2D sampleLocationGridSize;
254 4u, // deUint32 sampleLocationsCount;
255 locations, // const VkSampleLocationEXT* pSampleLocations;
256 };
257 vkd->cmdSetSampleLocationsEXT(cmdBuffer, &info);
258 }
259
260 #ifndef CTS_USES_VULKANSC
setRTPipelineStatckSize(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)261 void setRTPipelineStatckSize (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
262 {
263 vkd->cmdSetRayTracingPipelineStackSizeKHR(cmdBuffer, 4096u);
264 }
265 #endif // CTS_USES_VULKANSC
266
setFragmentShadingRage(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)267 void setFragmentShadingRage (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
268 {
269 const VkExtent2D fragmentSize = { 1u, 1u };
270 const VkFragmentShadingRateCombinerOpKHR combinerOps[2] =
271 {
272 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
273 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
274 };
275 vkd->cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, combinerOps);
276 }
277
setLineStipple(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)278 void setLineStipple (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
279 {
280 vkd->cmdSetLineStippleEXT(cmdBuffer, 1u, 1u);
281 }
282
setCullMode(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)283 void setCullMode (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
284 {
285 #ifndef CTS_USES_VULKANSC
286 vkd->cmdSetCullMode(cmdBuffer, VK_CULL_MODE_FRONT_AND_BACK);
287 #else
288 vkd->cmdSetCullModeEXT(cmdBuffer, VK_CULL_MODE_FRONT_AND_BACK);
289 #endif // CTS_USES_VULKANSC
290 }
291
setFrontFace(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)292 void setFrontFace (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
293 {
294 #ifndef CTS_USES_VULKANSC
295 vkd->cmdSetFrontFace(cmdBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
296 #else
297 vkd->cmdSetFrontFaceEXT(cmdBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
298 #endif // CTS_USES_VULKANSC
299 }
300
setPrimitiveTopology(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)301 void setPrimitiveTopology (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
302 {
303 #ifndef CTS_USES_VULKANSC
304 vkd->cmdSetPrimitiveTopology(cmdBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
305 #else
306 vkd->cmdSetPrimitiveTopologyEXT(cmdBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
307 #endif // CTS_USES_VULKANSC
308 }
309
setViewportWithCount(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)310 void setViewportWithCount (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
311 {
312 const VkViewport viewport =
313 {
314 0.0f, // float x;
315 0.0f, // float y;
316 1.0f, // float width;
317 1.0f, // float height;
318 0.0f, // float minDepth;
319 1.0f, // float maxDepth;
320 };
321 #ifndef CTS_USES_VULKANSC
322 vkd->cmdSetViewportWithCount(cmdBuffer, 1u, &viewport);
323 #else
324 vkd->cmdSetViewportWithCountEXT(cmdBuffer, 1u, &viewport);
325 #endif // CTS_USES_VULKANSC
326 }
327
setScissorWithCount(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)328 void setScissorWithCount (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
329 {
330 const VkRect2D scissor =
331 {
332 { 0, 0 }, // VkOffset2D offset;
333 { 1u, 1u }, // VkExtent2D extent;
334 };
335 #ifndef CTS_USES_VULKANSC
336 vkd->cmdSetScissorWithCount(cmdBuffer, 1u, &scissor);
337 #else
338 vkd->cmdSetScissorWithCountEXT(cmdBuffer, 1u, &scissor);
339 #endif // CTS_USES_VULKANSC
340 }
341
bindVertexBuffers(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData * data)342 void bindVertexBuffers (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData* data)
343 {
344 const auto bindData = dynamic_cast<const BindVertexBuffersData*>(data);
345 DE_ASSERT(bindData != nullptr);
346 const auto vertexBuffer = bindData->getVertexBuffer();
347 const auto dataSize = static_cast<VkDeviceSize>(bindData->getDataSize());
348 const auto bufferOffset = vertexBuffer->getAllocation().getOffset();
349 const auto stride = static_cast<VkDeviceSize>(0);
350 const auto pipeline = bindData->getPipeline();
351
352 vkd->cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
353 #ifndef CTS_USES_VULKANSC
354 vkd->cmdBindVertexBuffers2(cmdBuffer, 0u, 1u, &vertexBuffer->get(), &bufferOffset, &dataSize, &stride);
355 #else
356 vkd->cmdBindVertexBuffers2EXT(cmdBuffer, 0u, 1u, &vertexBuffer->get(), &bufferOffset, &dataSize, &stride);
357 #endif // CTS_USES_VULKANSC
358 }
359
setDepthTestEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)360 void setDepthTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
361 {
362 #ifndef CTS_USES_VULKANSC
363 vkd->cmdSetDepthTestEnable(cmdBuffer, VK_TRUE);
364 #else
365 vkd->cmdSetDepthTestEnableEXT(cmdBuffer, VK_TRUE);
366 #endif // CTS_USES_VULKANSC
367 }
368
setDepthWriteEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)369 void setDepthWriteEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
370 {
371 #ifndef CTS_USES_VULKANSC
372 vkd->cmdSetDepthWriteEnable(cmdBuffer, VK_TRUE);
373 #else
374 vkd->cmdSetDepthWriteEnableEXT(cmdBuffer, VK_TRUE);
375 #endif // CTS_USES_VULKANSC
376 }
377
setDepthCompareOp(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)378 void setDepthCompareOp (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
379 {
380 #ifndef CTS_USES_VULKANSC
381 vkd->cmdSetDepthCompareOp(cmdBuffer, VK_COMPARE_OP_LESS);
382 #else
383 vkd->cmdSetDepthCompareOpEXT(cmdBuffer, VK_COMPARE_OP_LESS);
384 #endif // CTS_USES_VULKANSC
385 }
386
setDepthBoundsTestEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)387 void setDepthBoundsTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
388 {
389 #ifndef CTS_USES_VULKANSC
390 vkd->cmdSetDepthBoundsTestEnable(cmdBuffer, VK_TRUE);
391 #else
392 vkd->cmdSetDepthBoundsTestEnableEXT(cmdBuffer, VK_TRUE);
393 #endif // CTS_USES_VULKANSC
394 }
395
setStencilTestEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)396 void setStencilTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
397 {
398 #ifndef CTS_USES_VULKANSC
399 vkd->cmdSetStencilTestEnable(cmdBuffer, VK_TRUE);
400 #else
401 vkd->cmdSetStencilTestEnableEXT(cmdBuffer, VK_TRUE);
402 #endif // CTS_USES_VULKANSC
403 }
404
setStencilOp(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)405 void setStencilOp (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
406 {
407 #ifndef CTS_USES_VULKANSC
408 vkd->cmdSetStencilOp(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_OP_ZERO, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS);
409 #else
410 vkd->cmdSetStencilOpEXT(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_OP_ZERO, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS);
411 #endif // CTS_USES_VULKANSC
412 }
413
414 #ifndef CTS_USES_VULKANSC
415
setViewportWScaling(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)416 void setViewportWScaling (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
417 {
418 const VkViewportWScalingNV viewport =
419 {
420 1.0f, // float xcoeff;
421 1.0f, // float ycoeff;
422 };
423 vkd->cmdSetViewportWScalingNV(cmdBuffer, 0u, 1u, &viewport);
424 }
425
setViewportShadingRatePalette(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)426 void setViewportShadingRatePalette (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
427 {
428 const VkShadingRatePaletteEntryNV entry = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV;
429 const VkShadingRatePaletteNV palette =
430 {
431 1u, // deUint32 shadingRatePaletteEntryCount;
432 &entry, // const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries;
433 };
434 vkd->cmdSetViewportShadingRatePaletteNV(cmdBuffer, 0u, 1u, &palette);
435 }
436
setCoarseSamplingOrder(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)437 void setCoarseSamplingOrder (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
438 {
439 const VkCoarseSampleLocationNV locations[2] =
440 {
441 {
442 0u, // deUint32 pixelX;
443 0u, // deUint32 pixelY;
444 0u, // deUint32 sample;
445 },
446 {
447 0u, // deUint32 pixelX;
448 1u, // deUint32 pixelY;
449 0u, // deUint32 sample;
450 },
451 };
452 const VkCoarseSampleOrderCustomNV order =
453 {
454 VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, // VkShadingRatePaletteEntryNV shadingRate;
455 1u, // deUint32 sampleCount;
456 2u, // deUint32 sampleLocationCount;
457 locations // const VkCoarseSampleLocationNV* pSampleLocations;
458 };
459 vkd->cmdSetCoarseSampleOrderNV(cmdBuffer, VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV, 1u, &order);
460 }
461
setExclusiveScissor(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)462 void setExclusiveScissor (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
463 {
464 const VkRect2D scissor =
465 {
466 { 0, 0 }, // VkOffset2D offset;
467 { 1u, 1u }, // VkExtent2D extent;
468 };
469 vkd->cmdSetExclusiveScissorNV(cmdBuffer, 0u, 1u, &scissor);
470 }
471
472 #endif // CTS_USES_VULKANSC
473
474 const VkDynamicState dynamicStateList[] =
475 {
476 VK_DYNAMIC_STATE_VIEWPORT,
477 VK_DYNAMIC_STATE_SCISSOR,
478 VK_DYNAMIC_STATE_LINE_WIDTH,
479 VK_DYNAMIC_STATE_DEPTH_BIAS,
480 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
481 VK_DYNAMIC_STATE_DEPTH_BOUNDS,
482 VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
483 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
484 VK_DYNAMIC_STATE_STENCIL_REFERENCE,
485 VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
486 VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
487 #ifndef CTS_USES_VULKANSC
488 VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR,
489 #endif // CTS_USES_VULKANSC
490 VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
491 VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
492 VK_DYNAMIC_STATE_CULL_MODE_EXT,
493 VK_DYNAMIC_STATE_FRONT_FACE_EXT,
494 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
495 VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
496 VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,
497 VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
498 VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
499 VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
500 VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
501 VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
502 VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
503 VK_DYNAMIC_STATE_STENCIL_OP_EXT,
504 #ifndef CTS_USES_VULKANSC
505 VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
506 VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,
507 VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,
508 VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,
509 #endif // CTS_USES_VULKANSC
510 };
511
512 // Information about a dynamic state.
513 struct StateInfo
514 {
515 std::vector<std::string> requirements; // List of required functionalities.
516 RecordStateFunction recorder; // Function that records the state to the command buffer being used.
517 };
518
519 // Returns the state info for a given dynamic state.
getDynamicStateInfo(VkDynamicState state)520 const StateInfo& getDynamicStateInfo (VkDynamicState state)
521 {
522 // Maps a given state to its state info structure.
523 using StateInfoMap = std::map<VkDynamicState, StateInfo>;
524
525 static const StateInfoMap result =
526 {
527 { VK_DYNAMIC_STATE_VIEWPORT, { {}, setViewport } },
528 { VK_DYNAMIC_STATE_SCISSOR, { {}, setScissor } },
529 { VK_DYNAMIC_STATE_LINE_WIDTH, { {}, setLineWidth } },
530 { VK_DYNAMIC_STATE_DEPTH_BIAS, { {}, setDepthBias } },
531 { VK_DYNAMIC_STATE_BLEND_CONSTANTS, { {}, setBlendConstants } },
532 { VK_DYNAMIC_STATE_DEPTH_BOUNDS, { {}, setDepthBounds } },
533 { VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, { {}, setStencilCompareMask } },
534 { VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, { {}, setStencilWriteMask } },
535 { VK_DYNAMIC_STATE_STENCIL_REFERENCE, { {}, setStencilReference } },
536 { VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, { { "VK_EXT_discard_rectangles" }, setDiscardRectangle } },
537 { VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, { { "VK_EXT_sample_locations" }, setSampleLocations } },
538 #ifndef CTS_USES_VULKANSC
539 { VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR, { { "VK_KHR_ray_tracing_pipeline" }, setRTPipelineStatckSize } },
540 #endif // CTS_USES_VULKANSC
541 { VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR, { { "VK_KHR_fragment_shading_rate" }, setFragmentShadingRage } },
542 { VK_DYNAMIC_STATE_LINE_STIPPLE_EXT, { { "VK_EXT_line_rasterization" }, setLineStipple } },
543 { VK_DYNAMIC_STATE_CULL_MODE_EXT, { { "VK_EXT_extended_dynamic_state" }, setCullMode } },
544 { VK_DYNAMIC_STATE_FRONT_FACE_EXT, { { "VK_EXT_extended_dynamic_state" }, setFrontFace } },
545 { VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT, { { "VK_EXT_extended_dynamic_state" }, setPrimitiveTopology } },
546 { VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT, { { "VK_EXT_extended_dynamic_state" }, setViewportWithCount } },
547 { VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT, { { "VK_EXT_extended_dynamic_state" }, setScissorWithCount } },
548 { VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT, { { "VK_EXT_extended_dynamic_state" }, bindVertexBuffers } },
549 { VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT, { { "VK_EXT_extended_dynamic_state" }, setDepthTestEnable } },
550 { VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT, { { "VK_EXT_extended_dynamic_state" }, setDepthWriteEnable } },
551 { VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT, { { "VK_EXT_extended_dynamic_state" }, setDepthCompareOp } },
552 { VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT, { { "VK_EXT_extended_dynamic_state" }, setDepthBoundsTestEnable } },
553 { VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT, { { "VK_EXT_extended_dynamic_state" }, setStencilTestEnable } },
554 { VK_DYNAMIC_STATE_STENCIL_OP_EXT, { { "VK_EXT_extended_dynamic_state" }, setStencilOp } },
555 #ifndef CTS_USES_VULKANSC
556 { VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV, { { "VK_NV_clip_space_w_scaling" }, setViewportWScaling } },
557 { VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV, { { "VK_NV_shading_rate_image"}, setViewportShadingRatePalette } },
558 { VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV, { { "VK_NV_shading_rate_image"}, setCoarseSamplingOrder } },
559 { VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV, { { "VK_NV_scissor_exclusive"}, setExclusiveScissor } },
560 #endif // CTS_USES_VULKANSC
561 };
562
563 const auto itr = result.find(state);
564 DE_ASSERT(itr != result.end());
565
566 return itr->second;
567 }
568
569 // Device helper: this is needed in some tests when we create custom devices.
570 class DeviceHelper
571 {
572 public:
~DeviceHelper()573 virtual ~DeviceHelper () {}
574 virtual const DeviceInterface& getDeviceInterface (void) const = 0;
575 virtual VkDevice getDevice (void) const = 0;
576 virtual uint32_t getQueueFamilyIndex (void) const = 0;
577 virtual VkQueue getQueue (void) const = 0;
578 virtual Allocator& getAllocator (void) const = 0;
579 };
580
581 // This one just reuses the default device from the context.
582 class ContextDeviceHelper : public DeviceHelper
583 {
584 public:
ContextDeviceHelper(Context & context)585 ContextDeviceHelper (Context& context)
586 : m_deviceInterface (context.getDeviceInterface())
587 , m_device (context.getDevice())
588 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
589 , m_queue (context.getUniversalQueue())
590 , m_allocator (context.getDefaultAllocator())
591 {}
592
~ContextDeviceHelper()593 virtual ~ContextDeviceHelper () {}
594
getDeviceInterface(void) const595 const DeviceInterface& getDeviceInterface (void) const override { return m_deviceInterface; }
getDevice(void) const596 VkDevice getDevice (void) const override { return m_device; }
getQueueFamilyIndex(void) const597 uint32_t getQueueFamilyIndex (void) const override { return m_queueFamilyIndex; }
getQueue(void) const598 VkQueue getQueue (void) const override { return m_queue; }
getAllocator(void) const599 Allocator& getAllocator (void) const override { return m_allocator; }
600
601 protected:
602 const DeviceInterface& m_deviceInterface;
603 const VkDevice m_device;
604 const uint32_t m_queueFamilyIndex;
605 const VkQueue m_queue;
606 Allocator& m_allocator;
607 };
608
609 // This one creates a new device with VK_NV_shading_rate_image.
610 class ShadingRateImageDeviceHelper : public DeviceHelper
611 {
612 public:
ShadingRateImageDeviceHelper(Context & context)613 ShadingRateImageDeviceHelper (Context& context)
614 {
615 const auto& vkp = context.getPlatformInterface();
616 const auto& vki = context.getInstanceInterface();
617 const auto instance = context.getInstance();
618 const auto physicalDevice = context.getPhysicalDevice();
619 const auto queuePriority = 1.0f;
620
621 // Queue index first.
622 m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
623
624 // Create a universal queue that supports graphics and compute.
625 const VkDeviceQueueCreateInfo queueParams =
626 {
627 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
628 DE_NULL, // const void* pNext;
629 0u, // VkDeviceQueueCreateFlags flags;
630 m_queueFamilyIndex, // deUint32 queueFamilyIndex;
631 1u, // deUint32 queueCount;
632 &queuePriority // const float* pQueuePriorities;
633 };
634
635 const char* extensions[] =
636 {
637 "VK_NV_shading_rate_image",
638 };
639
640 #ifndef CTS_USES_VULKANSC
641 VkPhysicalDeviceShadingRateImageFeaturesNV shadingRateImageFeatures = initVulkanStructure();
642 VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&shadingRateImageFeatures);
643
644 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
645 #endif // CTS_USES_VULKANSC
646
647 const VkDeviceCreateInfo deviceCreateInfo =
648 {
649 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
650 #ifndef CTS_USES_VULKANSC
651 &features2, //pNext;
652 #else
653 DE_NULL,
654 #endif // CTS_USES_VULKANSC
655 0u, //flags
656 1u, //queueRecordCount;
657 &queueParams, //pRequestedQueues;
658 0u, //layerCount;
659 nullptr, //ppEnabledLayerNames;
660 static_cast<uint32_t>(de::arrayLength(extensions)), // deUint32 enabledExtensionCount;
661 extensions, // const char* const* ppEnabledExtensionNames;
662 nullptr, //pEnabledFeatures;
663 };
664
665 m_device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
666 m_vkd .reset(new DeviceDriver(vkp, instance, m_device.get()));
667 m_queue = getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
668 m_allocator .reset(new SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
669 }
670
~ShadingRateImageDeviceHelper()671 virtual ~ShadingRateImageDeviceHelper () {}
672
getDeviceInterface(void) const673 const DeviceInterface& getDeviceInterface (void) const override { return *m_vkd; }
getDevice(void) const674 VkDevice getDevice (void) const override { return m_device.get(); }
getQueueFamilyIndex(void) const675 uint32_t getQueueFamilyIndex (void) const override { return m_queueFamilyIndex; }
getQueue(void) const676 VkQueue getQueue (void) const override { return m_queue; }
getAllocator(void) const677 Allocator& getAllocator (void) const override { return *m_allocator; }
678
679 protected:
680 Move<VkDevice> m_device;
681 std::unique_ptr<DeviceDriver> m_vkd;
682 deUint32 m_queueFamilyIndex;
683 VkQueue m_queue;
684 std::unique_ptr<SimpleAllocator> m_allocator;
685 };
686
687 std::unique_ptr<DeviceHelper> g_shadingRateDeviceHelper;
688 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
689
getDeviceHelper(Context & context,VkDynamicState dynamicState)690 DeviceHelper& getDeviceHelper(Context& context, VkDynamicState dynamicState)
691 {
692 const auto& stateInfo = getDynamicStateInfo(dynamicState);
693
694 if (de::contains(stateInfo.requirements.begin(), stateInfo.requirements.end(), "VK_NV_shading_rate_image"))
695 {
696 if (!g_shadingRateDeviceHelper)
697 g_shadingRateDeviceHelper.reset(new ShadingRateImageDeviceHelper(context));
698 return *g_shadingRateDeviceHelper;
699 }
700
701 if (!g_contextDeviceHelper)
702 g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
703 return *g_contextDeviceHelper;
704 }
705
706 // Returns the set of auxiliary data needed to set a given state.
getDynamicStateData(Context & ctx,VkDevice device,VkDynamicState state)707 de::MovePtr<DynamicStateData> getDynamicStateData (Context& ctx, VkDevice device, VkDynamicState state)
708 {
709 // Create vertex buffer for VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT.
710 if (state == VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT)
711 return de::MovePtr<DynamicStateData>(new BindVertexBuffersData(ctx, device));
712
713 // null pointer normally.
714 return de::MovePtr<DynamicStateData>();
715 }
716
717 enum class OperType { COMPUTE = 0, TRANSFER };
718 enum class WhenToSet { BEFORE = 0, AFTER };
719
720 // Set dynamic state before or after attempting to run a compute or transfer operation.
721 struct TestParams
722 {
723 OperType operationType;
724 WhenToSet whenToSet;
725 std::vector<VkDynamicState> states;
726 };
727
728 class DynamicStateComputeCase : public vkt::TestCase
729 {
730 public:
731
732 DynamicStateComputeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params);
~DynamicStateComputeCase(void)733 virtual ~DynamicStateComputeCase (void) {}
734
735 virtual void checkSupport (Context& context) const;
736 virtual void initPrograms (vk::SourceCollections& programCollection) const;
737 virtual TestInstance* createInstance (Context& context) const;
738
739 protected:
740 TestParams m_params;
741 };
742
743 class DynamicStateComputeInstance : public vkt::TestInstance
744 {
745 public:
746 DynamicStateComputeInstance (Context& context, const TestParams& params);
~DynamicStateComputeInstance(void)747 virtual ~DynamicStateComputeInstance (void) {}
748
749 virtual tcu::TestStatus iterate (void);
750
751 protected:
752 tcu::TestStatus iterateTransfer (void);
753 tcu::TestStatus iterateCompute (void);
754
755 TestParams m_params;
756 };
757
DynamicStateComputeCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)758 DynamicStateComputeCase::DynamicStateComputeCase(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
759 : vkt::TestCase (testCtx, name, description)
760 , m_params (params)
761 {}
762
DynamicStateComputeInstance(Context & context,const TestParams & params)763 DynamicStateComputeInstance::DynamicStateComputeInstance (Context& context, const TestParams& params)
764 : vkt::TestInstance (context)
765 , m_params (params)
766 {}
767
checkSupport(Context & context) const768 void DynamicStateComputeCase::checkSupport (Context& context) const
769 {
770 // Check required functionalities.
771 for (const auto& state : m_params.states)
772 {
773 const auto stateInfo = getDynamicStateInfo(state);
774 for (const auto& functionality : stateInfo.requirements)
775 context.requireDeviceFunctionality(functionality);
776 }
777 }
778
initPrograms(vk::SourceCollections & programCollection) const779 void DynamicStateComputeCase::initPrograms (vk::SourceCollections& programCollection) const
780 {
781 if (m_params.operationType == OperType::COMPUTE)
782 {
783 std::ostringstream comp;
784 comp
785 << "#version 450\n"
786 << "\n"
787 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
788 << "\n"
789 << "layout (push_constant, std430) uniform PushConstants {\n"
790 << " uint valueIndex;\n"
791 << "} pc;\n"
792 << "\n"
793 << "layout (set=0, binding=0, std430) buffer OutputBlock {\n"
794 << " uint value[];\n"
795 << "} ob;\n"
796 << "\n"
797 << "void main ()\n"
798 << "{\n"
799 << " ob.value[pc.valueIndex] = 1u;\n"
800 << "}\n"
801 ;
802
803 programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
804 }
805
806 if (de::contains(begin(m_params.states), end(m_params.states), VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT))
807 {
808 // Passthrough vertex shader for stand-in graphics pipeline.
809 std::ostringstream vert;
810 vert
811 << "#version 450\n"
812 << "layout (location=0) in vec4 inVertex;\n"
813 << "void main() {\n"
814 << " gl_Position = inVertex;\n"
815 << "}\n"
816 ;
817
818 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
819 }
820 }
821
createInstance(Context & context) const822 vkt::TestInstance* DynamicStateComputeCase::createInstance (Context& context) const
823 {
824 return new DynamicStateComputeInstance(context, m_params);
825 }
826
iterate(void)827 tcu::TestStatus DynamicStateComputeInstance::iterate (void)
828 {
829 if (m_params.operationType == OperType::COMPUTE)
830 return iterateCompute();
831 else
832 return iterateTransfer();
833 }
834
fillBuffer(const DeviceInterface & vkd,VkDevice device,BufferWithMemory & buffer,const std::vector<deUint32> & values)835 void fillBuffer(const DeviceInterface& vkd, VkDevice device, BufferWithMemory& buffer, const std::vector<deUint32> &values)
836 {
837 auto& alloc = buffer.getAllocation();
838
839 deMemcpy(alloc.getHostPtr(), values.data(), de::dataSize(values));
840 flushAlloc(vkd, device, alloc);
841 }
842
iterateTransfer(void)843 tcu::TestStatus DynamicStateComputeInstance::iterateTransfer (void)
844 {
845 const auto& vki = m_context.getInstanceInterface();
846 const auto phyDev = m_context.getPhysicalDevice();
847 auto& devHelper = getDeviceHelper(m_context, m_params.states.at(0));
848 const auto& vkd = devHelper.getDeviceInterface();
849 const auto device = devHelper.getDevice();
850 const auto qIndex = devHelper.getQueueFamilyIndex();
851 const auto queue = devHelper.getQueue();
852 auto& alloc = devHelper.getAllocator();
853
854 const auto cmdPool = makeCommandPool(vkd, device, qIndex);
855 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
856 const auto cmdBuffer = cmdBufferPtr.get();
857
858 // Prepare two host-visible buffers for a transfer operation, with one element per dynamic state.
859 const deUint32 seqStart = 1611747605u;
860
861 DE_ASSERT(!m_params.states.empty());
862 std::vector<deUint32> srcValues(m_params.states.size());
863 const decltype(srcValues) dstValues(srcValues.size(), 0u);
864 std::iota(begin(srcValues), end(srcValues), seqStart);
865
866 const auto elemSize = static_cast<VkDeviceSize>(sizeof(decltype(srcValues)::value_type));
867 const auto dataSize = static_cast<VkDeviceSize>(de::dataSize(srcValues));
868 const auto bufferSize = de::roundUp(dataSize, getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
869 const auto srcInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
870 const auto dstInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
871 BufferWithMemory srcBuffer (vkd, device, alloc, srcInfo, MemoryRequirement::HostVisible);
872 BufferWithMemory dstBuffer (vkd, device, alloc, dstInfo, MemoryRequirement::HostVisible);
873
874 // Fill source and destination buffer.
875 fillBuffer(vkd, device, srcBuffer, srcValues);
876 fillBuffer(vkd, device, dstBuffer, dstValues);
877
878 beginCommandBuffer(vkd, cmdBuffer);
879
880 // We need to preserve dynamic state data until the command buffer has run.
881 std::vector<de::MovePtr<DynamicStateData>> statesData;
882
883 for (size_t stateIdx = 0; stateIdx < m_params.states.size(); ++stateIdx)
884 {
885 // Get extra data needed for using the dynamic state.
886 const auto offset = elemSize * stateIdx;
887 const auto& state = m_params.states[stateIdx];
888 const auto stateInfo = getDynamicStateInfo(state);
889 statesData.push_back(getDynamicStateData(m_context, device, state));
890
891 // Record command if before.
892 if (m_params.whenToSet == WhenToSet::BEFORE)
893 stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
894
895 // Transfer op (copy one buffer element per dynamic state).
896 const VkBufferCopy region = { offset, offset, elemSize };
897 vkd.cmdCopyBuffer(cmdBuffer, srcBuffer.get(), dstBuffer.get(), 1u, ®ion);
898
899 // Record command if after.
900 if (m_params.whenToSet == WhenToSet::AFTER)
901 stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
902 }
903
904 const auto barrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
905 vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);
906
907 endCommandBuffer(vkd, cmdBuffer);
908 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
909
910 // Invalidate alloc and check destination buffer.
911 auto& dstBufferAlloc = dstBuffer.getAllocation();
912 invalidateAlloc(vkd, device, dstBufferAlloc);
913
914 decltype(srcValues) results (srcValues.size());
915 deMemcpy(results.data(), dstBufferAlloc.getHostPtr(), de::dataSize(srcValues));
916
917 for (size_t valueIdx = 0; valueIdx < srcValues.size(); ++valueIdx)
918 {
919 const auto& orig = srcValues[valueIdx];
920 const auto& res = results[valueIdx];
921
922 if (orig != res)
923 {
924 std::ostringstream msg;
925 msg << "Unexpected value found in destination buffer at position " << valueIdx << " (found=" << res << " expected=" << orig << ")";
926 TCU_FAIL(msg.str());
927 }
928 }
929
930 return tcu::TestStatus::pass("Pass");
931 }
932
iterateCompute(void)933 tcu::TestStatus DynamicStateComputeInstance::iterateCompute (void)
934 {
935 const auto& vki = m_context.getInstanceInterface();
936 const auto phyDev = m_context.getPhysicalDevice();
937 auto& devHelper = getDeviceHelper(m_context, m_params.states.at(0));
938 const auto& vkd = devHelper.getDeviceInterface();
939 const auto device = devHelper.getDevice();
940 const auto qIndex = devHelper.getQueueFamilyIndex();
941 const auto queue = devHelper.getQueue();
942 auto& alloc = devHelper.getAllocator();
943
944 const auto cmdPool = makeCommandPool(vkd, device, qIndex);
945 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
946 const auto cmdBuffer = cmdBufferPtr.get();
947
948 DescriptorSetLayoutBuilder setLayoutBuilder;
949 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
950 const auto setLayout = setLayoutBuilder.build(vkd, device);
951
952 // Push constants.
953 const deUint32 pcSize = static_cast<deUint32>(sizeof(deUint32));
954 const auto pcRange = makePushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, 0u, pcSize);
955
956 // Pipeline.
957 const VkPipelineLayoutCreateInfo layoutInfo =
958 {
959 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
960 nullptr, // const void* pNext;
961 0u, // VkPipelineLayoutCreateFlags flags;
962 1u, // deUint32 setLayoutCount;
963 &setLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
964 1u, // deUint32 pushConstantRangeCount;
965 &pcRange, // const VkPushConstantRange* pPushConstantRanges;
966 };
967 const auto pipelineLayout = createPipelineLayout(vkd, device, &layoutInfo);
968
969 const auto shaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);
970
971 const VkPipelineShaderStageCreateInfo shaderStageInfo =
972 {
973 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
974 nullptr, // const void* pNext;
975 0u, // VkPipelineShaderStageCreateFlags flags;
976 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
977 shaderModule.get(), // VkShaderModule module;
978 "main", // const char* pName;
979 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
980 };
981
982 const VkComputePipelineCreateInfo pipelineInfo =
983 {
984 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
985 nullptr, // const void* pNext;
986 0u, // VkPipelineCreateFlags flags;
987 shaderStageInfo, // VkPipelineShaderStageCreateInfo stage;
988 pipelineLayout.get(), // VkPipelineLayout layout;
989 DE_NULL, // VkPipeline basePipelineHandle;
990 0, // deInt32 basePipelineIndex;
991 };
992 const auto pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineInfo);
993
994 DE_ASSERT(!m_params.states.empty());
995
996 // Output buffer with one value per state.
997 std::vector<deUint32> bufferData (m_params.states.size(), 0u);
998 const auto dataSize (de::dataSize(bufferData));
999 const auto outputBufferSize = de::roundUp(static_cast<VkDeviceSize>(dataSize), getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
1000 const auto bufferCreateInfo = makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1001
1002 BufferWithMemory outputBuffer (vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
1003 auto& outputBufferAlloc = outputBuffer.getAllocation();
1004 auto outputBufferPtr = outputBufferAlloc.getHostPtr();
1005
1006 deMemcpy(outputBufferPtr, bufferData.data(), dataSize);
1007 flushAlloc(vkd, device, outputBufferAlloc);
1008
1009 // Descriptor set.
1010 DescriptorPoolBuilder poolBuilder;
1011 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1012 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1013
1014 const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
1015
1016 const auto bufferInfo = makeDescriptorBufferInfo(outputBuffer.get(), 0ull, outputBufferSize);
1017 DescriptorSetUpdateBuilder updateBuilder;
1018 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
1019 updateBuilder.update(vkd, device);
1020
1021 // Record and submit.
1022 beginCommandBuffer(vkd, cmdBuffer);
1023
1024 // We need to preserve dynamic state data until the command buffer has run.
1025 std::vector<de::MovePtr<DynamicStateData>> statesData;
1026
1027 for (size_t stateIdx = 0; stateIdx < m_params.states.size(); ++stateIdx)
1028 {
1029 // Objects needed to set the dynamic state.
1030 const auto& state = m_params.states[stateIdx];
1031 const auto stateInfo = getDynamicStateInfo(state);
1032 statesData.push_back(getDynamicStateData(m_context, device, state));
1033
1034 if (m_params.whenToSet == WhenToSet::BEFORE)
1035 stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
1036
1037 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.get());
1038 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1039 {
1040 // Each state will write to a different buffer position.
1041 const deUint32 pcData = static_cast<deUint32>(stateIdx);
1042 vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), VK_SHADER_STAGE_COMPUTE_BIT, 0u, pcSize, &pcData);
1043 }
1044 vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
1045
1046 if (m_params.whenToSet == WhenToSet::AFTER)
1047 stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
1048 }
1049
1050 // Barrier to read buffer contents.
1051 const auto barrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1052 vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);
1053
1054 endCommandBuffer(vkd, cmdBuffer);
1055 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1056
1057 // Read and verify buffer contents.
1058 invalidateAlloc(vkd, device, outputBufferAlloc);
1059 deMemcpy(bufferData.data(), outputBufferPtr, dataSize);
1060
1061 for (size_t idx = 0u; idx < bufferData.size(); ++idx)
1062 {
1063 if (bufferData[idx] != 1u)
1064 {
1065 std::ostringstream msg;
1066 msg << "Unexpected value found at buffer position " << idx << ": " << bufferData[idx];
1067 TCU_FAIL(msg.str());
1068 }
1069 }
1070
1071 return tcu::TestStatus::pass("Pass");
1072 }
1073
getDynamicStateBriefName(VkDynamicState state)1074 std::string getDynamicStateBriefName (VkDynamicState state)
1075 {
1076 const auto fullName = de::toString(state);
1077 const auto prefixLen = strlen("VK_DYNAMIC_STATE_");
1078
1079 return de::toLower(fullName.substr(prefixLen));
1080 }
1081
1082 } // anonymous
1083
createDynamicStateComputeTests(tcu::TestContext & testCtx)1084 tcu::TestCaseGroup* createDynamicStateComputeTests (tcu::TestContext& testCtx)
1085 {
1086 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
1087
1088 GroupPtr mainGroup(new tcu::TestCaseGroup(testCtx, "compute_transfer", "Dynamic state mixed with compute and transfer operations"));
1089
1090 const struct
1091 {
1092 OperType operationType;
1093 const char* name;
1094 } operations[] =
1095 {
1096 { OperType::COMPUTE, "compute" },
1097 { OperType::TRANSFER, "transfer" },
1098 };
1099
1100 const struct
1101 {
1102 WhenToSet when;
1103 const char* name;
1104 } moments[] =
1105 {
1106 { WhenToSet::BEFORE, "before" },
1107 { WhenToSet::AFTER, "after" },
1108 };
1109
1110 // Tests with a single dynamic state.
1111 {
1112 GroupPtr singleStateGroup(new tcu::TestCaseGroup(testCtx, "single", "Tests using a single dynamic state"));
1113
1114 for (int operIdx = 0; operIdx < DE_LENGTH_OF_ARRAY(operations); ++operIdx)
1115 {
1116 GroupPtr operationGroup(new tcu::TestCaseGroup(testCtx, operations[operIdx].name, ""));
1117
1118 for (int stateIdx = 0; stateIdx < DE_LENGTH_OF_ARRAY(dynamicStateList); ++stateIdx)
1119 {
1120 const auto state = dynamicStateList[stateIdx];
1121 const auto stateName = getDynamicStateBriefName(state);
1122
1123 GroupPtr stateGroup(new tcu::TestCaseGroup(testCtx, stateName.c_str(), ""));
1124
1125 for (int momentIdx = 0; momentIdx < DE_LENGTH_OF_ARRAY(moments); ++momentIdx)
1126 {
1127 const TestParams testParams =
1128 {
1129 operations[operIdx].operationType, // OperType operationType;
1130 moments[momentIdx].when, // WhenToSet whenToSet;
1131 std::vector<VkDynamicState>(1, state), // std::vector<VkDynamicState> state;
1132 };
1133
1134 stateGroup->addChild(new DynamicStateComputeCase(testCtx, moments[momentIdx].name, "", testParams));
1135 }
1136
1137 operationGroup->addChild(stateGroup.release());
1138 }
1139
1140 singleStateGroup->addChild(operationGroup.release());
1141 }
1142
1143 mainGroup->addChild(singleStateGroup.release());
1144 }
1145
1146 // A few tests with several dynamic states.
1147 {
1148 GroupPtr multiStateGroup(new tcu::TestCaseGroup(testCtx, "multi", "Tests using multiple dynamic states"));
1149
1150 for (int operIdx = 0; operIdx < DE_LENGTH_OF_ARRAY(operations); ++operIdx)
1151 {
1152 GroupPtr operationGroup(new tcu::TestCaseGroup(testCtx, operations[operIdx].name, ""));
1153
1154 for (int momentIdx = 0; momentIdx < DE_LENGTH_OF_ARRAY(moments); ++momentIdx)
1155 {
1156 TestParams testParams =
1157 {
1158 operations[operIdx].operationType, // OperType operationType;
1159 moments[momentIdx].when, // WhenToSet whenToSet;
1160 std::vector<VkDynamicState>(), // std::vector<VkDynamicState> states;
1161 };
1162
1163 // Use the basic states so as not to introduce extra requirements.
1164 for (int stateIdx = 0; stateIdx < DE_LENGTH_OF_ARRAY(dynamicStateList); ++stateIdx)
1165 {
1166 testParams.states.push_back(dynamicStateList[stateIdx]);
1167 if (dynamicStateList[stateIdx] == VK_DYNAMIC_STATE_STENCIL_REFERENCE)
1168 break;
1169 }
1170
1171 operationGroup->addChild(new DynamicStateComputeCase(testCtx, moments[momentIdx].name, "", testParams));
1172 }
1173
1174 multiStateGroup->addChild(operationGroup.release());
1175 }
1176
1177 mainGroup->addChild(multiStateGroup.release());
1178 }
1179
1180 return mainGroup.release();
1181 }
1182
cleanupDevice()1183 void cleanupDevice()
1184 {
1185 g_shadingRateDeviceHelper.reset(nullptr);
1186 g_contextDeviceHelper.reset(nullptr);
1187 }
1188
1189 } // DynamicState
1190 } // vkt
1191