1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel 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 Viewport Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDynamicStateVPTests.hpp"
26
27 #include "vktDynamicStateBaseClass.hpp"
28 #include "vktDynamicStateTestCaseUtil.hpp"
29
30 #include "vkImageUtil.hpp"
31 #include "vkCmdUtil.hpp"
32
33 #include "tcuTextureUtil.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuRGBA.hpp"
36
37 namespace vkt
38 {
39 namespace DynamicState
40 {
41
42 using namespace Draw;
43
44 namespace
45 {
46
47 class ViewportStateBaseCase : public DynamicStateBaseClass
48 {
49 public:
ViewportStateBaseCase(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName, const char* meshShaderName)50 ViewportStateBaseCase (Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName, const char* meshShaderName)
51 : DynamicStateBaseClass (context, pipelineConstructionType, vertexShaderName, fragmentShaderName, meshShaderName)
52 {}
53
initialize(void)54 void initialize(void)
55 {
56 m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, 0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
57 m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
58 m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, -0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
59 m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, -0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
60
61 DynamicStateBaseClass::initialize();
62 }
63
buildReferenceFrame(void)64 virtual tcu::Texture2D buildReferenceFrame (void)
65 {
66 DE_ASSERT(false);
67 return tcu::Texture2D(tcu::TextureFormat(), 0, 0);
68 }
69
setDynamicStates(void)70 virtual void setDynamicStates (void)
71 {
72 DE_ASSERT(false);
73 }
74
iterate(void)75 virtual tcu::TestStatus iterate (void)
76 {
77 tcu::TestLog& log = m_context.getTestContext().getLog();
78 const vk::VkQueue queue = m_context.getUniversalQueue();
79 const vk::VkDevice device = m_context.getDevice();
80
81 beginRenderPass();
82
83 // set states here
84 setDynamicStates();
85
86 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.getPipeline());
87
88 #ifndef CTS_USES_VULKANSC
89 if (m_isMesh)
90 {
91 const auto numVert = static_cast<uint32_t>(m_data.size());
92 DE_ASSERT(numVert >= 2u);
93
94 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
95 pushVertexOffset(0u, *m_pipelineLayout);
96 m_vk.cmdDrawMeshTasksEXT(*m_cmdBuffer, numVert - 2u, 1u, 1u);
97 }
98 else
99 #endif // CTS_USES_VULKANSC
100 {
101 const vk::VkDeviceSize vertexBufferOffset = 0;
102 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
103 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
104
105 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
106 }
107
108 endRenderPass(m_vk, *m_cmdBuffer);
109 endCommandBuffer(m_vk, *m_cmdBuffer);
110
111 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
112
113 // validation
114 {
115 tcu::Texture2D referenceFrame = buildReferenceFrame();
116
117 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
118 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
119 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
120
121 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
122 referenceFrame.getLevel(0), renderedFrame, 0.05f,
123 tcu::COMPARE_LOG_RESULT))
124 {
125 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
126 }
127
128 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
129 }
130 }
131 };
132
133 class ViewportParamTestInstance : public ViewportStateBaseCase
134 {
135 public:
ViewportParamTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)136 ViewportParamTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)
137 : ViewportStateBaseCase (context, pipelineConstructionType, shaders.at(glu::SHADERTYPE_VERTEX), shaders.at(glu::SHADERTYPE_FRAGMENT), shaders.at(glu::SHADERTYPE_MESH))
138 {
139 ViewportStateBaseCase::initialize();
140 }
141
setDynamicStates(void)142 virtual void setDynamicStates(void)
143 {
144 const vk::VkViewport viewport = { 0.0f, 0.0f, static_cast<float>(WIDTH) * 2.0f, static_cast<float>(HEIGHT) * 2.0f, 0.0f, 0.0f };
145 const vk::VkRect2D scissor = { { 0, 0 }, { WIDTH, HEIGHT } };
146
147 setDynamicViewportState(1, &viewport, &scissor);
148 setDynamicRasterizationState();
149 setDynamicBlendState();
150 setDynamicDepthStencilState();
151 }
152
buildReferenceFrame(void)153 virtual tcu::Texture2D buildReferenceFrame (void)
154 {
155 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
156 referenceFrame.allocLevel(0);
157
158 const deInt32 frameWidth = referenceFrame.getWidth();
159 const deInt32 frameHeight = referenceFrame.getHeight();
160
161 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
162
163 for (int y = 0; y < frameHeight; y++)
164 {
165 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
166
167 for (int x = 0; x < frameWidth; x++)
168 {
169 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
170
171 if (xCoord >= 0.0f && xCoord <= 1.0f && yCoord >= 0.0f && yCoord <= 1.0f)
172 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
173 }
174 }
175
176 return referenceFrame;
177 }
178 };
179
180 class ScissorParamTestInstance : public ViewportStateBaseCase
181 {
182 public:
ScissorParamTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)183 ScissorParamTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)
184 : ViewportStateBaseCase (context, pipelineConstructionType, shaders.at(glu::SHADERTYPE_VERTEX), shaders.at(glu::SHADERTYPE_FRAGMENT), shaders.at(glu::SHADERTYPE_MESH))
185 {
186 ViewportStateBaseCase::initialize();
187 }
188
setDynamicStates(void)189 virtual void setDynamicStates (void)
190 {
191 const vk::VkViewport viewport = { 0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 0.0f };
192 const vk::VkRect2D scissor = { { 0, 0 }, { WIDTH / 2, HEIGHT / 2 } };
193
194 setDynamicViewportState(1, &viewport, &scissor);
195 setDynamicRasterizationState();
196 setDynamicBlendState();
197 setDynamicDepthStencilState();
198 }
199
buildReferenceFrame(void)200 virtual tcu::Texture2D buildReferenceFrame (void)
201 {
202 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
203 referenceFrame.allocLevel(0);
204
205 const deInt32 frameWidth = referenceFrame.getWidth();
206 const deInt32 frameHeight = referenceFrame.getHeight();
207
208 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
209
210 for (int y = 0; y < frameHeight; y++)
211 {
212 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
213
214 for (int x = 0; x < frameWidth; x++)
215 {
216 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
217
218 if (xCoord >= -0.5f && xCoord <= 0.0f && yCoord >= -0.5f && yCoord <= 0.0f)
219 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
220 }
221 }
222
223 return referenceFrame;
224 }
225 };
226
227 class ViewportArrayTestInstance : public DynamicStateBaseClass
228 {
229 protected:
230 std::string m_geometryShaderName;
231
232 public:
233
234 static constexpr uint32_t kNumViewports = 4u;
235
ViewportArrayTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)236 ViewportArrayTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)
237 : DynamicStateBaseClass (context, pipelineConstructionType, shaders.at(glu::SHADERTYPE_VERTEX), shaders.at(glu::SHADERTYPE_FRAGMENT), shaders.at(glu::SHADERTYPE_MESH))
238 , m_geometryShaderName (shaders.at(glu::SHADERTYPE_GEOMETRY) ? shaders.at(glu::SHADERTYPE_GEOMETRY) : "")
239 {
240 if (m_isMesh)
241 DE_ASSERT(m_geometryShaderName.empty());
242 else
243 DE_ASSERT(!m_geometryShaderName.empty());
244
245 for (uint32_t i = 0u; i < kNumViewports; i++)
246 {
247 m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
248 m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
249 m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
250 m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
251 }
252
253 DynamicStateBaseClass::initialize();
254 }
255
initPipeline(const vk::VkDevice device)256 virtual void initPipeline (const vk::VkDevice device)
257 {
258 const auto& binaries = m_context.getBinaryCollection();
259 const vk::Move<vk::VkShaderModule> vs (m_isMesh ? vk::Move<vk::VkShaderModule>() : createShaderModule(m_vk, device, binaries.get(m_vertexShaderName), 0));
260 const vk::Move<vk::VkShaderModule> gs (m_isMesh ? vk::Move<vk::VkShaderModule>() : createShaderModule(m_vk, device, binaries.get(m_geometryShaderName), 0));
261 const vk::Move<vk::VkShaderModule> ms (m_isMesh ? vk::createShaderModule(m_vk, device, binaries.get(m_meshShaderName)) : vk::Move<vk::VkShaderModule>());
262 const vk::Move<vk::VkShaderModule> fs (createShaderModule(m_vk, device, binaries.get(m_fragmentShaderName), 0));
263 std::vector<vk::VkViewport> viewports (4u, { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f });
264 std::vector<vk::VkRect2D> scissors (4u, { { 0u, 0u }, { 0u, 0u } });
265
266 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
267 const PipelineCreateInfo::ColorBlendState colorBlendState(1u, static_cast<const vk::VkPipelineColorBlendAttachmentState*>(&attachmentState));
268 const PipelineCreateInfo::RasterizerState rasterizerState;
269 const PipelineCreateInfo::DepthStencilState depthStencilState;
270 PipelineCreateInfo::DynamicState dynamicState;
271
272 m_pipeline.setDefaultTopology(m_topology)
273 .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState))
274 .setDefaultMultisampleState();
275
276 #ifndef CTS_USES_VULKANSC
277 if (m_isMesh)
278 {
279 m_pipeline
280 .setupPreRasterizationMeshShaderState(viewports,
281 scissors,
282 *m_pipelineLayout,
283 *m_renderPass,
284 0u,
285 DE_NULL,
286 *ms,
287 static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState));
288 }
289 else
290 #endif // CTS_USES_VULKANSC
291 {
292 m_pipeline
293 .setupVertexInputState(&m_vertexInputState)
294 .setupPreRasterizationShaderState(viewports,
295 scissors,
296 *m_pipelineLayout,
297 *m_renderPass,
298 0u,
299 *vs,
300 static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState),
301 DE_NULL,
302 DE_NULL,
303 *gs);
304 }
305
306 m_pipeline.setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, *fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState))
307 .setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState))
308 .setMonolithicPipelineLayout(*m_pipelineLayout)
309 .buildPipeline();
310 }
311
iterate(void)312 virtual tcu::TestStatus iterate (void)
313 {
314 tcu::TestLog& log = m_context.getTestContext().getLog();
315 const vk::VkQueue queue = m_context.getUniversalQueue();
316 const vk::VkDevice device = m_context.getDevice();
317
318 beginRenderPass();
319
320 // set states here
321 const float halfWidth = (float)WIDTH / 2;
322 const float halfHeight = (float)HEIGHT / 2;
323 const deInt32 quarterWidth = WIDTH / 4;
324 const deInt32 quarterHeight = HEIGHT / 4;
325
326 const vk::VkViewport viewports[kNumViewports] =
327 {
328 { 0.0f, 0.0f, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
329 { halfWidth, 0.0f, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
330 { halfWidth, halfHeight, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
331 { 0.0f, halfHeight, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f }
332 };
333
334 const vk::VkRect2D scissors[kNumViewports] =
335 {
336 { { quarterWidth, quarterHeight }, { quarterWidth, quarterHeight } },
337 { { (deInt32)halfWidth, quarterHeight }, { quarterWidth, quarterHeight } },
338 { { (deInt32)halfWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
339 { { quarterWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
340 };
341
342 setDynamicViewportState(kNumViewports, viewports, scissors);
343 setDynamicRasterizationState();
344 setDynamicBlendState();
345 setDynamicDepthStencilState();
346
347 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.getPipeline());
348
349 DE_ASSERT(m_data.size() % kNumViewports == 0u);
350 const uint32_t vertsPerViewport = static_cast<uint32_t>(m_data.size() / kNumViewports);
351
352 if (!m_isMesh)
353 {
354 const vk::VkDeviceSize vertexBufferOffset = 0;
355 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
356 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
357
358 for (uint32_t i = 0u; i < kNumViewports; ++i)
359 {
360 const uint32_t firstVertex = i * vertsPerViewport;
361 m_vk.cmdDraw(*m_cmdBuffer, vertsPerViewport, 1, firstVertex, 0);
362 }
363 }
364 #ifndef CTS_USES_VULKANSC
365 else
366 {
367 DE_ASSERT(vertsPerViewport >= 2u);
368
369 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
370
371 for (uint32_t i = 0u; i < kNumViewports; ++i)
372 {
373 const uint32_t firstVertex = i * vertsPerViewport;
374 pushVertexOffset(firstVertex, *m_pipelineLayout);
375 m_vk.cmdDrawMeshTasksEXT(*m_cmdBuffer, vertsPerViewport - 2u, 1u, 1u);
376 }
377 }
378 #endif // CTS_USES_VULKANSC
379
380 endRenderPass(m_vk, *m_cmdBuffer);
381 endCommandBuffer(m_vk, *m_cmdBuffer);
382
383 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
384
385 // validation
386 {
387 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
388 referenceFrame.allocLevel(0);
389
390 const deInt32 frameWidth = referenceFrame.getWidth();
391 const deInt32 frameHeight = referenceFrame.getHeight();
392
393 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
394
395 for (int y = 0; y < frameHeight; y++)
396 {
397 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
398
399 for (int x = 0; x < frameWidth; x++)
400 {
401 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
402
403 if (xCoord >= -0.5f && xCoord <= 0.5f && yCoord >= -0.5f && yCoord <= 0.5f)
404 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
405 }
406 }
407
408 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
409 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
410 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
411
412 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
413 referenceFrame.getLevel(0), renderedFrame, 0.05f,
414 tcu::COMPARE_LOG_RESULT))
415 {
416 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
417 }
418
419 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
420 }
421 }
422 };
423
checkGeometryAndMultiViewportSupport(Context& context)424 void checkGeometryAndMultiViewportSupport (Context& context)
425 {
426 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
427 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
428 }
429
checkMeshShaderSupport(Context& context)430 void checkMeshShaderSupport (Context& context)
431 {
432 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
433 }
434
checkMeshAndMultiViewportSupport(Context& context)435 void checkMeshAndMultiViewportSupport (Context& context)
436 {
437 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
438 checkMeshShaderSupport(context);
439 }
440
checkNothing(Context&)441 void checkNothing (Context&)
442 {
443 }
444
445 } //anonymous
446
DynamicStateVPTests(tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)447 DynamicStateVPTests::DynamicStateVPTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
448 : TestCaseGroup (testCtx, "vp_state", "Tests for viewport state")
449 , m_pipelineConstructionType (pipelineConstructionType)
450 {
451 /* Left blank on purpose */
452 }
453
~DynamicStateVPTests()454 DynamicStateVPTests::~DynamicStateVPTests ()
455 {
456 }
457
init(void)458 void DynamicStateVPTests::init (void)
459 {
460 ShaderMap basePaths;
461 basePaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
462 basePaths[glu::SHADERTYPE_GEOMETRY] = nullptr;
463 basePaths[glu::SHADERTYPE_VERTEX] = nullptr;
464 basePaths[glu::SHADERTYPE_MESH] = nullptr;
465
466 for (int i = 0; i < 2; ++i)
467 {
468 const bool isMesh = (i > 0);
469 ShaderMap shaderPaths(basePaths);
470 std::string nameSuffix;
471 std::string descSuffix;
472 FunctionSupport0::Function checkSupportFunc;
473
474 if (isMesh)
475 {
476 #ifndef CTS_USES_VULKANSC
477 shaderPaths[glu::SHADERTYPE_MESH] = "vulkan/dynamic_state/VertexFetch.mesh";
478 nameSuffix = "_mesh";
479 descSuffix = " using mesh shaders";
480 checkSupportFunc = checkMeshShaderSupport;
481 #else
482 continue;
483 #endif // CTS_USES_VULKANSC
484 }
485 else
486 {
487 shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
488 checkSupportFunc = checkNothing;
489 }
490
491 addChild(new InstanceFactory<ViewportParamTestInstance, FunctionSupport0>(m_testCtx, "viewport" + nameSuffix, "Set viewport which is twice bigger than screen size" + descSuffix, m_pipelineConstructionType, shaderPaths, checkSupportFunc));
492 addChild(new InstanceFactory<ScissorParamTestInstance, FunctionSupport0>(m_testCtx, "scissor" + nameSuffix, "Perform a scissor test on 1/4 bottom-left part of the surface" + descSuffix, m_pipelineConstructionType, shaderPaths, checkSupportFunc));
493
494 if (isMesh)
495 {
496 shaderPaths[glu::SHADERTYPE_MESH] = "vulkan/dynamic_state/VertexFetchViewportArray.mesh";
497 checkSupportFunc = checkMeshAndMultiViewportSupport;
498 }
499 else
500 {
501 shaderPaths[glu::SHADERTYPE_GEOMETRY] = "vulkan/dynamic_state/ViewportArray.geom";
502 checkSupportFunc = checkGeometryAndMultiViewportSupport;
503 }
504 addChild(new InstanceFactory<ViewportArrayTestInstance, FunctionSupport0>(m_testCtx, "viewport_array" + nameSuffix, "Multiple viewports and scissors" + descSuffix, m_pipelineConstructionType, shaderPaths, checkSupportFunc));
505 }
506 }
507
508 } // DynamicState
509 } // vkt
510