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