1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017-2019 The Khronos Group Inc.
6 * Copyright (c) 2018-2020 NVIDIA Corporation
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Tests for VK_KHR_fragment_shading_rate
25 * The test renders 9*9 triangles, where each triangle has one of the valid
26 * fragment sizes ({1,2,4},{1,2,4}) (clamped to implementation limits) for
27 * each of the pipeline shading rate and the primitive shading rate. The
28 * fragment shader does an atomic add to a memory location to get a unique
29 * identifier for the fragment, and outputs the primitive ID, atomic counter,
30 * fragment size, and some other info the the color output. Then a compute
31 * shader copies this to buffer memory, and the host verifies several
32 * properties of the output. For example, if a sample has a particular
33 * primitive ID and atomic value, then all other samples in the tile with
34 * the same primitive ID should have the same atomic value.
35 *//*--------------------------------------------------------------------*/
36
37 #include "vktFragmentShadingRateBasic.hpp"
38
39 #include "vkBufferWithMemory.hpp"
40 #include "vkImageWithMemory.hpp"
41 #include "vkQueryUtil.hpp"
42 #include "vkBuilderUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkTypeUtil.hpp"
45 #include "vkObjUtil.hpp"
46 #include "vkImageUtil.hpp"
47 #include "vkStrUtil.hpp"
48 #include "vkBarrierUtil.hpp"
49
50 #include "vktTestGroupUtil.hpp"
51 #include "vktTestCase.hpp"
52
53 #include "deDefs.h"
54 #include "deMath.h"
55 #include "deRandom.h"
56 #include "deSharedPtr.hpp"
57 #include "deString.h"
58
59 #include "tcuTestCase.hpp"
60 #include "tcuTestLog.hpp"
61 #include "tcuImageCompare.hpp"
62
63 #include <set>
64 #include <string>
65 #include <sstream>
66 #include <vector>
67 #include <algorithm>
68 #include <iterator>
69
70 namespace vkt
71 {
72 namespace FragmentShadingRate
73 {
74 namespace
75 {
76 using namespace vk;
77 using namespace std;
78
79 #define NUM_TRIANGLES (9 * 9)
80
81 enum class AttachmentUsage
82 {
83 NO_ATTACHMENT = 0,
84 NO_ATTACHMENT_PTR,
85 WITH_ATTACHMENT,
86 WITH_ATTACHMENT_WITHOUT_IMAGEVIEW, // No imageview at VkRenderingFragmentShadingRateAttachmentInfoKHR.
87 };
88
89 struct CaseDef
90 {
91 SharedGroupParams groupParams;
92 int32_t seed;
93 VkExtent2D framebufferDim;
94 VkSampleCountFlagBits samples;
95 VkFragmentShadingRateCombinerOpKHR combinerOp[2];
96 AttachmentUsage attachmentUsage;
97 bool shaderWritesRate;
98 bool geometryShader;
99 bool meshShader;
100 bool useDynamicState;
101 bool useApiSampleMask;
102 bool useSampleMaskIn;
103 bool conservativeEnable;
104 VkConservativeRasterizationModeEXT conservativeMode;
105 bool useDepthStencil; // == fragDepth || fragStencil
106 bool fragDepth;
107 bool fragStencil;
108 bool multiViewport;
109 bool colorLayered;
110 bool srLayered; // colorLayered must also be true
111 uint32_t numColorLayers;
112 bool multiView;
113 bool correlationMask;
114 bool interlock;
115 bool sampleLocations;
116 bool sampleShadingEnable;
117 bool sampleShadingInput;
118 bool sampleMaskTest;
119 bool earlyAndLateTest;
120 bool garbageAttachment;
121 bool dsClearOp;
122 uint32_t dsBaseMipLevel;
123 bool multiSubpasses;
124 bool maintenance6;
125
useAttachmentvkt::FragmentShadingRate::__anonf2ee18150111::CaseDef126 bool useAttachment() const
127 {
128 return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT);
129 }
130
useAttachmentWithoutImageViewvkt::FragmentShadingRate::__anonf2ee18150111::CaseDef131 bool useAttachmentWithoutImageView() const
132 {
133 return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW);
134 }
135 };
136
137 class FSRTestInstance : public TestInstance
138 {
139 public:
140 FSRTestInstance(Context &context, const CaseDef &data);
141 ~FSRTestInstance(void);
142 tcu::TestStatus iterate(void);
143
144 private:
145 // Test parameters
146 CaseDef m_data;
147
148 // Cache simulated combiner operations, to avoid recomputing per-sample
149 int32_t m_simulateValueCount;
150 vector<int32_t> m_simulateCache;
151 // Cache mapping of primitive ID to pipeline/primitive shading rate
152 vector<int32_t> m_primIDToPrimitiveShadingRate;
153 vector<int32_t> m_primIDToPipelineShadingRate;
154 uint32_t m_supportedFragmentShadingRateCount;
155 vector<VkPhysicalDeviceFragmentShadingRateKHR> m_supportedFragmentShadingRates;
156 VkPhysicalDeviceFragmentShadingRatePropertiesKHR m_shadingRateProperties;
157 #ifndef CTS_USES_VULKANSC
158 VkPhysicalDeviceMaintenance6PropertiesKHR m_maintenance6Properties;
159 #endif
160
161 protected:
162 void preRenderCommands(VkCommandBuffer cmdBuffer, ImageWithMemory *cbImage, ImageWithMemory *dsImage,
163 ImageWithMemory *secCbImage, ImageWithMemory *derivImage, uint32_t derivNumLevels,
164 ImageWithMemory *srImage, VkImageLayout srLayout, BufferWithMemory *srFillBuffer,
165 uint32_t numSRLayers, uint32_t srWidth, uint32_t srHeight, uint32_t srFillBpp,
166 const VkClearValue &clearColor, const VkClearValue &clearDepthStencil);
167 void beginLegacyRender(VkCommandBuffer cmdBuffer, RenderPassWrapper &renderPass, VkImageView srImageView,
168 VkImageView cbImageView, VkImageView dsImageView, VkImageView secCbImageView,
169 bool imagelessFB) const;
170 void drawCommands(VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
171 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
172 const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass,
173 const VkPipelineVertexInputStateCreateInfo *vertexInputState,
174 const VkPipelineDynamicStateCreateInfo *dynamicState,
175 const VkPipelineRasterizationStateCreateInfo *rasterizationState,
176 const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
177 const VkPipelineMultisampleStateCreateInfo *multisampleState,
178 VkPipelineFragmentShadingRateStateCreateInfoKHR *shadingRateState,
179 PipelineRenderingCreateInfoWrapper dynamicRenderingState, const ShaderWrapper vertShader,
180 const ShaderWrapper geomShader, const ShaderWrapper meshShader, const ShaderWrapper fragShader,
181 const std::vector<VkDescriptorSet> &descriptorSet, VkBuffer vertexBuffer,
182 const uint32_t pushConstantSize);
183
184 void copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer, const ImageWithMemory *image,
185 const BufferWithMemory *outputBuffer, const VkDeviceSize bufferSize);
186
187 void drawCommandsOnNormalSubpass(VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
188 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
189 const PipelineLayoutWrapper &pipelineLayout, const RenderPassWrapper &renderPass,
190 const VkPipelineRasterizationStateCreateInfo *rasterizationState,
191 const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
192 const VkPipelineMultisampleStateCreateInfo *multisampleState,
193 const ShaderWrapper &vertShader, const ShaderWrapper &fragShader,
194 const uint32_t subpass, VkBuffer vertexBuffer);
195
196 #ifndef CTS_USES_VULKANSC
197 void beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat cbFormat, VkFormat dsFormat,
198 VkRenderingFlagsKHR renderingFlags = 0u) const;
199 void beginDynamicRender(VkCommandBuffer cmdBuffer, VkImageView srImageView, VkImageLayout srImageLayout,
200 const VkExtent2D &srTexelSize, VkImageView cbImageView, VkImageView dsImageView,
201 const VkClearValue &clearColor, const VkClearValue &clearDepthStencil,
202 VkRenderingFlagsKHR renderingFlags = 0u) const;
203 #endif // CTS_USES_VULKANSC
204
205 int32_t PrimIDToPrimitiveShadingRate(int32_t primID);
206 int32_t PrimIDToPipelineShadingRate(int32_t primID);
207 VkExtent2D SanitizeExtent(VkExtent2D ext) const;
208 int32_t SanitizeRate(int32_t rate) const;
209 int32_t ShadingRateExtentToClampedMask(VkExtent2D ext) const;
210 int32_t ShadingRateExtentToEnum(VkExtent2D ext) const;
211 VkExtent2D ShadingRateEnumToExtent(int32_t rate) const;
212 int32_t Simulate(int32_t rate0, int32_t rate1, int32_t rate2);
213 VkExtent2D Combine(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const;
214 int32_t CombineMasks(int32_t rateMask0, int32_t rateMask1, VkFragmentShadingRateCombinerOpKHR comb,
215 bool allowUnclampedResult) const;
216 bool Force1x1() const;
217 };
218
FSRTestInstance(Context & context,const CaseDef & data)219 FSRTestInstance::FSRTestInstance(Context &context, const CaseDef &data)
220 : vkt::TestInstance(context)
221 , m_data(data)
222 , m_simulateValueCount(((4 * 4) | 4) + 1)
223 , m_simulateCache(m_simulateValueCount * m_simulateValueCount * m_simulateValueCount, ~0)
224 , m_primIDToPrimitiveShadingRate(NUM_TRIANGLES, ~0)
225 , m_primIDToPipelineShadingRate(NUM_TRIANGLES, ~0)
226 {
227 m_supportedFragmentShadingRateCount = 0;
228 m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(
229 m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, nullptr);
230
231 if (m_supportedFragmentShadingRateCount < 3)
232 TCU_THROW(TestError, "*pFragmentShadingRateCount too small");
233
234 m_supportedFragmentShadingRates.resize(m_supportedFragmentShadingRateCount);
235 for (uint32_t i = 0; i < m_supportedFragmentShadingRateCount; ++i)
236 {
237 m_supportedFragmentShadingRates[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR;
238 m_supportedFragmentShadingRates[i].pNext = nullptr;
239 }
240 m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(
241 m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, &m_supportedFragmentShadingRates[0]);
242
243 m_shadingRateProperties = m_context.getFragmentShadingRateProperties();
244 #ifndef CTS_USES_VULKANSC
245 m_maintenance6Properties = m_context.getMaintenance6Properties();
246 #endif
247 }
248
~FSRTestInstance(void)249 FSRTestInstance::~FSRTestInstance(void)
250 {
251 }
252
253 class FSRTestCase : public TestCase
254 {
255 public:
256 FSRTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
257 ~FSRTestCase(void);
258 virtual void initPrograms(SourceCollections &programCollection) const;
259 virtual TestInstance *createInstance(Context &context) const;
260 virtual void checkSupport(Context &context) const;
261
262 private:
263 CaseDef m_data;
264 };
265
FSRTestCase(tcu::TestContext & context,const char * name,const CaseDef data)266 FSRTestCase::FSRTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
267 : vkt::TestCase(context, name)
268 , m_data(data)
269 {
270 }
271
~FSRTestCase(void)272 FSRTestCase::~FSRTestCase(void)
273 {
274 }
275
Force1x1() const276 bool FSRTestInstance::Force1x1() const
277 {
278 if (m_data.useApiSampleMask && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
279 return true;
280
281 if (m_data.useSampleMaskIn && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderSampleMask)
282 return true;
283
284 if (m_data.conservativeEnable &&
285 !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithConservativeRasterization)
286 return true;
287
288 if (m_data.useDepthStencil &&
289 !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderDepthStencilWrites)
290 return true;
291
292 if (m_data.interlock &&
293 !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithFragmentShaderInterlock)
294 return true;
295
296 if (m_data.sampleLocations &&
297 !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithCustomSampleLocations)
298 return true;
299
300 if (m_data.sampleShadingEnable || m_data.sampleShadingInput)
301 return true;
302
303 return false;
304 }
305
306 static VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
307 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
308
309 static VkImageUsageFlags dsUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
310 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
311
checkSupport(Context & context) const312 void FSRTestCase::checkSupport(Context &context) const
313 {
314 context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
315
316 if (m_data.groupParams->useDynamicRendering)
317 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
318
319 if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
320 TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
321
322 if (m_data.shaderWritesRate && !context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate)
323 TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
324
325 if (!context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate &&
326 m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
327 TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
328
329 if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
330 m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
331 TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
332
333 const auto &vki = context.getInstanceInterface();
334 const auto physDev = context.getPhysicalDevice();
335
336 VkImageFormatProperties imageProperties;
337 VkResult result = vki.getPhysicalDeviceImageFormatProperties(physDev, VK_FORMAT_R32G32B32A32_UINT, VK_IMAGE_TYPE_2D,
338 VK_IMAGE_TILING_OPTIMAL, cbUsage, 0, &imageProperties);
339
340 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
341 TCU_THROW(NotSupportedError, "VK_FORMAT_R32G32B32A32_UINT not supported");
342
343 if (m_data.geometryShader)
344 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
345
346 if (!(imageProperties.sampleCounts & m_data.samples))
347 TCU_THROW(NotSupportedError, "color buffer sample count not supported");
348
349 if (m_data.numColorLayers > imageProperties.maxArrayLayers)
350 TCU_THROW(NotSupportedError, "color buffer layers not supported");
351
352 if (m_data.useAttachment() && !context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
353 TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
354
355 if (!context.getFragmentShadingRateProperties().fragmentShadingRateNonTrivialCombinerOps &&
356 ((m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR &&
357 m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
358 (m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR &&
359 m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
360 TCU_THROW(NotSupportedError, "fragmentShadingRateNonTrivialCombinerOps not supported");
361
362 if (m_data.conservativeEnable)
363 {
364 context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
365 if (m_data.conservativeMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT &&
366 !context.getConservativeRasterizationPropertiesEXT().primitiveUnderestimation)
367 TCU_THROW(NotSupportedError, "primitiveUnderestimation not supported");
368 }
369
370 if (m_data.fragStencil)
371 context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
372
373 if (m_data.multiViewport &&
374 !context.getFragmentShadingRateProperties().primitiveFragmentShadingRateWithMultipleViewports)
375 TCU_THROW(NotSupportedError, "primitiveFragmentShadingRateWithMultipleViewports not supported");
376
377 if (m_data.srLayered && !context.getFragmentShadingRateProperties().layeredShadingRateAttachments)
378 TCU_THROW(NotSupportedError, "layeredShadingRateAttachments not supported");
379
380 if ((m_data.multiViewport || m_data.colorLayered) && !m_data.geometryShader)
381 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
382
383 if (m_data.multiView && m_data.geometryShader && !context.getMultiviewFeatures().multiviewGeometryShader)
384 TCU_THROW(NotSupportedError, "multiviewGeometryShader not supported");
385
386 if (m_data.interlock && !context.getFragmentShaderInterlockFeaturesEXT().fragmentShaderPixelInterlock)
387 TCU_THROW(NotSupportedError, "fragmentShaderPixelInterlock not supported");
388
389 if (m_data.sampleLocations)
390 {
391 context.requireDeviceFunctionality("VK_EXT_sample_locations");
392 if (!(m_data.samples & context.getSampleLocationsPropertiesEXT().sampleLocationSampleCounts))
393 TCU_THROW(NotSupportedError, "samples not supported in sampleLocationSampleCounts");
394 }
395
396 if (m_data.sampleMaskTest && !context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
397 TCU_THROW(NotSupportedError, "fragmentShadingRateWithSampleMask not supported");
398
399 #ifndef CTS_USES_VULKANSC
400 if (m_data.meshShader)
401 {
402 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
403 const auto &meshFeatures = context.getMeshShaderFeaturesEXT();
404
405 if (m_data.shaderWritesRate && !meshFeatures.primitiveFragmentShadingRateMeshShader)
406 TCU_THROW(NotSupportedError, "primitiveFragmentShadingRateMeshShader not supported");
407
408 if (m_data.multiView && !meshFeatures.multiviewMeshShader)
409 TCU_THROW(NotSupportedError, "multiviewMeshShader not supported");
410 }
411
412 checkPipelineConstructionRequirements(vki, physDev, m_data.groupParams->pipelineConstructionType);
413
414 if (m_data.earlyAndLateTest)
415 {
416 context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
417 if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
418 TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
419 }
420
421 if (m_data.maintenance6)
422 context.requireDeviceFunctionality("VK_KHR_maintenance6");
423 #endif
424
425 if (m_data.sampleShadingEnable || m_data.sampleShadingInput)
426 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
427 }
428
429 // Error codes writted by the fragment shader
430 enum
431 {
432 ERROR_NONE = 0,
433 ERROR_FRAGCOORD_CENTER = 1,
434 ERROR_VTG_READBACK = 2,
435 ERROR_FRAGCOORD_DERIV = 3,
436 ERROR_FRAGCOORD_IMPLICIT_DERIV = 4,
437 };
438
initPrograms(SourceCollections & programCollection) const439 void FSRTestCase::initPrograms(SourceCollections &programCollection) const
440 {
441 if (!m_data.meshShader)
442 {
443 std::stringstream vss;
444
445 vss << "#version 450 core\n"
446 "#extension GL_EXT_fragment_shading_rate : enable\n"
447 "#extension GL_ARB_shader_viewport_layer_array : enable\n"
448 "layout(push_constant) uniform PC {\n"
449 " int shadingRate;\n"
450 "} pc;\n"
451 "layout(location = 0) in vec2 pos;\n"
452 "layout(location = 0) out int instanceIndex;\n"
453 "layout(location = 1) out int readbackok;\n"
454 "layout(location = 2) out float zero;\n"
455 "out gl_PerVertex\n"
456 "{\n"
457 " vec4 gl_Position;\n"
458 "};\n"
459 "void main()\n"
460 "{\n"
461 " gl_Position = vec4(pos, 0, 1);\n"
462 " instanceIndex = gl_InstanceIndex;\n"
463 " readbackok = 1;\n"
464 " zero = 0;\n";
465
466 if (m_data.shaderWritesRate)
467 {
468 vss << " gl_PrimitiveShadingRateEXT = pc.shadingRate;\n";
469
470 // Verify that we can read from the output variable
471 vss << " if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
472
473 if (!m_data.geometryShader)
474 {
475 if (m_data.multiViewport)
476 vss << " gl_ViewportIndex = instanceIndex & 1;\n";
477 if (m_data.colorLayered)
478 vss << " gl_Layer = ((instanceIndex & 2) >> 1);\n";
479 }
480 }
481
482 vss << "}\n";
483
484 programCollection.glslSources.add("vert") << glu::VertexSource(vss.str());
485 programCollection.glslSources.add("vert_1_2")
486 << glu::VertexSource(vss.str())
487 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
488
489 if (m_data.geometryShader)
490 {
491 std::string writeShadingRate = "";
492 if (m_data.shaderWritesRate)
493 {
494 writeShadingRate = " gl_PrimitiveShadingRateEXT = pc.shadingRate;\n"
495 " if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
496
497 if (m_data.multiViewport)
498 writeShadingRate += " gl_ViewportIndex = inInstanceIndex[0] & 1;\n";
499
500 if (m_data.colorLayered)
501 writeShadingRate += " gl_Layer = (inInstanceIndex[0] & 2) >> 1;\n";
502 }
503
504 std::stringstream gss;
505 gss << "#version 450 core\n"
506 "#extension GL_EXT_fragment_shading_rate : enable\n"
507 "\n"
508 "layout(push_constant) uniform PC {\n"
509 " int shadingRate;\n"
510 "} pc;\n"
511 "\n"
512 "in gl_PerVertex\n"
513 "{\n"
514 " vec4 gl_Position;\n"
515 "} gl_in[3];\n"
516 "\n"
517 "layout(location = 0) in int inInstanceIndex[];\n"
518 "layout(location = 0) out int outInstanceIndex;\n"
519 "layout(location = 1) out int readbackok;\n"
520 "layout(location = 2) out float zero;\n"
521 "layout(triangles) in;\n"
522 "layout(triangle_strip, max_vertices=3) out;\n"
523 "\n"
524 "out gl_PerVertex {\n"
525 " vec4 gl_Position;\n"
526 "};\n"
527 "\n"
528 "void main(void)\n"
529 "{\n"
530 " gl_Position = gl_in[0].gl_Position;\n"
531 " outInstanceIndex = inInstanceIndex[0];\n"
532 " readbackok = 1;\n"
533 " zero = 0;\n"
534 << writeShadingRate
535 << " EmitVertex();"
536 "\n"
537 " gl_Position = gl_in[1].gl_Position;\n"
538 " outInstanceIndex = inInstanceIndex[1];\n"
539 " readbackok = 1;\n"
540 " zero = 0;\n"
541 << writeShadingRate
542 << " EmitVertex();"
543 "\n"
544 " gl_Position = gl_in[2].gl_Position;\n"
545 " outInstanceIndex = inInstanceIndex[2];\n"
546 " readbackok = 1;\n"
547 " zero = 0;\n"
548 << writeShadingRate
549 << " EmitVertex();"
550 "}\n";
551
552 programCollection.glslSources.add("geom") << glu::GeometrySource(gss.str());
553 }
554 }
555 else
556 {
557 std::stringstream mss;
558
559 mss << "#version 450 core\n"
560 "#extension GL_EXT_mesh_shader : enable\n";
561
562 if (m_data.shaderWritesRate)
563 {
564 mss << "#extension GL_EXT_fragment_shading_rate : enable\n";
565 }
566
567 mss << "layout(local_size_x=3) in;\n"
568 "layout(triangles) out;\n"
569 "layout(max_vertices=3, max_primitives=1) out;\n"
570 "layout(push_constant, std430) uniform PC {\n"
571 " int shadingRate;\n"
572 " uint instanceIndex;\n"
573 "} pc;\n"
574 "layout(set=1, binding=0, std430) readonly buffer PosBuffer {\n"
575 " vec2 vertexPositions[];\n"
576 "} pb;\n"
577 "layout(location = 0) flat out int instanceIndex[];\n"
578 "layout(location = 1) flat out int readbackok[];\n"
579 "layout(location = 2) out float zero[];\n";
580
581 if (m_data.shaderWritesRate)
582 {
583 mss << "perprimitiveEXT out gl_MeshPerPrimitiveEXT {\n"
584 << (m_data.colorLayered ? " int gl_Layer;\n" : "")
585 << (m_data.multiViewport ? " int gl_ViewportIndex;\n" : "")
586 << " int gl_PrimitiveShadingRateEXT;\n"
587 "} gl_MeshPrimitivesEXT[];\n";
588 }
589
590 mss << "void main()\n"
591 "{\n"
592 " SetMeshOutputsEXT(3u, 1u);\n"
593 " const uint vertexIdx = (pc.instanceIndex * 3u + gl_LocalInvocationIndex);\n"
594 " gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(pb.vertexPositions[vertexIdx], 0, "
595 "1);\n"
596 " if (gl_LocalInvocationIndex == 0) {\n"
597 " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
598 " }\n"
599 " instanceIndex[gl_LocalInvocationIndex] = int(pc.instanceIndex);\n"
600 " readbackok[gl_LocalInvocationIndex] = 1;\n"
601 " zero[gl_LocalInvocationIndex] = 0;\n";
602
603 if (m_data.shaderWritesRate)
604 {
605 mss << " gl_MeshPrimitivesEXT[0].gl_PrimitiveShadingRateEXT = pc.shadingRate;\n";
606
607 // gl_MeshPerPrimitiveEXT is write-only in mesh shaders, so we cannot verify the readback operation.
608 //mss << " if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
609
610 if (m_data.multiViewport)
611 mss << " gl_MeshPrimitivesEXT[0].gl_ViewportIndex = int(pc.instanceIndex & 1);\n";
612 if (m_data.colorLayered)
613 mss << " gl_MeshPrimitivesEXT[0].gl_Layer = int((pc.instanceIndex & 2) >> 1);\n";
614 }
615
616 mss << "}\n";
617
618 const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
619 programCollection.glslSources.add("mesh") << glu::MeshSource(mss.str()) << buildOptions;
620 }
621
622 std::stringstream fss;
623
624 fss << "#version 450 core\n"
625 "#extension GL_EXT_fragment_shading_rate : enable\n"
626 "#extension GL_ARB_shader_stencil_export : enable\n"
627 "#extension GL_ARB_fragment_shader_interlock : enable\n";
628
629 if (m_data.earlyAndLateTest)
630 fss << "#extension GL_AMD_shader_early_and_late_fragment_tests : enable\n";
631
632 fss << "layout(location = 0) out uvec4 col0;\n"
633 "layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
634 "layout(set = 0, binding = 3) uniform usampler2D tex;\n"
635 "layout(location = 0) flat in int instanceIndex;\n"
636 "layout(location = 1) flat in int readbackok;\n"
637 "layout(location = 2) "
638 << (m_data.sampleShadingInput ? "sample " : "") << "in float zero;\n";
639
640 if (m_data.earlyAndLateTest)
641 fss << "layout(early_and_late_fragment_tests_amd) in;\n";
642
643 if (m_data.fragDepth && m_data.earlyAndLateTest)
644 fss << "layout(depth_less) out float gl_FragDepth;\n";
645
646 if (m_data.fragStencil && m_data.earlyAndLateTest)
647 fss << "layout(stencil_ref_less_front_amd) out int gl_FragStencilRefARB;\n";
648
649 if (m_data.interlock)
650 fss << "layout(pixel_interlock_ordered) in;\n";
651
652 fss << "void main()\n"
653 "{\n";
654
655 if (m_data.interlock)
656 fss << " beginInvocationInterlockARB();\n";
657
658 fss <<
659 // X component gets shading rate enum
660 " col0.x = gl_ShadingRateEXT;\n"
661 " col0.y = 0;\n"
662 // Z component gets packed primitiveID | atomic value
663 " col0.z = (instanceIndex << 24) | ((atomicAdd(buf.counter, 1) + 1) & 0x00FFFFFFu);\n"
664 " ivec2 fragCoordXY = ivec2(gl_FragCoord.xy);\n"
665 " ivec2 fragSize = ivec2(1<<((gl_ShadingRateEXT/4)&3), 1<<(gl_ShadingRateEXT&3));\n"
666 // W component gets error code
667 " col0.w = uint(zero)"
668 << (m_data.sampleShadingInput ? " * gl_SampleID" : "")
669 << ";\n"
670 " if (((fragCoordXY - fragSize / 2) % fragSize) != ivec2(0,0))\n"
671 " col0.w = "
672 << ERROR_FRAGCOORD_CENTER << ";\n";
673
674 if (m_data.shaderWritesRate)
675 {
676 fss << " if (readbackok != 1)\n"
677 " col0.w = "
678 << ERROR_VTG_READBACK << ";\n";
679 }
680
681 // When sample shading, gl_FragCoord is more likely to give bad derivatives,
682 // e.g. due to a partially covered quad having some pixels center sample and
683 // some sample at a sample location.
684 if (!m_data.sampleShadingEnable && !m_data.sampleShadingInput)
685 {
686 fss << " if (dFdx(gl_FragCoord.xy) != ivec2(fragSize.x, 0) || dFdy(gl_FragCoord.xy) != ivec2(0, fragSize.y))\n"
687 " col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (int(dFdx(gl_FragCoord.xy)) << 14) | "
688 "(int(dFdx(gl_FragCoord.xy)) << 8) | "
689 << ERROR_FRAGCOORD_DERIV << ";\n";
690
691 fss << " uint implicitDerivX = texture(tex, vec2(gl_FragCoord.x / textureSize(tex, 0).x, 0)).x;\n"
692 " uint implicitDerivY = texture(tex, vec2(0, gl_FragCoord.y / textureSize(tex, 0).y)).x;\n"
693 " if (implicitDerivX != fragSize.x || implicitDerivY != fragSize.y)\n"
694 " col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (implicitDerivY << 14) | (implicitDerivX << 8) "
695 "| "
696 << ERROR_FRAGCOORD_IMPLICIT_DERIV << ";\n";
697 }
698 // Y component gets sample mask value
699 if (m_data.useSampleMaskIn)
700 fss << " col0.y = gl_SampleMaskIn[0];\n";
701
702 if (m_data.fragDepth)
703 fss << " gl_FragDepth = float(instanceIndex) / float(" << NUM_TRIANGLES << ");\n";
704
705 if (m_data.fragStencil)
706 fss << " gl_FragStencilRefARB = instanceIndex;\n";
707
708 if (m_data.interlock)
709 fss << " endInvocationInterlockARB();\n";
710
711 fss << "}\n";
712
713 programCollection.glslSources.add("frag") << glu::FragmentSource(fss.str());
714
715 std::stringstream css;
716
717 std::string fsampType = m_data.samples > 1 ? "texture2DMSArray" : "texture2DArray";
718 std::string usampType = m_data.samples > 1 ? "utexture2DMSArray" : "utexture2DArray";
719
720 // Compute shader copies color/depth/stencil to linear layout in buffer memory
721 css << "#version 450 core\n"
722 "#extension GL_EXT_samplerless_texture_functions : enable\n"
723 "layout(set = 0, binding = 1) uniform "
724 << usampType
725 << " colorTex;\n"
726 "layout(set = 0, binding = 2, std430) buffer Block0 { uvec4 b[]; } colorbuf;\n"
727 "layout(set = 0, binding = 4, std430) buffer Block1 { float b[]; } depthbuf;\n"
728 "layout(set = 0, binding = 5, std430) buffer Block2 { uint b[]; } stencilbuf;\n"
729 "layout(set = 0, binding = 6) uniform "
730 << fsampType
731 << " depthTex;\n"
732 "layout(set = 0, binding = 7) uniform "
733 << usampType
734 << " stencilTex;\n"
735 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
736 "void main()\n"
737 "{\n"
738 " for (int i = 0; i < "
739 << m_data.samples
740 << "; ++i) {\n"
741 " uint idx = ((gl_GlobalInvocationID.z * "
742 << m_data.framebufferDim.height << " + gl_GlobalInvocationID.y) * " << m_data.framebufferDim.width
743 << " + gl_GlobalInvocationID.x) * " << m_data.samples
744 << " + i;\n"
745 " colorbuf.b[idx] = texelFetch(colorTex, ivec3(gl_GlobalInvocationID.xyz), i);\n";
746
747 if (m_data.fragDepth)
748 css << " depthbuf.b[idx] = texelFetch(depthTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
749
750 if (m_data.fragStencil)
751 css << " stencilbuf.b[idx] = texelFetch(stencilTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
752
753 css << " }\n"
754 "}\n";
755
756 programCollection.glslSources.add("comp") << glu::ComputeSource(css.str());
757
758 // Vertex shader for simple rendering without FSR on another subpass
759 {
760 std::ostringstream src;
761 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
762 << "\n"
763 << "layout(location = 0) in vec4 in_position;\n"
764 << "\n"
765 << "out gl_PerVertex {\n"
766 << " vec4 gl_Position;\n"
767 << "};\n"
768 << "\n"
769 << "void main(void)\n"
770 << "{\n"
771 << " gl_Position = in_position;\n"
772 << "}\n";
773
774 programCollection.glslSources.add("vert_simple") << glu::VertexSource(src.str());
775 }
776
777 // Fragment shader for simple rendering without FSR on another subpass
778 {
779 std::ostringstream src;
780 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
781 << "\n"
782 << "#extension GL_EXT_fragment_shading_rate : enable\n"
783 << "#extension GL_ARB_shader_stencil_export : enable\n"
784 << "\n"
785 << "layout(location = 0) out uvec4 o_color;\n"
786 << "\n"
787 << "void main(void)\n"
788 << "{\n"
789 << " if (gl_ShadingRateEXT == 0)\n"
790 << " o_color = uvec4(128, 128, 128, 1);\n"
791 << " else\n"
792 << " o_color = uvec4(255, 0, 0, 1);\n"
793 << "\n";
794
795 if (m_data.fragDepth)
796 {
797 src << " if (gl_ShadingRateEXT == 0)\n"
798 << " gl_FragDepth = 0.4;\n"
799 << " else\n"
800 << " gl_FragDepth = 0.2;\n"
801 << "\n";
802 }
803 if (m_data.fragStencil)
804 {
805 src << " if (gl_ShadingRateEXT == 0)\n"
806 << " gl_FragStencilRefARB = 1;\n"
807 << " else\n"
808 << " gl_FragStencilRefARB = 2;\n";
809 }
810
811 src << "}\n";
812
813 programCollection.glslSources.add("frag_simple") << glu::FragmentSource(src.str());
814 }
815 }
816
createInstance(Context & context) const817 TestInstance *FSRTestCase::createInstance(Context &context) const
818 {
819 return new FSRTestInstance(context, m_data);
820 }
821
ShadingRateExtentToEnum(VkExtent2D ext) const822 int32_t FSRTestInstance::ShadingRateExtentToEnum(VkExtent2D ext) const
823 {
824 ext.width = deCtz32(ext.width);
825 ext.height = deCtz32(ext.height);
826
827 return (ext.width << 2) | ext.height;
828 }
829
ShadingRateEnumToExtent(int32_t rate) const830 VkExtent2D FSRTestInstance::ShadingRateEnumToExtent(int32_t rate) const
831 {
832 VkExtent2D ret;
833 ret.width = 1 << ((rate / 4) & 3);
834 ret.height = 1 << (rate & 3);
835
836 return ret;
837 }
838
Combine(VkExtent2D ext0,VkExtent2D ext1,VkFragmentShadingRateCombinerOpKHR comb) const839 VkExtent2D FSRTestInstance::Combine(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const
840 {
841 VkExtent2D ret;
842 switch (comb)
843 {
844 default:
845 DE_ASSERT(0);
846 // fallthrough
847 case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR:
848 return ext0;
849 case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR:
850 return ext1;
851 case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR:
852 ret = {de::min(ext0.width, ext1.width), de::min(ext0.height, ext1.height)};
853 return ret;
854 case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR:
855 ret = {de::max(ext0.width, ext1.width), de::max(ext0.height, ext1.height)};
856 return ret;
857 case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR:
858 ret = {ext0.width * ext1.width, ext0.height * ext1.height};
859 if (!m_shadingRateProperties.fragmentShadingRateStrictMultiplyCombiner)
860 {
861 if (ext0.width == 1 && ext1.width == 1)
862 ret.width = 2;
863 if (ext0.height == 1 && ext1.height == 1)
864 ret.height = 2;
865 }
866 return ret;
867 }
868 }
869
CombineMasks(int32_t rateMask0,int32_t rateMask1,VkFragmentShadingRateCombinerOpKHR comb,bool allowUnclampedResult) const870 int32_t FSRTestInstance::CombineMasks(int32_t rateMask0, int32_t rateMask1, VkFragmentShadingRateCombinerOpKHR comb,
871 bool allowUnclampedResult) const
872 {
873 int32_t combinedMask = 0;
874
875 for (int i = 0; i < 16; i++)
876 {
877 if (rateMask0 & (1 << i))
878 {
879 VkExtent2D rate0 = ShadingRateEnumToExtent(i);
880
881 for (int j = 0; j < 16; j++)
882 {
883 if (rateMask1 & (1 << j))
884 {
885 VkExtent2D combinerResult = Combine(rate0, ShadingRateEnumToExtent(j), comb);
886 int32_t clampedResult = ShadingRateExtentToClampedMask(combinerResult);
887
888 if (allowUnclampedResult)
889 {
890 combinedMask |= 1 << ShadingRateExtentToEnum(combinerResult);
891 }
892
893 combinedMask |= clampedResult;
894 }
895 }
896 }
897 }
898
899 return combinedMask;
900 }
901
Simulate(int32_t rate0,int32_t rate1,int32_t rate2)902 int32_t FSRTestInstance::Simulate(int32_t rate0, int32_t rate1, int32_t rate2)
903 {
904 bool allowUnclampedInputs = true;
905
906 #ifndef CTS_USES_VULKANSC
907 if (m_data.maintenance6)
908 {
909 allowUnclampedInputs = !m_maintenance6Properties.fragmentShadingRateClampCombinerInputs;
910 }
911 #endif
912
913 int32_t &cachedRate = m_simulateCache[(rate2 * m_simulateValueCount + rate1) * m_simulateValueCount + rate0];
914 if (cachedRate != ~0)
915 return cachedRate;
916
917 const VkExtent2D extent0 = ShadingRateEnumToExtent(rate0);
918 const VkExtent2D extent1 = ShadingRateEnumToExtent(rate1);
919 const VkExtent2D extent2 = ShadingRateEnumToExtent(rate2);
920
921 int32_t finalMask = 0;
922
923 // Clamped and unclamped inputs.
924 const int32_t extentMask0 = ShadingRateExtentToClampedMask(extent0) | (1 << rate0);
925 const int32_t extentMask1 = ShadingRateExtentToClampedMask(extent1) | (1 << rate1);
926 const int32_t extentMask2 = ShadingRateExtentToClampedMask(extent2) | (1 << rate2);
927
928 // Combine rate 0 and 1, get a mask of possible clamped rates
929 int32_t intermedMask =
930 CombineMasks(extentMask0, extentMask1, m_data.combinerOp[0], allowUnclampedInputs /* allowUnclampedResult */);
931
932 // For each clamped rate, combine that with rate 2 and accumulate the possible clamped rates
933 for (int i = 0; i < 16; ++i)
934 {
935 if (intermedMask & (1 << i))
936 {
937 finalMask |=
938 CombineMasks(intermedMask, extentMask2, m_data.combinerOp[1], false /* allowUnclampedResult */);
939 }
940 }
941
942 if (Force1x1())
943 finalMask = 0x1;
944
945 cachedRate = finalMask;
946 return finalMask;
947 }
948
949 // If a rate is not valid (<=4x4), clamp it to something valid.
950 // This is only used for "inputs" to the system, not to mimic
951 // how the implementation internally clamps intermediate values.
SanitizeExtent(VkExtent2D ext) const952 VkExtent2D FSRTestInstance::SanitizeExtent(VkExtent2D ext) const
953 {
954 DE_ASSERT(ext.width > 0 && ext.height > 0);
955
956 ext.width = de::min(ext.width, 4u);
957 ext.height = de::min(ext.height, 4u);
958
959 return ext;
960 }
961
962 // Map an extent to a mask of all modes smaller than or equal to it in either dimension
ShadingRateExtentToClampedMask(VkExtent2D ext) const963 int32_t FSRTestInstance::ShadingRateExtentToClampedMask(VkExtent2D ext) const
964 {
965 const uint32_t shadingRateBit = (1 << ShadingRateExtentToEnum(ext));
966 uint32_t desiredSize = ext.width * ext.height;
967 int32_t mask = 0;
968 int32_t swappedSizesMask = 0;
969
970 while (desiredSize > 0)
971 {
972 // First, find modes that maximize the area
973 for (uint32_t i = 0; i < m_supportedFragmentShadingRateCount; ++i)
974 {
975 const VkPhysicalDeviceFragmentShadingRateKHR &supportedRate = m_supportedFragmentShadingRates[i];
976 if ((supportedRate.sampleCounts & m_data.samples) &&
977 supportedRate.fragmentSize.width * supportedRate.fragmentSize.height == desiredSize)
978 {
979 if (supportedRate.fragmentSize.width <= ext.width && supportedRate.fragmentSize.height <= ext.height)
980 {
981 mask |= 1 << ShadingRateExtentToEnum(supportedRate.fragmentSize);
982 }
983 else if (supportedRate.fragmentSize.height <= ext.width &&
984 supportedRate.fragmentSize.width <= ext.height)
985 {
986 swappedSizesMask |= 1 << ShadingRateExtentToEnum(supportedRate.fragmentSize);
987 }
988 }
989 }
990 if (mask)
991 {
992 // Amongst the modes that maximize the area, pick the ones that
993 // minimize the aspect ratio. Prefer ratio of 1, then 2, then 4.
994 // 1x1 = 0, 2x2 = 5, 4x4 = 10
995 static const uint32_t aspectMaskRatio1 = 0x421;
996 // 2x1 = 4, 1x2 = 1, 4x2 = 9, 2x4 = 6
997 static const uint32_t aspectMaskRatio2 = 0x252;
998 // 4x1 = 8, 1x4 = 2,
999 static const uint32_t aspectMaskRatio4 = 0x104;
1000
1001 if (mask & aspectMaskRatio1)
1002 {
1003 mask &= aspectMaskRatio1;
1004 break;
1005 }
1006 if (mask & aspectMaskRatio2)
1007 {
1008 mask &= aspectMaskRatio2;
1009 break;
1010 }
1011 if (mask & aspectMaskRatio4)
1012 {
1013 mask &= aspectMaskRatio4;
1014 break;
1015 }
1016 DE_ASSERT(0);
1017 }
1018 desiredSize /= 2;
1019 }
1020
1021 // Optionally include the sizes with swapped width and height.
1022 mask |= swappedSizesMask;
1023
1024 if (mask & shadingRateBit)
1025 {
1026 // The given shading rate is valid. Don't clamp it.
1027 return shadingRateBit;
1028 }
1029
1030 // Return alternative shading rates.
1031 return mask;
1032 }
1033
SanitizeRate(int32_t rate) const1034 int32_t FSRTestInstance::SanitizeRate(int32_t rate) const
1035 {
1036 VkExtent2D extent = ShadingRateEnumToExtent(rate);
1037
1038 extent = SanitizeExtent(extent);
1039
1040 return ShadingRateExtentToEnum(extent);
1041 }
1042
1043 // Map primID % 9 to primitive shading rate
PrimIDToPrimitiveShadingRate(int32_t primID)1044 int32_t FSRTestInstance::PrimIDToPrimitiveShadingRate(int32_t primID)
1045 {
1046 int32_t &cachedRate = m_primIDToPrimitiveShadingRate[primID];
1047 if (cachedRate != ~0)
1048 return cachedRate;
1049
1050 VkExtent2D extent;
1051 extent.width = 1 << (primID % 3);
1052 extent.height = 1 << ((primID / 3) % 3);
1053
1054 cachedRate = ShadingRateExtentToEnum(extent);
1055 return cachedRate;
1056 }
1057
1058 // Map primID / 9 to pipeline shading rate
PrimIDToPipelineShadingRate(int32_t primID)1059 int32_t FSRTestInstance::PrimIDToPipelineShadingRate(int32_t primID)
1060 {
1061 int32_t &cachedRate = m_primIDToPipelineShadingRate[primID];
1062 if (cachedRate != ~0)
1063 return cachedRate;
1064
1065 primID /= 9;
1066 VkExtent2D extent;
1067 extent.width = 1 << (primID % 3);
1068 extent.height = 1 << ((primID / 3) % 3);
1069
1070 cachedRate = ShadingRateExtentToEnum(extent);
1071 return cachedRate;
1072 }
1073
CreateCachedBuffer(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkBufferCreateInfo & bufferCreateInfo)1074 static de::MovePtr<BufferWithMemory> CreateCachedBuffer(const vk::DeviceInterface &vk, const vk::VkDevice device,
1075 vk::Allocator &allocator,
1076 const vk::VkBufferCreateInfo &bufferCreateInfo)
1077 {
1078 try
1079 {
1080 return de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1081 vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Cached));
1082 }
1083 catch (const tcu::NotSupportedError &)
1084 {
1085 return de::MovePtr<BufferWithMemory>(
1086 new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1087 }
1088 }
1089
iterate(void)1090 tcu::TestStatus FSRTestInstance::iterate(void)
1091 {
1092 const DeviceInterface &vk = m_context.getDeviceInterface();
1093 const VkDevice device = m_context.getDevice();
1094 tcu::TestLog &log = m_context.getTestContext().getLog();
1095 Allocator &allocator = m_context.getDefaultAllocator();
1096 VkFlags allShaderStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
1097 VkFlags allPipelineStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1098 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
1099 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
1100 VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1101 const VkFormat cbFormat = VK_FORMAT_R32G32B32A32_UINT;
1102 VkFormat dsFormat = VK_FORMAT_UNDEFINED;
1103 const auto vertBufferUsage =
1104 (m_data.meshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1105
1106 if (m_data.meshShader)
1107 {
1108 #ifndef CTS_USES_VULKANSC
1109 allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
1110 allPipelineStages |= VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT;
1111 #else
1112 DE_ASSERT(false);
1113 #endif // CTS_USES_VULKANSC
1114 }
1115 else
1116 {
1117 allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
1118 allPipelineStages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
1119
1120 if (m_data.geometryShader)
1121 {
1122 allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
1123 allPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
1124 }
1125 }
1126
1127 if (m_data.useDepthStencil)
1128 {
1129 VkFormatProperties formatProps;
1130 m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(),
1131 VK_FORMAT_D32_SFLOAT_S8_UINT, &formatProps);
1132 if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
1133 {
1134 dsFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
1135 }
1136 else
1137 {
1138 dsFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1139 }
1140 }
1141
1142 deRandom rnd;
1143 deRandom_init(&rnd, m_data.seed);
1144
1145 qpTestResult res = QP_TEST_RESULT_PASS;
1146 uint32_t numUnexpected1x1Samples = 0;
1147 uint32_t numTotalSamples = 0;
1148
1149 enum AttachmentModes
1150 {
1151 ATTACHMENT_MODE_DEFAULT = 0,
1152 ATTACHMENT_MODE_LAYOUT_OPTIMAL,
1153 ATTACHMENT_MODE_IMAGELESS,
1154 ATTACHMENT_MODE_2DARRAY,
1155 ATTACHMENT_MODE_TILING_LINEAR,
1156
1157 ATTACHMENT_MODE_COUNT,
1158 };
1159
1160 uint32_t numSRLayers = m_data.srLayered ? 2u : 1u;
1161
1162 VkExtent2D minFragmentShadingRateAttachmentTexelSize = {1, 1};
1163 VkExtent2D maxFragmentShadingRateAttachmentTexelSize = {1, 1};
1164 uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio = 1;
1165 if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
1166 {
1167 minFragmentShadingRateAttachmentTexelSize =
1168 m_context.getFragmentShadingRateProperties().minFragmentShadingRateAttachmentTexelSize;
1169 maxFragmentShadingRateAttachmentTexelSize =
1170 m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSize;
1171 maxFragmentShadingRateAttachmentTexelSizeAspectRatio =
1172 m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
1173 }
1174
1175 VkDeviceSize atomicBufferSize = sizeof(uint32_t);
1176
1177 de::MovePtr<BufferWithMemory> atomicBuffer;
1178 atomicBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1179 vk, device, allocator,
1180 makeBufferCreateInfo(atomicBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
1181 MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
1182
1183 uint32_t *abuf = (uint32_t *)atomicBuffer->getAllocation().getHostPtr();
1184
1185 // NUM_TRIANGLES triangles, 3 vertices, 2 components of float position
1186 VkDeviceSize vertexBufferSize = NUM_TRIANGLES * 3 * 2 * sizeof(float);
1187
1188 de::MovePtr<BufferWithMemory> vertexBuffer;
1189 vertexBuffer = de::MovePtr<BufferWithMemory>(
1190 new BufferWithMemory(vk, device, allocator,
1191 makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vertBufferUsage),
1192 MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
1193
1194 float *vbuf = (float *)vertexBuffer->getAllocation().getHostPtr();
1195 for (int32_t i = 0; i < (int32_t)(vertexBufferSize / sizeof(float)); ++i)
1196 {
1197 vbuf[i] = deRandom_getFloat(&rnd) * 2.0f - 1.0f;
1198 }
1199 flushAlloc(vk, device, vertexBuffer->getAllocation());
1200
1201 VkDeviceSize colorOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples *
1202 4 * sizeof(uint32_t) * m_data.numColorLayers;
1203 de::MovePtr<BufferWithMemory> colorOutputBuffer =
1204 CreateCachedBuffer(vk, device, allocator,
1205 makeBufferCreateInfo(colorOutputBufferSize,
1206 VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1207
1208 de::MovePtr<BufferWithMemory> secColorOutputBuffer = CreateCachedBuffer(
1209 vk, device, allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1210
1211 VkDeviceSize depthOutputBufferSize = 0, stencilOutputBufferSize = 0;
1212 de::MovePtr<BufferWithMemory> depthOutputBuffer, stencilOutputBuffer;
1213 if (m_data.useDepthStencil)
1214 {
1215 depthOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples *
1216 sizeof(float) * m_data.numColorLayers;
1217 depthOutputBuffer =
1218 CreateCachedBuffer(vk, device, allocator,
1219 makeBufferCreateInfo(depthOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT |
1220 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1221
1222 stencilOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples *
1223 sizeof(uint32_t) * m_data.numColorLayers;
1224 stencilOutputBuffer =
1225 CreateCachedBuffer(vk, device, allocator,
1226 makeBufferCreateInfo(stencilOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT |
1227 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1228 }
1229
1230 uint32_t minSRTexelWidth = minFragmentShadingRateAttachmentTexelSize.width;
1231 uint32_t minSRTexelHeight = minFragmentShadingRateAttachmentTexelSize.height;
1232 uint32_t maxSRWidth = (m_data.framebufferDim.width + minSRTexelWidth - 1) / minSRTexelWidth;
1233 uint32_t maxSRHeight = (m_data.framebufferDim.height + minSRTexelHeight - 1) / minSRTexelHeight;
1234
1235 // max size over all formats
1236 VkDeviceSize srFillBufferSize = numSRLayers * maxSRWidth * maxSRHeight * 32 /*4 component 64-bit*/;
1237 de::MovePtr<BufferWithMemory> srFillBuffer;
1238 uint8_t *fillPtr = nullptr;
1239 if (m_data.useAttachment())
1240 {
1241 srFillBuffer = CreateCachedBuffer(vk, device, allocator,
1242 makeBufferCreateInfo(srFillBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
1243 fillPtr = (uint8_t *)srFillBuffer->getAllocation().getHostPtr();
1244 }
1245
1246 de::MovePtr<ImageWithMemory> cbImage;
1247 Move<VkImageView> cbImageView;
1248 {
1249 const VkImageCreateInfo imageCreateInfo = {
1250 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1251 nullptr, // const void* pNext;
1252 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
1253 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1254 cbFormat, // VkFormat format;
1255 {
1256 m_data.framebufferDim.width, // uint32_t width;
1257 m_data.framebufferDim.height, // uint32_t height;
1258 1u // uint32_t depth;
1259 }, // VkExtent3D extent;
1260 1u, // uint32_t mipLevels;
1261 m_data.numColorLayers, // uint32_t arrayLayers;
1262 m_data.samples, // VkSampleCountFlagBits samples;
1263 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1264 cbUsage, // VkImageUsageFlags usage;
1265 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1266 0u, // uint32_t queueFamilyIndexCount;
1267 nullptr, // const uint32_t* pQueueFamilyIndices;
1268 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1269 };
1270 cbImage = de::MovePtr<ImageWithMemory>(
1271 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1272
1273 VkImageViewCreateInfo imageViewCreateInfo = {
1274 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1275 nullptr, // const void* pNext;
1276 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
1277 **cbImage, // VkImage image;
1278 VK_IMAGE_VIEW_TYPE_2D_ARRAY, // VkImageViewType viewType;
1279 cbFormat, // VkFormat format;
1280 {
1281 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1282 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1283 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1284 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
1285 }, // VkComponentMapping components;
1286 {
1287 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1288 0u, // uint32_t baseMipLevel;
1289 1u, // uint32_t levelCount;
1290 0u, // uint32_t baseArrayLayer;
1291 m_data.numColorLayers // uint32_t layerCount;
1292 } // VkImageSubresourceRange subresourceRange;
1293 };
1294 cbImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1295 }
1296
1297 de::MovePtr<ImageWithMemory> secCbImage;
1298 Move<VkImageView> secCbImageView;
1299 if (m_data.multiSubpasses)
1300 {
1301 const VkImageCreateInfo imageCreateInfo = {
1302 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1303 nullptr, // const void* pNext;
1304 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
1305 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1306 cbFormat, // VkFormat format;
1307 {
1308 m_data.framebufferDim.width, // uint32_t width;
1309 m_data.framebufferDim.height, // uint32_t height;
1310 1u // uint32_t depth;
1311 }, // VkExtent3D extent;
1312 1u, // uint32_t mipLevels;
1313 1u, // uint32_t arrayLayers;
1314 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1315 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1316 cbUsage, // VkImageUsageFlags usage;
1317 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1318 0u, // uint32_t queueFamilyIndexCount;
1319 nullptr, // const uint32_t* pQueueFamilyIndices;
1320 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1321 };
1322 secCbImage = de::MovePtr<ImageWithMemory>(
1323 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1324
1325 VkImageViewCreateInfo imageViewCreateInfo = {
1326 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1327 nullptr, // const void* pNext;
1328 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
1329 **secCbImage, // VkImage image;
1330 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
1331 cbFormat, // VkFormat format;
1332 {
1333 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1334 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1335 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1336 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
1337 }, // VkComponentMapping components;
1338 {
1339 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1340 0u, // uint32_t baseMipLevel;
1341 1u, // uint32_t levelCount;
1342 0u, // uint32_t baseArrayLayer;
1343 1u // uint32_t layerCount;
1344 } // VkImageSubresourceRange subresourceRange;
1345 };
1346 secCbImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1347 }
1348
1349 de::MovePtr<ImageWithMemory> dsImage;
1350 Move<VkImageView> dsImageView, dImageView, sImageView;
1351
1352 if (m_data.useDepthStencil)
1353 {
1354 const VkImageCreateInfo imageCreateInfo = {
1355 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1356 nullptr, // const void* pNext;
1357 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
1358 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1359 dsFormat, // VkFormat format;
1360 {
1361 m_data.framebufferDim.width * (1 << m_data.dsBaseMipLevel), // uint32_t width;
1362 m_data.framebufferDim.height * (1 << m_data.dsBaseMipLevel), // uint32_t height;
1363 1u // uint32_t depth;
1364 }, // VkExtent3D extent;
1365 m_data.dsBaseMipLevel + 1, // uint32_t mipLevels;
1366 m_data.numColorLayers, // uint32_t arrayLayers;
1367 m_data.samples, // VkSampleCountFlagBits samples;
1368 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1369 dsUsage, // VkImageUsageFlags usage;
1370 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1371 0u, // uint32_t queueFamilyIndexCount;
1372 nullptr, // const uint32_t* pQueueFamilyIndices;
1373 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1374 };
1375 dsImage = de::MovePtr<ImageWithMemory>(
1376 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1377
1378 VkImageViewCreateInfo imageViewCreateInfo = {
1379 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1380 nullptr, // const void* pNext;
1381 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
1382 **dsImage, // VkImage image;
1383 VK_IMAGE_VIEW_TYPE_2D_ARRAY, // VkImageViewType viewType;
1384 dsFormat, // VkFormat format;
1385 {
1386 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1387 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1388 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1389 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
1390 }, // VkComponentMapping components;
1391 {
1392 VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
1393 m_data.dsBaseMipLevel, // uint32_t baseMipLevel;
1394 1u, // uint32_t levelCount;
1395 0u, // uint32_t baseArrayLayer;
1396 m_data.numColorLayers // uint32_t layerCount;
1397 } // VkImageSubresourceRange subresourceRange;
1398 };
1399 dsImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1400 imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1401 dImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1402 imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
1403 sImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1404 }
1405
1406 // Image used to test implicit derivative calculations.
1407 // Filled with a value of 1<<lod.
1408 de::MovePtr<ImageWithMemory> derivImage;
1409 Move<VkImageView> derivImageView;
1410 VkImageUsageFlags derivUsage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1411
1412 uint32_t derivNumLevels;
1413 {
1414 uint32_t maxDim = de::max(m_context.getFragmentShadingRateProperties().maxFragmentSize.width,
1415 m_context.getFragmentShadingRateProperties().maxFragmentSize.height);
1416 derivNumLevels = 1 + deCtz32(maxDim);
1417 const VkImageCreateInfo imageCreateInfo = {
1418 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1419 nullptr, // const void* pNext;
1420 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
1421 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1422 VK_FORMAT_R32_UINT, // VkFormat format;
1423 {
1424 m_context.getFragmentShadingRateProperties().maxFragmentSize.width, // uint32_t width;
1425 m_context.getFragmentShadingRateProperties().maxFragmentSize.height, // uint32_t height;
1426 1u // uint32_t depth;
1427 }, // VkExtent3D extent;
1428 derivNumLevels, // uint32_t mipLevels;
1429 1u, // uint32_t arrayLayers;
1430 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1431 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1432 derivUsage, // VkImageUsageFlags usage;
1433 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1434 0u, // uint32_t queueFamilyIndexCount;
1435 nullptr, // const uint32_t* pQueueFamilyIndices;
1436 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1437 };
1438 derivImage = de::MovePtr<ImageWithMemory>(
1439 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1440
1441 VkImageViewCreateInfo imageViewCreateInfo = {
1442 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1443 nullptr, // const void* pNext;
1444 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
1445 **derivImage, // VkImage image;
1446 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
1447 VK_FORMAT_R32_UINT, // VkFormat format;
1448 {
1449 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1450 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1451 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1452 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
1453 }, // VkComponentMapping components;
1454 {
1455 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1456 0u, // uint32_t baseMipLevel;
1457 derivNumLevels, // uint32_t levelCount;
1458 0u, // uint32_t baseArrayLayer;
1459 1u // uint32_t layerCount;
1460 } // VkImageSubresourceRange subresourceRange;
1461 };
1462 derivImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1463 }
1464
1465 // sampler used with derivImage
1466 const struct VkSamplerCreateInfo samplerInfo = {
1467 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
1468 nullptr, // pNext
1469 0u, // flags
1470 VK_FILTER_NEAREST, // magFilter
1471 VK_FILTER_NEAREST, // minFilter
1472 VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode
1473 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
1474 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
1475 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
1476 0.0f, // mipLodBias
1477 VK_FALSE, // anisotropyEnable
1478 1.0f, // maxAnisotropy
1479 false, // compareEnable
1480 VK_COMPARE_OP_ALWAYS, // compareOp
1481 0.0f, // minLod
1482 (float)derivNumLevels, // maxLod
1483 VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // borderColor
1484 VK_FALSE, // unnormalizedCoords
1485 };
1486
1487 Move<VkSampler> sampler = createSampler(vk, device, &samplerInfo);
1488
1489 std::vector<Move<vk::VkDescriptorSetLayout>> descriptorSetLayouts;
1490 const VkDescriptorSetLayoutCreateFlags layoutCreateFlags = 0;
1491
1492 const VkDescriptorSetLayoutBinding bindings[] = {
1493 {
1494 0u, // binding
1495 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1496 1u, // descriptorCount
1497 allShaderStages, // stageFlags
1498 nullptr, // pImmutableSamplers
1499 },
1500 {
1501 1u, // binding
1502 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1503 1u, // descriptorCount
1504 allShaderStages, // stageFlags
1505 nullptr, // pImmutableSamplers
1506 },
1507 {
1508 2u, // binding
1509 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1510 1u, // descriptorCount
1511 allShaderStages, // stageFlags
1512 nullptr, // pImmutableSamplers
1513 },
1514 {
1515 3u, // binding
1516 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // descriptorType
1517 1u, // descriptorCount
1518 allShaderStages, // stageFlags
1519 nullptr, // pImmutableSamplers
1520 },
1521 {
1522 4u, // binding
1523 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1524 1u, // descriptorCount
1525 allShaderStages, // stageFlags
1526 nullptr, // pImmutableSamplers
1527 },
1528 {
1529 5u, // binding
1530 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1531 1u, // descriptorCount
1532 allShaderStages, // stageFlags
1533 nullptr, // pImmutableSamplers
1534 },
1535 {
1536 6u, // binding
1537 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1538 1u, // descriptorCount
1539 allShaderStages, // stageFlags
1540 nullptr, // pImmutableSamplers
1541 },
1542 {
1543 7u, // binding
1544 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1545 1u, // descriptorCount
1546 allShaderStages, // stageFlags
1547 nullptr, // pImmutableSamplers
1548 },
1549 };
1550
1551 // Create a layout and allocate a descriptor set for it.
1552 const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo = {
1553 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1554 nullptr, // pNext
1555 layoutCreateFlags, // flags
1556 static_cast<uint32_t>(de::arrayLength(bindings)), // bindingCount
1557 &bindings[0] // pBindings
1558 };
1559
1560 descriptorSetLayouts.push_back(vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo));
1561
1562 // Mesh shaders use set 1 binding 0 as the vertex buffer.
1563 if (m_data.meshShader)
1564 {
1565 #ifndef CTS_USES_VULKANSC
1566 const VkDescriptorSetLayoutBinding extraBinding = {
1567 0u, // binding
1568 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1569 1u, // descriptorCount
1570 VK_SHADER_STAGE_MESH_BIT_EXT, // stageFlags
1571 nullptr, // pImmutableSamplers
1572 };
1573
1574 const VkDescriptorSetLayoutCreateInfo extraSetLayoutCreateInfo = {
1575 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1576 nullptr, // pNext
1577 layoutCreateFlags, // flags
1578 1u, // bindingCount
1579 &extraBinding, // pBindings
1580 };
1581
1582 descriptorSetLayouts.push_back(vk::createDescriptorSetLayout(vk, device, &extraSetLayoutCreateInfo));
1583 #else
1584 DE_ASSERT(false);
1585 #endif // CTS_USES_VULKANSC
1586 }
1587
1588 const uint32_t numConstants = (m_data.meshShader ? 2u : 1u);
1589 const uint32_t pushConstantSize = (static_cast<uint32_t>(sizeof(int32_t)) * numConstants);
1590 const VkPushConstantRange pushConstantRange = {
1591 allShaderStages, // VkShaderStageFlags stageFlags;
1592 0u, // uint32_t offset;
1593 pushConstantSize, // uint32_t size;
1594 };
1595
1596 std::vector<VkDescriptorSetLayout> descriptorSetLayoutsRaw;
1597 descriptorSetLayoutsRaw.reserve(descriptorSetLayouts.size());
1598
1599 std::transform(begin(descriptorSetLayouts), end(descriptorSetLayouts), std::back_inserter(descriptorSetLayoutsRaw),
1600 [](const Move<VkDescriptorSetLayout> &elem) { return elem.get(); });
1601
1602 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
1603 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1604 nullptr, // pNext
1605 (VkPipelineLayoutCreateFlags)0,
1606 static_cast<uint32_t>(descriptorSetLayoutsRaw.size()), // setLayoutCount
1607 de::dataOrNull(descriptorSetLayoutsRaw), // pSetLayouts
1608 1u, // pushConstantRangeCount
1609 &pushConstantRange, // pPushConstantRanges
1610 };
1611
1612 PipelineLayoutWrapper pipelineLayout(m_data.groupParams->pipelineConstructionType, vk, device,
1613 &pipelineLayoutCreateInfo, NULL);
1614
1615 const Unique<VkShaderModule> cs(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
1616
1617 const VkPipelineShaderStageCreateInfo csShaderCreateInfo = {
1618 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1619 nullptr,
1620 (VkPipelineShaderStageCreateFlags)0,
1621 VK_SHADER_STAGE_COMPUTE_BIT, // stage
1622 *cs, // shader
1623 "main",
1624 nullptr, // pSpecializationInfo
1625 };
1626
1627 const VkComputePipelineCreateInfo pipelineCreateInfo = {
1628 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1629 nullptr,
1630 0u, // flags
1631 csShaderCreateInfo, // cs
1632 *pipelineLayout, // layout
1633 VK_NULL_HANDLE, // basePipelineHandle
1634 0u, // basePipelineIndex
1635 };
1636 Move<VkPipeline> computePipeline = createComputePipeline(vk, device, VK_NULL_HANDLE, &pipelineCreateInfo, NULL);
1637
1638 for (uint32_t modeIdx = 0; modeIdx < ATTACHMENT_MODE_COUNT; ++modeIdx)
1639 {
1640 // If we're not using an attachment, don't test all the different attachment modes
1641 if (modeIdx != ATTACHMENT_MODE_DEFAULT && !m_data.useAttachment())
1642 continue;
1643
1644 // Consider all uint formats possible
1645 static const VkFormat srFillFormats[] = {
1646 VK_FORMAT_R8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8B8_UINT, VK_FORMAT_R8G8B8A8_UINT,
1647 VK_FORMAT_R16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16B16_UINT, VK_FORMAT_R16G16B16A16_UINT,
1648 VK_FORMAT_R32_UINT, VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32A32_UINT,
1649 VK_FORMAT_R64_UINT, VK_FORMAT_R64G64_UINT, VK_FORMAT_R64G64B64_UINT, VK_FORMAT_R64G64B64A64_UINT,
1650 };
1651 // Only test all formats in the default mode
1652 uint32_t numFillFormats =
1653 modeIdx == ATTACHMENT_MODE_DEFAULT ? (uint32_t)(sizeof(srFillFormats) / sizeof(srFillFormats[0])) : 1u;
1654
1655 // Iterate over all supported tile sizes and formats
1656 for (uint32_t srTexelWidth = minFragmentShadingRateAttachmentTexelSize.width;
1657 srTexelWidth <= maxFragmentShadingRateAttachmentTexelSize.width; srTexelWidth *= 2)
1658 for (uint32_t srTexelHeight = minFragmentShadingRateAttachmentTexelSize.height;
1659 srTexelHeight <= maxFragmentShadingRateAttachmentTexelSize.height; srTexelHeight *= 2)
1660 for (uint32_t formatIdx = 0; formatIdx < numFillFormats; ++formatIdx)
1661 {
1662 uint32_t aspectRatio = (srTexelHeight > srTexelWidth) ? (srTexelHeight / srTexelWidth) :
1663 (srTexelWidth / srTexelHeight);
1664 if (aspectRatio > maxFragmentShadingRateAttachmentTexelSizeAspectRatio)
1665 continue;
1666
1667 // Go through the loop only once when not using an attachment
1668 if (!m_data.useAttachment() &&
1669 (srTexelWidth != minFragmentShadingRateAttachmentTexelSize.width ||
1670 srTexelHeight != minFragmentShadingRateAttachmentTexelSize.height || formatIdx != 0))
1671 continue;
1672
1673 bool imagelessFB = modeIdx == ATTACHMENT_MODE_IMAGELESS;
1674
1675 uint32_t srWidth = (m_data.framebufferDim.width + srTexelWidth - 1) / srTexelWidth;
1676 uint32_t srHeight = (m_data.framebufferDim.height + srTexelHeight - 1) / srTexelHeight;
1677
1678 VkFormat srFormat = srFillFormats[formatIdx];
1679 uint32_t srFillBpp = tcu::getPixelSize(mapVkFormat(srFormat));
1680
1681 VkImageLayout srLayout = modeIdx == ATTACHMENT_MODE_LAYOUT_OPTIMAL ?
1682 VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR :
1683 VK_IMAGE_LAYOUT_GENERAL;
1684 VkImageViewType srViewType =
1685 modeIdx == ATTACHMENT_MODE_2DARRAY ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
1686 VkImageTiling srTiling =
1687 (modeIdx == ATTACHMENT_MODE_TILING_LINEAR) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1688
1689 VkFormatProperties srFormatProperties;
1690 m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(),
1691 srFormat, &srFormatProperties);
1692 VkFormatFeatureFlags srFormatFeatures = srTiling == VK_IMAGE_TILING_LINEAR ?
1693 srFormatProperties.linearTilingFeatures :
1694 srFormatProperties.optimalTilingFeatures;
1695
1696 if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
1697 !(srFormatFeatures & VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
1698 {
1699 if (srFormat == VK_FORMAT_R8_UINT && srTiling == VK_IMAGE_TILING_OPTIMAL)
1700 {
1701 log << tcu::TestLog::Message
1702 << "VK_FORMAT_R8_UINT/VK_IMAGE_TILING_OPTIMAL don't support "
1703 "VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"
1704 << tcu::TestLog::EndMessage;
1705 res = QP_TEST_RESULT_FAIL;
1706 }
1707 continue;
1708 }
1709
1710 Move<vk::VkDescriptorPool> descriptorPool;
1711 std::vector<Move<vk::VkDescriptorSet>> descriptorSets;
1712 VkDescriptorPoolCreateFlags poolCreateFlags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1713
1714 vk::DescriptorPoolBuilder poolBuilder;
1715 for (int32_t i = 0; i < (int32_t)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1716 poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1717 if (m_data.meshShader)
1718 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1719
1720 descriptorPool = poolBuilder.build(vk, device, poolCreateFlags,
1721 static_cast<uint32_t>(descriptorSetLayouts.size()));
1722 for (const auto &setLayout : descriptorSetLayouts)
1723 descriptorSets.push_back(makeDescriptorSet(vk, device, *descriptorPool, *setLayout));
1724
1725 const auto mainDescriptorSet = descriptorSets.front().get();
1726
1727 de::MovePtr<ImageWithMemory> srImage;
1728 Move<VkImageView> srImageView;
1729 VkImageUsageFlags srUsage = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
1730 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1731
1732 if (m_data.useAttachment())
1733 {
1734 const VkImageCreateInfo imageCreateInfo = {
1735 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1736 nullptr, // const void* pNext;
1737 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
1738 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1739 srFormat, // VkFormat format;
1740 {
1741 srWidth, // uint32_t width;
1742 srHeight, // uint32_t height;
1743 1u // uint32_t depth;
1744 }, // VkExtent3D extent;
1745 1u, // uint32_t mipLevels;
1746 numSRLayers, // uint32_t arrayLayers;
1747 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1748 srTiling, // VkImageTiling tiling;
1749 srUsage, // VkImageUsageFlags usage;
1750 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1751 0u, // uint32_t queueFamilyIndexCount;
1752 nullptr, // const uint32_t* pQueueFamilyIndices;
1753 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1754 };
1755 srImage = de::MovePtr<ImageWithMemory>(
1756 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1757
1758 VkImageViewCreateInfo imageViewCreateInfo = {
1759 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1760 nullptr, // const void* pNext;
1761 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
1762 **srImage, // VkImage image;
1763 srViewType, // VkImageViewType viewType;
1764 srFormat, // VkFormat format;
1765 {
1766 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
1767 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
1768 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
1769 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
1770 }, // VkComponentMapping components;
1771 {
1772 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1773 0u, // uint32_t baseMipLevel;
1774 1u, // uint32_t levelCount;
1775 0u, // uint32_t baseArrayLayer;
1776 srViewType == VK_IMAGE_VIEW_TYPE_2D ? 1 : numSRLayers, // uint32_t layerCount;
1777 } // VkImageSubresourceRange subresourceRange;
1778 };
1779 srImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1780 }
1781
1782 VkDescriptorImageInfo imageInfo;
1783 VkDescriptorBufferInfo bufferInfo;
1784
1785 VkWriteDescriptorSet w = {
1786 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1787 nullptr, // pNext
1788 descriptorSets.front().get(), // dstSet
1789 (uint32_t)0, // dstBinding
1790 0, // dstArrayElement
1791 1u, // descriptorCount
1792 bindings[0].descriptorType, // descriptorType
1793 &imageInfo, // pImageInfo
1794 &bufferInfo, // pBufferInfo
1795 nullptr, // pTexelBufferView
1796 };
1797
1798 abuf[0] = 0;
1799 flushAlloc(vk, device, atomicBuffer->getAllocation());
1800
1801 bufferInfo = makeDescriptorBufferInfo(**atomicBuffer, 0, atomicBufferSize);
1802 w.dstBinding = 0;
1803 w.descriptorType = bindings[0].descriptorType;
1804 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1805
1806 imageInfo = makeDescriptorImageInfo(VK_NULL_HANDLE, *cbImageView, VK_IMAGE_LAYOUT_GENERAL);
1807 w.dstBinding = 1;
1808 w.descriptorType = bindings[1].descriptorType;
1809 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1810
1811 bufferInfo = makeDescriptorBufferInfo(**colorOutputBuffer, 0, colorOutputBufferSize);
1812 w.dstBinding = 2;
1813 w.descriptorType = bindings[2].descriptorType;
1814 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1815
1816 imageInfo = makeDescriptorImageInfo(*sampler, *derivImageView, VK_IMAGE_LAYOUT_GENERAL);
1817 w.dstBinding = 3;
1818 w.descriptorType = bindings[3].descriptorType;
1819 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1820
1821 if (m_data.useDepthStencil)
1822 {
1823 bufferInfo = makeDescriptorBufferInfo(**depthOutputBuffer, 0, depthOutputBufferSize);
1824 w.dstBinding = 4;
1825 w.descriptorType = bindings[4].descriptorType;
1826 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1827
1828 bufferInfo = makeDescriptorBufferInfo(**stencilOutputBuffer, 0, stencilOutputBufferSize);
1829 w.dstBinding = 5;
1830 w.descriptorType = bindings[5].descriptorType;
1831 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1832
1833 imageInfo = makeDescriptorImageInfo(VK_NULL_HANDLE, *dImageView, VK_IMAGE_LAYOUT_GENERAL);
1834 w.dstBinding = 6;
1835 w.descriptorType = bindings[6].descriptorType;
1836 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1837
1838 imageInfo = makeDescriptorImageInfo(VK_NULL_HANDLE, *sImageView, VK_IMAGE_LAYOUT_GENERAL);
1839 w.dstBinding = 7;
1840 w.descriptorType = bindings[7].descriptorType;
1841 vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1842 }
1843
1844 // Update vertex buffer descriptor.
1845 if (m_data.meshShader)
1846 {
1847 const auto extraBufferInfo =
1848 makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
1849 const VkWriteDescriptorSet extraWrite = {
1850 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1851 nullptr, // pNext
1852 descriptorSets.back().get(), // dstSet
1853 (uint32_t)0, // dstBinding
1854 0, // dstArrayElement
1855 1u, // descriptorCount
1856 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1857 nullptr, // pImageInfo
1858 &extraBufferInfo, // pBufferInfo
1859 nullptr, // pTexelBufferView
1860 };
1861
1862 vk.updateDescriptorSets(device, 1u, &extraWrite, 0u, nullptr);
1863 }
1864
1865 RenderPassWrapper renderPass;
1866
1867 std::vector<VkImage> images;
1868 std::vector<VkImageView> attachments;
1869 images.push_back(**cbImage);
1870 attachments.push_back(*cbImageView);
1871 uint32_t dsAttachmentIdx = 0, srAttachmentIdx = 0, secAttachmentIdx = 0;
1872 if (m_data.useAttachment())
1873 {
1874 srAttachmentIdx = (uint32_t)attachments.size();
1875 images.push_back(**srImage);
1876 attachments.push_back(*srImageView);
1877 }
1878 if (m_data.useDepthStencil)
1879 {
1880 dsAttachmentIdx = (uint32_t)attachments.size();
1881 images.push_back(**dsImage);
1882 attachments.push_back(*dsImageView);
1883 }
1884 if (m_data.multiSubpasses)
1885 {
1886 secAttachmentIdx = (uint32_t)attachments.size();
1887 images.push_back(**secCbImage);
1888 attachments.push_back(*secCbImageView);
1889 }
1890
1891 if (!m_data.groupParams->useDynamicRendering)
1892 {
1893 const vk::VkAttachmentReference2 colorAttachmentReference{
1894 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1895 nullptr, // pNext
1896 0, // attachment
1897 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
1898 0, // aspectMask
1899 };
1900
1901 const vk::VkAttachmentReference2 colorAttachmentReference2{
1902 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1903 nullptr, // pNext
1904 secAttachmentIdx, // attachment
1905 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
1906 0, // aspectMask
1907 };
1908
1909 const vk::VkAttachmentReference2 fragmentShadingRateAttachment = {
1910 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1911 nullptr, // pNext
1912 srAttachmentIdx, // attachment
1913 srLayout, // layout
1914 0, // aspectMask
1915 };
1916
1917 const vk::VkAttachmentReference2 depthAttachmentReference = {
1918 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // sType
1919 nullptr, // pNext
1920 dsAttachmentIdx, // attachment
1921 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
1922 0, // aspectMask
1923 };
1924
1925 const bool noAttachmentPtr = (m_data.attachmentUsage == AttachmentUsage::NO_ATTACHMENT_PTR);
1926 const VkFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo = {
1927 VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, // VkStructureType sType;
1928 nullptr, // const void* pNext;
1929 (noAttachmentPtr ?
1930 nullptr :
1931 &fragmentShadingRateAttachment), // const VkAttachmentReference2* pFragmentShadingRateAttachment;
1932 {srTexelWidth, srTexelHeight}, // VkExtent2D shadingRateAttachmentTexelSize;
1933 };
1934
1935 const bool useAttachmentInfo = (m_data.attachmentUsage != AttachmentUsage::NO_ATTACHMENT);
1936 const VkSubpassDescription2 subpassDesc = {
1937 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // sType
1938 (useAttachmentInfo ? &shadingRateAttachmentInfo : nullptr), // pNext;
1939 (vk::VkSubpassDescriptionFlags)0, // flags
1940 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
1941 m_data.multiView ? 0x3 : 0u, // viewMask
1942 0u, // inputCount
1943 nullptr, // pInputAttachments
1944 1, // colorCount
1945 &colorAttachmentReference, // pColorAttachments
1946 nullptr, // pResolveAttachments
1947 m_data.useDepthStencil ? &depthAttachmentReference : nullptr, // depthStencilAttachment
1948 0u, // preserveCount
1949 nullptr, // pPreserveAttachments
1950 };
1951
1952 const VkSubpassDescription2 secSubpassDesc = {
1953 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // sType
1954 nullptr, // pNext;
1955 (vk::VkSubpassDescriptionFlags)0, // flags
1956 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
1957 0u, // viewMask
1958 0u, // inputCount
1959 nullptr, // pInputAttachments
1960 1, // colorCount
1961 &colorAttachmentReference2, // pColorAttachments
1962 nullptr, // pResolveAttachments
1963 m_data.useDepthStencil ? &depthAttachmentReference : nullptr, // depthStencilAttachment
1964 0u, // preserveCount
1965 nullptr, // pPreserveAttachments
1966 };
1967
1968 std::vector<VkSubpassDescription2> subpassDescriptions = {subpassDesc};
1969
1970 if (m_data.multiSubpasses)
1971 subpassDescriptions.push_back(secSubpassDesc);
1972
1973 std::vector<VkAttachmentDescription2> attachmentDescriptions{{
1974 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1975 nullptr, // const void* pNext;
1976 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
1977 cbFormat, // VkFormat format;
1978 m_data.samples, // VkSampleCountFlagBits samples;
1979 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
1980 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1981 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1982 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1983 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
1984 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout;
1985 }};
1986
1987 std::vector<VkSubpassDependency2> subpassDependencies;
1988
1989 if (m_data.useAttachment())
1990 attachmentDescriptions.push_back({
1991 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1992 nullptr, // const void* pNext;
1993 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
1994 srFormat, // VkFormat format;
1995 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1996 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
1997 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1998 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1999 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
2000 srLayout, // VkImageLayout initialLayout;
2001 srLayout // VkImageLayout finalLayout;
2002 });
2003
2004 if (m_data.useDepthStencil)
2005 {
2006 attachmentDescriptions.push_back({
2007 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
2008 nullptr, // const void* pNext;
2009 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
2010 dsFormat, // VkFormat format;
2011 m_data.samples, // VkSampleCountFlagBits samples;
2012 (m_data.dsClearOp // VkAttachmentLoadOp loadOp;
2013 ?
2014 VK_ATTACHMENT_LOAD_OP_CLEAR :
2015 VK_ATTACHMENT_LOAD_OP_LOAD),
2016 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
2017 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp stencilLoadOp;
2018 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
2019 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
2020 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout;
2021 });
2022 }
2023
2024 if (m_data.multiSubpasses)
2025 {
2026 attachmentDescriptions.push_back({
2027 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
2028 nullptr, // const void* pNext;
2029 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
2030 cbFormat, // VkFormat format;
2031 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
2032 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
2033 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
2034 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
2035 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
2036 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
2037 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout;
2038 });
2039
2040 subpassDependencies.push_back({
2041 VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, // VkStructureType sType;
2042 nullptr, // const void* pNext;
2043 VK_SUBPASS_EXTERNAL, // uint32_t srcSubpass;
2044 0, // uint32_t srcSubpass;
2045 0, // VkPipelineStageFlags srcStageMask;
2046 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2047 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
2048 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags dstStageMask;
2049 0, // VkAccessFlags srcAccessMask;
2050 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2051 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
2052 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
2053 0 // int32_t viewOffset;
2054 });
2055
2056 subpassDependencies.push_back({
2057 VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, // VkStructureType sType;
2058 nullptr, // const void* pNext;
2059 0, // uint32_t srcSubpass;
2060 1, // uint32_t dstSubpass;
2061 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2062 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask;
2063 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2064 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags dstStageMask;
2065 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2066 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // VkAccessFlags srcAccessMask;
2067 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2068 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
2069 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
2070 0 // int32_t viewOffset;
2071 });
2072 }
2073
2074 const uint32_t correlatedViewMask = 0x3;
2075 const VkRenderPassCreateInfo2 renderPassParams = {
2076 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // sType
2077 nullptr, // pNext
2078 (vk::VkRenderPassCreateFlags)0,
2079 (uint32_t)attachmentDescriptions.size(), // attachmentCount
2080 &attachmentDescriptions[0], // pAttachments
2081 (uint32_t)subpassDescriptions.size(), // subpassCount
2082 &subpassDescriptions[0], // pSubpasses
2083 (uint32_t)subpassDependencies.size(), // dependencyCount
2084 m_data.multiSubpasses ? &subpassDependencies[0] : nullptr, // pDependencies
2085 m_data.correlationMask, // correlatedViewMaskCount
2086 m_data.correlationMask ? &correlatedViewMask : nullptr // pCorrelatedViewMasks
2087 };
2088
2089 renderPass = RenderPassWrapper(m_data.groupParams->pipelineConstructionType, vk, device,
2090 &renderPassParams);
2091
2092 std::vector<VkFramebufferAttachmentImageInfo> framebufferAttachmentImageInfo;
2093 framebufferAttachmentImageInfo.push_back({
2094 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, // VkStructureType sType;
2095 nullptr, // const void* pNext;
2096 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
2097 cbUsage, // VkImageUsageFlags usage;
2098 m_data.framebufferDim.width, // uint32_t width;
2099 m_data.framebufferDim.height, // uint32_t height;
2100 m_data.numColorLayers, // uint32_t layerCount;
2101 1u, // uint32_t viewFormatCount;
2102 &cbFormat // const VkFormat* pViewFormats;
2103 });
2104 if (m_data.useAttachment())
2105 framebufferAttachmentImageInfo.push_back({
2106 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, // VkStructureType sType;
2107 nullptr, // const void* pNext;
2108 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
2109 srUsage, // VkImageUsageFlags usage;
2110 srWidth, // uint32_t width;
2111 srHeight, // uint32_t height;
2112 srViewType == VK_IMAGE_VIEW_TYPE_2D ? 1 : numSRLayers, // uint32_t layerCount;
2113 1u, // uint32_t viewFormatCount;
2114 &srFormat // const VkFormat* pViewFormats;
2115 });
2116
2117 if (m_data.useDepthStencil)
2118 framebufferAttachmentImageInfo.push_back({
2119 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, // VkStructureType sType;
2120 nullptr, // const void* pNext;
2121 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
2122 dsUsage, // VkImageUsageFlags usage;
2123 m_data.framebufferDim.width, // uint32_t width;
2124 m_data.framebufferDim.height, // uint32_t height;
2125 m_data.numColorLayers, // uint32_t layerCount;
2126 1u, // uint32_t viewFormatCount;
2127 &dsFormat // const VkFormat* pViewFormats;
2128 });
2129
2130 if (m_data.multiSubpasses)
2131 framebufferAttachmentImageInfo.push_back({
2132 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, // VkStructureType sType;
2133 nullptr, // const void* pNext;
2134 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
2135 cbUsage, // VkImageUsageFlags usage;
2136 m_data.framebufferDim.width, // uint32_t width;
2137 m_data.framebufferDim.height, // uint32_t height;
2138 1u, // uint32_t layerCount;
2139 1u, // uint32_t viewFormatCount;
2140 &cbFormat // const VkFormat* pViewFormats;
2141 });
2142
2143 const VkFramebufferAttachmentsCreateInfo framebufferAttachmentsCreateInfo = {
2144 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, // VkStructureType sType;
2145 nullptr, // const void* pNext;
2146 (uint32_t)framebufferAttachmentImageInfo.size(), // uint32_t attachmentImageInfoCount;
2147 &framebufferAttachmentImageInfo
2148 [0] // const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos;
2149 };
2150
2151 const vk::VkFramebufferCreateInfo framebufferParams = {
2152 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
2153 imagelessFB ? &framebufferAttachmentsCreateInfo : nullptr, // pNext
2154 (vk::VkFramebufferCreateFlags)(imagelessFB ? VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT : 0),
2155 *renderPass, // renderPass
2156 (uint32_t)attachments.size(), // attachmentCount
2157 imagelessFB ? nullptr : &attachments[0], // pAttachments
2158 m_data.framebufferDim.width, // width
2159 m_data.framebufferDim.height, // height
2160 m_data.multiView ? 1 : m_data.numColorLayers, // layers
2161 };
2162
2163 renderPass.createFramebuffer(vk, device, &framebufferParams, images);
2164 }
2165
2166 const VkVertexInputBindingDescription vertexBinding = {
2167 0u, // uint32_t binding;
2168 sizeof(float) * 2, // uint32_t stride;
2169 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
2170 };
2171 const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
2172 0u, // uint32_t location;
2173 0u, // uint32_t binding;
2174 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
2175 0u // uint32_t offset;
2176 };
2177
2178 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
2179 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2180 nullptr, // const void* pNext;
2181 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
2182 1u, // uint32_t vertexBindingDescriptionCount;
2183 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2184 1u, // uint32_t vertexAttributeDescriptionCount;
2185 &vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
2186 };
2187
2188 const VkPipelineRasterizationConservativeStateCreateInfoEXT consRastState = {
2189 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT, // VkStructureType sType;
2190 nullptr, // const void* pNext;
2191 (VkPipelineRasterizationConservativeStateCreateFlagsEXT)0, // VkPipelineRasterizationConservativeStateCreateFlagsEXT flags;
2192 m_data.conservativeMode, // VkConservativeRasterizationModeEXT conservativeRasterizationMode;
2193 0.0f, // float extraPrimitiveOverestimationSize;
2194 };
2195
2196 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
2197 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2198 m_data.conservativeEnable ? &consRastState : nullptr, // const void* pNext;
2199 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
2200 VK_FALSE, // VkBool32 depthClampEnable;
2201 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
2202 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
2203 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
2204 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
2205 VK_FALSE, // VkBool32 depthBiasEnable;
2206 0.0f, // float depthBiasConstantFactor;
2207 0.0f, // float depthBiasClamp;
2208 0.0f, // float depthBiasSlopeFactor;
2209 1.0f // float lineWidth;
2210 };
2211
2212 // Kill some bits from each AA mode
2213 const VkSampleMask sampleMask = m_data.sampleMaskTest ? 0x9 : 0x7D56;
2214 const VkSampleMask *pSampleMask = m_data.useApiSampleMask ? &sampleMask : nullptr;
2215
2216 // All samples at pixel center. We'll validate that pixels are fully covered or uncovered.
2217 std::vector<VkSampleLocationEXT> sampleLocations(m_data.samples, {0.5f, 0.5f});
2218 const VkSampleLocationsInfoEXT sampleLocationsInfo = {
2219 VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, // VkStructureType sType;
2220 nullptr, // const void* pNext;
2221 (VkSampleCountFlagBits)m_data.samples, // VkSampleCountFlagBits sampleLocationsPerPixel;
2222 {1, 1}, // VkExtent2D sampleLocationGridSize;
2223 (uint32_t)m_data.samples, // uint32_t sampleLocationsCount;
2224 &sampleLocations[0], // const VkSampleLocationEXT* pSampleLocations;
2225 };
2226
2227 const VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo = {
2228 VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT, // VkStructureType sType;
2229 nullptr, // const void* pNext;
2230 VK_TRUE, // VkBool32 sampleLocationsEnable;
2231 sampleLocationsInfo, // VkSampleLocationsInfoEXT sampleLocationsInfo;
2232 };
2233
2234 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
2235 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
2236 m_data.sampleLocations ? &pipelineSampleLocationsCreateInfo :
2237 nullptr, // const void* pNext
2238 0u, // VkPipelineMultisampleStateCreateFlags flags
2239 (VkSampleCountFlagBits)
2240 m_data.samples, // VkSampleCountFlagBits rasterizationSamples
2241 (VkBool32)m_data
2242 .sampleShadingEnable, // VkBool32 sampleShadingEnable
2243 1.0f, // float minSampleShading
2244 pSampleMask, // const VkSampleMask* pSampleMask
2245 VK_FALSE, // VkBool32 alphaToCoverageEnable
2246 VK_FALSE // VkBool32 alphaToOneEnable
2247 };
2248
2249 std::vector<VkViewport> viewports;
2250 std::vector<VkRect2D> scissors;
2251 if (m_data.multiViewport)
2252 {
2253 // Split the viewport into left and right halves
2254 int x0 = 0, x1 = m_data.framebufferDim.width / 2, x2 = m_data.framebufferDim.width;
2255
2256 viewports.push_back(makeViewport((float)x0, 0, std::max((float)(x1 - x0), 1.0f),
2257 (float)m_data.framebufferDim.height, 0.0f, 1.0f));
2258 scissors.push_back(makeRect2D(x0, 0, x1 - x0, m_data.framebufferDim.height));
2259
2260 viewports.push_back(makeViewport((float)x1, 0, std::max((float)(x2 - x1), 1.0f),
2261 (float)m_data.framebufferDim.height, 0.0f, 1.0f));
2262 scissors.push_back(makeRect2D(x1, 0, x2 - x1, m_data.framebufferDim.height));
2263 }
2264 else
2265 {
2266 viewports.push_back(makeViewport(m_data.framebufferDim.width, m_data.framebufferDim.height));
2267 scissors.push_back(makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height));
2268 }
2269
2270 const auto &binaries = m_context.getBinaryCollection();
2271 ShaderWrapper fragShader = ShaderWrapper(vk, device, binaries.get("frag"), 0);
2272 ShaderWrapper vertShader;
2273 ShaderWrapper geomShader;
2274 ShaderWrapper meshShader;
2275
2276 if (m_data.meshShader)
2277 {
2278 meshShader = ShaderWrapper(vk, device, binaries.get("mesh"), 0);
2279 }
2280 else
2281 {
2282 if (m_context.contextSupports(VK_API_VERSION_1_2))
2283 vertShader = ShaderWrapper(vk, device, binaries.get("vert_1_2"), 0);
2284 else
2285 vertShader = ShaderWrapper(vk, device, binaries.get("vert"), 0);
2286
2287 if (m_data.geometryShader)
2288 geomShader = ShaderWrapper(vk, device, binaries.get("geom"), 0);
2289 }
2290
2291 const uint32_t fragSizeWH = m_data.sampleMaskTest ? 2 : 1;
2292
2293 PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
2294 #ifndef CTS_USES_VULKANSC
2295 VkPipelineRenderingCreateInfoKHR renderingCreateInfo{
2296 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
2297 nullptr,
2298 m_data.multiView ? 0x3 : 0u,
2299 1u,
2300 &cbFormat,
2301 dsFormat,
2302 dsFormat};
2303 renderingCreateInfoWrapper.ptr =
2304 m_data.groupParams->useDynamicRendering ? &renderingCreateInfo : nullptr;
2305 #endif // CTS_USES_VULKANSC
2306
2307 VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo{
2308 VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
2309 renderingCreateInfoWrapper.ptr, // const void* pNext;
2310 {fragSizeWH, fragSizeWH}, // VkExtent2D fragmentSize;
2311 {m_data.combinerOp[0],
2312 m_data.combinerOp[1]}, // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
2313 };
2314
2315 VkDynamicState dynamicState = VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR;
2316 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{
2317 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
2318 nullptr, // const void* pNext;
2319 (VkPipelineDynamicStateCreateFlags)0, // VkPipelineDynamicStateCreateFlags flags;
2320 m_data.useDynamicState ? 1u : 0u, // uint32_t dynamicStateCount;
2321 &dynamicState, // const VkDynamicState* pDynamicStates;
2322 };
2323
2324 // Enable depth/stencil writes, always passing
2325 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams{
2326 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
2327 nullptr, // const void* pNext;
2328 0u, // VkPipelineDepthStencilStateCreateFlags flags;
2329 VK_TRUE, // VkBool32 depthTestEnable;
2330 VK_TRUE, // VkBool32 depthWriteEnable;
2331 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
2332 VK_FALSE, // VkBool32 depthBoundsTestEnable;
2333 VK_TRUE, // VkBool32 stencilTestEnable;
2334 // VkStencilOpState front;
2335 {
2336 VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
2337 VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
2338 VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
2339 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
2340 0u, // uint32_t compareMask;
2341 0xFFu, // uint32_t writeMask;
2342 0xFFu, // uint32_t reference;
2343 },
2344 // VkStencilOpState back;
2345 {
2346 VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
2347 VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
2348 VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
2349 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
2350 0u, // uint32_t compareMask;
2351 0xFFu, // uint32_t writeMask;
2352 0xFFu, // uint32_t reference;
2353 },
2354 0.0f, // float minDepthBounds;
2355 0.0f, // float maxDepthBounds;
2356 };
2357
2358 const VkQueue queue = m_context.getUniversalQueue();
2359 Move<VkCommandPool> cmdPool =
2360 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
2361 m_context.getUniversalQueueFamilyIndex());
2362 Move<VkCommandBuffer> cmdBuffer =
2363 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2364 Move<VkCommandBuffer> secCmdBuffer;
2365 VkClearValue clearColor = makeClearValueColorU32(0, 0, 0, 0);
2366 VkClearValue clearDepthStencil = makeClearValueDepthStencil(0.0, 0);
2367
2368 std::vector<GraphicsPipelineWrapper> pipelines;
2369 uint32_t pipelineCount =
2370 (m_data.useDynamicState ? 1u : NUM_TRIANGLES) + (m_data.multiSubpasses ? 1u : 0u);
2371 pipelines.reserve(pipelineCount);
2372
2373 std::vector<VkDescriptorSet> descriptorSetsRaw;
2374
2375 descriptorSetsRaw.reserve(descriptorSets.size());
2376
2377 std::transform(begin(descriptorSets), end(descriptorSets), std::back_inserter(descriptorSetsRaw),
2378 [](const Move<VkDescriptorSet> &elem) { return elem.get(); });
2379
2380 #ifndef CTS_USES_VULKANSC
2381 const VkExtent2D srTexelSize{srTexelWidth, srTexelHeight};
2382 if (m_data.groupParams->useSecondaryCmdBuffer)
2383 {
2384 secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2385
2386 // record secondary command buffer
2387 if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2388 {
2389 beginSecondaryCmdBuffer(*secCmdBuffer, cbFormat, dsFormat,
2390 VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
2391 beginDynamicRender(*secCmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView,
2392 *dsImageView, clearColor, clearDepthStencil);
2393 }
2394 else
2395 beginSecondaryCmdBuffer(*secCmdBuffer, cbFormat, dsFormat);
2396
2397 drawCommands(*secCmdBuffer, pipelines, viewports, scissors, pipelineLayout, *renderPass,
2398 &vertexInputStateCreateInfo, &dynamicStateCreateInfo,
2399 &rasterizationStateCreateInfo, &depthStencilStateParams,
2400 &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2401 renderingCreateInfoWrapper, vertShader, geomShader, meshShader, fragShader,
2402 descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2403
2404 if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2405 endRendering(vk, *secCmdBuffer);
2406
2407 endCommandBuffer(vk, *secCmdBuffer);
2408
2409 // record primary command buffer
2410 beginCommandBuffer(vk, *cmdBuffer, 0u);
2411
2412 preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), secCbImage.get(), derivImage.get(),
2413 derivNumLevels, srImage.get(), srLayout, srFillBuffer.get(), numSRLayers,
2414 srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2415 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2416 beginDynamicRender(*cmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView,
2417 *dsImageView, clearColor, clearDepthStencil,
2418 VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR);
2419
2420 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
2421
2422 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2423 endRendering(vk, *cmdBuffer);
2424 }
2425 else if (m_data.groupParams->useDynamicRendering)
2426 {
2427 beginCommandBuffer(vk, *cmdBuffer);
2428 preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), secCbImage.get(), derivImage.get(),
2429 derivNumLevels, srImage.get(), srLayout, srFillBuffer.get(), numSRLayers,
2430 srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2431 beginDynamicRender(*cmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView, *dsImageView,
2432 clearColor, clearDepthStencil);
2433 drawCommands(*cmdBuffer, pipelines, viewports, scissors, pipelineLayout, *renderPass,
2434 &vertexInputStateCreateInfo, &dynamicStateCreateInfo,
2435 &rasterizationStateCreateInfo, &depthStencilStateParams,
2436 &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2437 renderingCreateInfoWrapper, vertShader, geomShader, meshShader, fragShader,
2438 descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2439 endRendering(vk, *cmdBuffer);
2440 }
2441 #endif // CTS_USES_VULKANSC
2442
2443 de::MovePtr<BufferWithMemory> secVertexBuf;
2444 secVertexBuf = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
2445 vk, device, allocator,
2446 makeBufferCreateInfo(vertexBufferSize,
2447 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
2448 MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
2449
2450 vector<tcu::Vec4> vertices;
2451 vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
2452 vertices.push_back(tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f));
2453 vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
2454 vertices.push_back(tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
2455
2456 const VkDeviceSize vertexBufferSize2 = vertices.size() * sizeof(vertices[0]);
2457
2458 float *vbuf2 = (float *)secVertexBuf->getAllocation().getHostPtr();
2459 deMemcpy(vbuf2, &vertices[0], static_cast<std::size_t>(vertexBufferSize2));
2460 flushAlloc(vk, device, secVertexBuf->getAllocation());
2461
2462 ShaderWrapper fragSimpleShader = ShaderWrapper(vk, device, binaries.get("frag_simple"), 0);
2463 ShaderWrapper vertSimpleShader = ShaderWrapper(vk, device, binaries.get("vert_simple"), 0);
2464
2465 PipelineLayoutWrapper pipelineLayout1(m_data.groupParams->pipelineConstructionType, vk, device);
2466
2467 if (!m_data.groupParams->useDynamicRendering)
2468 {
2469 beginCommandBuffer(vk, *cmdBuffer);
2470 preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), secCbImage.get(), derivImage.get(),
2471 derivNumLevels, srImage.get(), srLayout, srFillBuffer.get(), numSRLayers,
2472 srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2473
2474 beginLegacyRender(*cmdBuffer, renderPass, *srImageView, *cbImageView, *dsImageView,
2475 *secCbImageView, imagelessFB);
2476 drawCommands(*cmdBuffer, pipelines, viewports, scissors, pipelineLayout, *renderPass,
2477 &vertexInputStateCreateInfo, &dynamicStateCreateInfo,
2478 &rasterizationStateCreateInfo, &depthStencilStateParams,
2479 &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2480 renderingCreateInfoWrapper, vertShader, geomShader, meshShader, fragShader,
2481 descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2482
2483 if (m_data.multiSubpasses)
2484 {
2485 drawCommandsOnNormalSubpass(*cmdBuffer, pipelines, viewports, scissors, pipelineLayout1,
2486 renderPass, &rasterizationStateCreateInfo,
2487 &depthStencilStateParams, &multisampleStateCreateInfo,
2488 vertSimpleShader, fragSimpleShader, 1u, **secVertexBuf);
2489 }
2490
2491 renderPass.end(vk, *cmdBuffer);
2492
2493 if (m_data.multiSubpasses)
2494 copyImageToBufferOnNormalSubpass(*cmdBuffer, secCbImage.get(), secColorOutputBuffer.get(),
2495 colorOutputBufferSize);
2496 }
2497
2498 VkMemoryBarrier memBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, nullptr,
2499 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
2500 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2501 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
2502 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT};
2503 vk.cmdPipelineBarrier(*cmdBuffer, allPipelineStages, allPipelineStages, 0, 1, &memBarrier, 0,
2504 nullptr, 0, nullptr);
2505
2506 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1,
2507 &mainDescriptorSet, 0u, nullptr);
2508 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
2509
2510 // Copy color/depth/stencil buffers to buffer memory
2511 vk.cmdDispatch(*cmdBuffer, m_data.framebufferDim.width, m_data.framebufferDim.height,
2512 m_data.numColorLayers);
2513
2514 memBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2515 memBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2516 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2517 0, 1, &memBarrier, 0, nullptr, 0, nullptr);
2518
2519 endCommandBuffer(vk, *cmdBuffer);
2520
2521 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2522
2523 uint32_t *colorptr = (uint32_t *)colorOutputBuffer->getAllocation().getHostPtr();
2524 invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
2525
2526 invalidateAlloc(vk, device, atomicBuffer->getAllocation());
2527
2528 float *depthptr = nullptr;
2529 uint32_t *stencilptr = nullptr;
2530 uint32_t *secColorPtr = nullptr;
2531
2532 if (m_data.useDepthStencil)
2533 {
2534 depthptr = (float *)depthOutputBuffer->getAllocation().getHostPtr();
2535 invalidateAlloc(vk, device, depthOutputBuffer->getAllocation());
2536
2537 stencilptr = (uint32_t *)stencilOutputBuffer->getAllocation().getHostPtr();
2538 invalidateAlloc(vk, device, stencilOutputBuffer->getAllocation());
2539 }
2540
2541 if (m_data.multiSubpasses)
2542 {
2543 secColorPtr = (uint32_t *)secColorOutputBuffer->getAllocation().getHostPtr();
2544 invalidateAlloc(vk, device, secColorOutputBuffer->getAllocation());
2545 }
2546
2547 // Loop over all samples and validate the output
2548 for (uint32_t layer = 0; layer < m_data.numColorLayers && res == QP_TEST_RESULT_PASS; ++layer)
2549 {
2550 for (uint32_t y = 0; y < m_data.framebufferDim.height && res == QP_TEST_RESULT_PASS; ++y)
2551 {
2552 for (uint32_t x = 0; x < m_data.framebufferDim.width && res == QP_TEST_RESULT_PASS; ++x)
2553 {
2554 for (int32_t s = 0; s < m_data.samples && res == QP_TEST_RESULT_PASS; ++s)
2555 {
2556 uint32_t *sample = &colorptr[4 * (((layer * m_data.framebufferDim.height + y) *
2557 m_data.framebufferDim.width +
2558 x) *
2559 m_data.samples +
2560 s)];
2561
2562 // If testing the rasterizer sample mask, if this sample is not set in the
2563 // mask then it shouldn't have written anything.
2564 if (m_data.useApiSampleMask && !(sampleMask & (1 << s)) && sample[2] != 0)
2565 {
2566 log << tcu::TestLog::Message << std::hex
2567 << "sample written despite pSampleMask (" << x << "," << y << ",sample "
2568 << s << ")" << tcu::TestLog::EndMessage;
2569 res = QP_TEST_RESULT_FAIL;
2570 continue;
2571 }
2572
2573 // The same isn't covered by any primitives, skip it
2574 if (sample[2] == 0)
2575 continue;
2576
2577 // skip samples that have the same value as sample zero - it would be redundant to check them.
2578 if (s > 0)
2579 {
2580 uint32_t *sample0 = &colorptr[4 * (((layer * m_data.framebufferDim.height + y) *
2581 m_data.framebufferDim.width +
2582 x) *
2583 m_data.samples +
2584 0)];
2585 bool same = deMemCmp(sample, sample0, 16) == 0;
2586
2587 if (m_data.fragDepth && !m_data.multiSubpasses)
2588 {
2589 float *dsample = &depthptr[((layer * m_data.framebufferDim.height + y) *
2590 m_data.framebufferDim.width +
2591 x) *
2592 m_data.samples +
2593 s];
2594 float *dsample0 = &depthptr[((layer * m_data.framebufferDim.height + y) *
2595 m_data.framebufferDim.width +
2596 x) *
2597 m_data.samples +
2598 0];
2599 same = same && (*dsample == *dsample0);
2600 }
2601
2602 if (m_data.fragStencil && !m_data.multiSubpasses)
2603 {
2604 uint32_t *ssample =
2605 &stencilptr[((layer * m_data.framebufferDim.height + y) *
2606 m_data.framebufferDim.width +
2607 x) *
2608 m_data.samples +
2609 s];
2610 uint32_t *ssample0 =
2611 &stencilptr[((layer * m_data.framebufferDim.height + y) *
2612 m_data.framebufferDim.width +
2613 x) *
2614 m_data.samples +
2615 0];
2616 same = same && (*ssample == *ssample0);
2617 }
2618
2619 if (same)
2620 continue;
2621 }
2622
2623 // Fragment shader writes error codes to .w component.
2624 // All nonzero values are unconditionally failures
2625 if (sample[3] != 0)
2626 {
2627 if (sample[3] == ERROR_FRAGCOORD_CENTER)
2628 log << tcu::TestLog::Message << std::hex
2629 << "fragcoord test failed pixel (0x" << x << ",0x" << y << ",sample 0x"
2630 << s << ")" << tcu::TestLog::EndMessage;
2631 else if (sample[3] == ERROR_VTG_READBACK)
2632 log << tcu::TestLog::Message << std::hex
2633 << "vs/gs output readback test failed pixel (0x" << x << ",0x" << y
2634 << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2635 else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_DERIV)
2636 log << tcu::TestLog::Message << std::hex
2637 << "fragcoord derivative test failed pixel (0x" << x << ",0x" << y
2638 << ",sample 0x" << s
2639 << ")="
2640 "(0x"
2641 << ((sample[3] >> 8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F)
2642 << "), expected="
2643 "(0x"
2644 << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F)
2645 << ")" << tcu::TestLog::EndMessage;
2646 else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_IMPLICIT_DERIV)
2647 log << tcu::TestLog::Message << std::hex
2648 << "implicit derivative test failed pixel (0x" << x << ",0x" << y
2649 << ",sample 0x" << s
2650 << ")="
2651 "(0x"
2652 << ((sample[3] >> 8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F)
2653 << "), expected="
2654 "(0x"
2655 << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F)
2656 << ")" << tcu::TestLog::EndMessage;
2657 else
2658 log << tcu::TestLog::Message << std::hex
2659 << "w coord unknown test failed pixel (0x" << x << ",0x" << y
2660 << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2661 res = QP_TEST_RESULT_FAIL;
2662 continue;
2663 }
2664
2665 // x component of sample
2666 uint32_t rate = sample[0];
2667 // fragment size
2668 uint32_t pixelsX = 1 << ((rate / 4) & 3);
2669 uint32_t pixelsY = 1 << (rate & 3);
2670
2671 // Fragment region
2672 uint32_t fragMinX = x & ~(pixelsX - 1);
2673 uint32_t fragMinY = y & ~(pixelsY - 1);
2674 uint32_t fragMaxX = fragMinX + pixelsX;
2675 uint32_t fragMaxY = fragMinY + pixelsY;
2676
2677 // Clamp to FB dimension for odd sizes
2678 if (fragMaxX > m_data.framebufferDim.width)
2679 fragMaxX = m_data.framebufferDim.width;
2680 if (fragMaxY > m_data.framebufferDim.height)
2681 fragMaxY = m_data.framebufferDim.height;
2682
2683 // z component of sample
2684 uint32_t primID = sample[2] >> 24;
2685 uint32_t atomVal = sample[2] & 0xFFFFFF;
2686
2687 // Compute pipeline and primitive rate from primitive ID, and attachment
2688 // rate from the x/y coordinate
2689 int32_t pipelineRate = PrimIDToPipelineShadingRate(primID);
2690 int32_t primitiveRate =
2691 m_data.shaderWritesRate ? PrimIDToPrimitiveShadingRate(primID) : 0;
2692
2693 int32_t attachmentLayer =
2694 (m_data.srLayered && modeIdx == ATTACHMENT_MODE_2DARRAY) ? layer : 0;
2695 int32_t attachmentRate =
2696 m_data.useAttachment() ?
2697 fillPtr[srFillBpp *
2698 ((attachmentLayer * srHeight + (y / srTexelHeight)) * srWidth +
2699 (x / srTexelWidth))] :
2700 0;
2701
2702 // Get mask of allowed shading rates
2703 int32_t expectedMasks = Simulate(pipelineRate, primitiveRate, attachmentRate);
2704
2705 if (!(expectedMasks & (1 << rate)))
2706 {
2707 log << tcu::TestLog::Message << std::hex
2708 << "unexpected shading rate. failed pixel (0x" << x << ",0x" << y
2709 << ",sample 0x" << s
2710 << ") "
2711 "result rate 0x"
2712 << rate << " mask of expected rates 0x" << expectedMasks
2713 << " pipelineRate=0x" << pipelineRate << " primitiveRate=0x"
2714 << primitiveRate << " attachmentRate =0x" << attachmentRate
2715 << tcu::TestLog::EndMessage;
2716 res = QP_TEST_RESULT_FAIL;
2717 continue;
2718 }
2719 // Check that not all fragments are downgraded to 1x1
2720 if (rate == 0 && expectedMasks != 1)
2721 numUnexpected1x1Samples++;
2722 numTotalSamples++;
2723
2724 // Check that gl_FragDepth = primID / NUM_TRIANGLES
2725 if (m_data.fragDepth && !m_data.multiSubpasses)
2726 {
2727 float *dsample = &depthptr[((layer * m_data.framebufferDim.height + y) *
2728 m_data.framebufferDim.width +
2729 x) *
2730 m_data.samples +
2731 s];
2732 float expected = (float)primID / NUM_TRIANGLES;
2733 if (fabs(*dsample - expected) > 0.01)
2734 {
2735 log << tcu::TestLog::Message << std::hex << "depth write failed pixel (0x"
2736 << x << ",0x" << y << ",sample 0x" << s << ")=" << *dsample
2737 << " expected " << expected << tcu::TestLog::EndMessage;
2738 res = QP_TEST_RESULT_FAIL;
2739 continue;
2740 }
2741 }
2742
2743 // Check that stencil value = primID
2744 if (m_data.fragStencil && !m_data.multiSubpasses)
2745 {
2746 uint32_t *ssample = &stencilptr[((layer * m_data.framebufferDim.height + y) *
2747 m_data.framebufferDim.width +
2748 x) *
2749 m_data.samples +
2750 s];
2751 if (*ssample != primID)
2752 {
2753 log << tcu::TestLog::Message << std::hex << "stencil write failed pixel (0x"
2754 << x << ",0x" << y << ",sample 0x" << s << ")=" << *ssample
2755 << " expected " << primID << tcu::TestLog::EndMessage;
2756 res = QP_TEST_RESULT_FAIL;
2757 continue;
2758 }
2759 }
2760
2761 // Check that primitives are in the right viewport/scissor
2762 if (m_data.multiViewport)
2763 {
2764 VkRect2D *scissor = &scissors[primID & 1];
2765 if ((int)x < scissor->offset.x ||
2766 (int)x >= (int)(scissor->offset.x + scissor->extent.width) ||
2767 (int)y < scissor->offset.y ||
2768 (int)y >= (int)(scissor->offset.y + scissor->extent.height))
2769 {
2770 log << tcu::TestLog::Message << std::hex
2771 << "primitive found outside of expected viewport (0x" << x << ",0x" << y
2772 << ",sample 0x" << s << ") primID=" << primID
2773 << tcu::TestLog::EndMessage;
2774 res = QP_TEST_RESULT_FAIL;
2775 continue;
2776 }
2777 }
2778
2779 // Check that primitives are in the right layer
2780 if (m_data.colorLayered)
2781 {
2782 if (layer != ((primID & 2) >> 1))
2783 {
2784 log << tcu::TestLog::Message << std::hex
2785 << "primitive found in wrong layer (0x" << x << ",0x" << y
2786 << ",sample 0x" << s << ") primID=" << primID << " layer=" << layer
2787 << tcu::TestLog::EndMessage;
2788 res = QP_TEST_RESULT_FAIL;
2789 continue;
2790 }
2791 }
2792
2793 // Check that multiview broadcasts the same primitive to both layers
2794 if (m_data.multiView)
2795 {
2796 uint32_t otherLayer = layer ^ 1;
2797 uint32_t *othersample =
2798 &colorptr[4 * (((otherLayer * m_data.framebufferDim.height + y) *
2799 m_data.framebufferDim.width +
2800 x) *
2801 m_data.samples +
2802 s)];
2803 uint32_t otherPrimID = othersample[2] >> 24;
2804 if (primID != otherPrimID)
2805 {
2806 log << tcu::TestLog::Message << std::hex
2807 << "multiview primitive mismatch (0x" << x << ",0x" << y << ",sample 0x"
2808 << s << ") primID=" << primID << " otherPrimID=" << otherPrimID
2809 << tcu::TestLog::EndMessage;
2810 res = QP_TEST_RESULT_FAIL;
2811 continue;
2812 }
2813 }
2814
2815 // Loop over all samples in the same fragment
2816 for (uint32_t fx = fragMinX; fx < fragMaxX; ++fx)
2817 {
2818 for (uint32_t fy = fragMinY; fy < fragMaxY; ++fy)
2819 {
2820 for (int32_t fs = 0; fs < m_data.samples; ++fs)
2821 {
2822 uint32_t *fsample =
2823 &colorptr[4 * (((layer * m_data.framebufferDim.height + fy) *
2824 m_data.framebufferDim.width +
2825 fx) *
2826 m_data.samples +
2827 fs)];
2828 uint32_t frate = fsample[0];
2829 uint32_t fprimID = fsample[2] >> 24;
2830 uint32_t fatomVal = fsample[2] & 0xFFFFFF;
2831
2832 // If we write out the sample mask value, check that the samples in the
2833 // mask must not be uncovered, and that samples not in the mask must not
2834 // be covered by this primitive
2835 if (m_data.useSampleMaskIn)
2836 {
2837 int p = pixelsX * pixelsY -
2838 ((fx - fragMinX) + pixelsX * (fy - fragMinY)) - 1;
2839 int sampleIdx = fs + m_data.samples * p;
2840
2841 if ((sample[1] & (1 << sampleIdx)) && fsample[2] == 0)
2842 {
2843 log << tcu::TestLog::Message << std::hex
2844 << "sample set in sampleMask but not written (0x" << fx
2845 << ",0x" << fy << ",sample 0x" << fs << ")"
2846 << tcu::TestLog::EndMessage;
2847 res = QP_TEST_RESULT_FAIL;
2848 continue;
2849 }
2850 if (!(sample[1] & (1 << sampleIdx)) && fsample[2] != 0 &&
2851 fprimID == primID)
2852 {
2853 log << tcu::TestLog::Message << std::hex
2854 << "sample not set in sampleMask but written with same "
2855 "primID (0x"
2856 << fx << ",0x" << fy << ",sample 0x" << fs << ")"
2857 << tcu::TestLog::EndMessage;
2858 res = QP_TEST_RESULT_FAIL;
2859 continue;
2860 }
2861 }
2862
2863 // If conservative raster is enabled, or custom sample locations all at the center, check that
2864 // samples in the same pixel must be covered.
2865 if (m_data.conservativeEnable ||
2866 (m_data.sampleLocations &&
2867 m_context.getFragmentShadingRateProperties()
2868 .fragmentShadingRateWithCustomSampleLocations))
2869 {
2870 // If it's in the same pixel, expect it to be fully covered.
2871 if (fx == x && fy == y && fsample[2] == 0)
2872 {
2873 log << tcu::TestLog::Message << std::hex
2874 << "pixel not fully covered (0x" << fx << ",0x" << fy
2875 << ",sample 0x" << fs << ")" << tcu::TestLog::EndMessage;
2876 res = QP_TEST_RESULT_FAIL;
2877 continue;
2878 }
2879 }
2880
2881 if (fsample[2] == 0)
2882 continue;
2883
2884 // If the primitive matches this sample, then it must have the same rate and
2885 // atomic value
2886 if (fprimID == primID)
2887 {
2888 if (rate != frate ||
2889 (atomVal != fatomVal &&
2890 !(m_data.sampleShadingEnable || m_data.sampleShadingInput)))
2891 {
2892 log << tcu::TestLog::Message << std::hex << "failed pixel (0x"
2893 << x << ",0x" << y << ",sample " << s << ")=0x"
2894 << ((primID << 24) | atomVal) << " compared to (0x" << fx
2895 << ",0x" << fy << ",sample " << fs << ")=0x"
2896 << ((fprimID << 24) | fatomVal) << " pipelineRate=0x"
2897 << pipelineRate << " primitiveRate=0x" << primitiveRate
2898 << " attachmentRate =0x" << attachmentRate
2899 << tcu::TestLog::EndMessage;
2900 res = QP_TEST_RESULT_FAIL;
2901 }
2902 }
2903 }
2904 }
2905 }
2906 }
2907 }
2908 }
2909 }
2910
2911 if (res == QP_TEST_RESULT_FAIL)
2912 break;
2913
2914 if (secColorPtr)
2915 {
2916 const tcu::TextureFormat format = mapVkFormat(cbFormat);
2917 const tcu::ConstPixelBufferAccess resultImage(format, m_data.framebufferDim.width,
2918 m_data.framebufferDim.height, 1, secColorPtr);
2919
2920 tcu::TextureLevel textureLevel(format, m_data.framebufferDim.width,
2921 m_data.framebufferDim.height, 1);
2922 const tcu::PixelBufferAccess expectedImage(textureLevel);
2923
2924 for (int z = 0; z < expectedImage.getDepth(); ++z)
2925 {
2926 for (int y = 0; y < expectedImage.getHeight(); ++y)
2927 {
2928 for (int x = 0; x < expectedImage.getWidth(); ++x)
2929 expectedImage.setPixel(tcu::UVec4(128, 128, 128, 1), x, y, z);
2930 }
2931 }
2932
2933 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image Comparison", "",
2934 expectedImage, resultImage, tcu::UVec4(1),
2935 tcu::COMPARE_LOG_RESULT))
2936 return tcu::TestStatus::fail("Fail");
2937
2938 for (uint32_t y = 0; y < m_data.framebufferDim.height && res == QP_TEST_RESULT_PASS; ++y)
2939 {
2940 for (uint32_t x = 0; x < m_data.framebufferDim.width && res == QP_TEST_RESULT_PASS; ++x)
2941 {
2942 if (m_data.fragDepth)
2943 {
2944 float *dsample = &depthptr[(y * m_data.framebufferDim.width + x)];
2945 if (*dsample != 0.4f)
2946 {
2947 log << tcu::TestLog::Message << std::hex
2948 << "On another subpass, depth write failed pixel (0x" << x << ",0x" << y
2949 << ",sample 0x1"
2950 << ")=" << *dsample << " expected 0.4f" << tcu::TestLog::EndMessage;
2951 res = QP_TEST_RESULT_FAIL;
2952 continue;
2953 }
2954 }
2955 if (m_data.fragStencil)
2956 {
2957 uint32_t *ssample = &stencilptr[y * m_data.framebufferDim.width + x];
2958 if (*ssample != 1)
2959 {
2960 log << tcu::TestLog::Message << std::hex
2961 << "On another subpass, stencil write failed pixel (0x" << x << ",0x" << y
2962 << ",sample 0x1"
2963 << ")=" << *ssample << " expected 1" << tcu::TestLog::EndMessage;
2964 res = QP_TEST_RESULT_FAIL;
2965 continue;
2966 }
2967 }
2968 }
2969 }
2970 }
2971
2972 if (res == QP_TEST_RESULT_FAIL)
2973 break;
2974 }
2975 }
2976 // All samples were coerced to 1x1, unexpected
2977 if (res == QP_TEST_RESULT_PASS && numTotalSamples != 0 && numUnexpected1x1Samples == numTotalSamples &&
2978 numTotalSamples > 16)
2979 {
2980 log << tcu::TestLog::Message << std::hex << "Quality warning - all fragments used 1x1"
2981 << tcu::TestLog::EndMessage;
2982 res = QP_TEST_RESULT_QUALITY_WARNING;
2983 }
2984
2985 return tcu::TestStatus(res, qpGetTestResultName(res));
2986 }
2987
2988 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat cbFormat,VkFormat dsFormat,VkRenderingFlagsKHR renderingFlags) const2989 void FSRTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat cbFormat, VkFormat dsFormat,
2990 VkRenderingFlagsKHR renderingFlags) const
2991 {
2992 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
2993 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
2994 nullptr, // const void* pNext;
2995 renderingFlags, // VkRenderingFlagsKHR flags;
2996 m_data.multiView ? 0x3 : 0u, // uint32_t viewMask;
2997 1u, // uint32_t colorAttachmentCount;
2998 &cbFormat, // const VkFormat* pColorAttachmentFormats;
2999 dsFormat, // VkFormat depthAttachmentFormat;
3000 dsFormat, // VkFormat stencilAttachmentFormat;
3001 m_data.samples, // VkSampleCountFlagBits rasterizationSamples;
3002 };
3003 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
3004
3005 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
3006 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
3007 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
3008
3009 const VkCommandBufferBeginInfo commandBufBeginParams{
3010 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
3011 nullptr, // const void* pNext;
3012 usageFlags, // VkCommandBufferUsageFlags flags;
3013 &bufferInheritanceInfo};
3014
3015 const DeviceInterface &vk = m_context.getDeviceInterface();
3016 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
3017 }
3018
beginDynamicRender(VkCommandBuffer cmdBuffer,VkImageView srImageView,VkImageLayout srImageLayout,const VkExtent2D & srTexelSize,VkImageView cbImageView,VkImageView dsImageView,const VkClearValue & clearColor,const VkClearValue & clearDepthStencil,VkRenderingFlagsKHR renderingFlags) const3019 void FSRTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkImageView srImageView,
3020 VkImageLayout srImageLayout, const VkExtent2D &srTexelSize,
3021 VkImageView cbImageView, VkImageView dsImageView,
3022 const VkClearValue &clearColor, const VkClearValue &clearDepthStencil,
3023 VkRenderingFlagsKHR renderingFlags) const
3024 {
3025 const DeviceInterface &vk = m_context.getDeviceInterface();
3026 VkRect2D renderArea = makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
3027
3028 VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo{
3029 VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, // VkStructureType sType;
3030 nullptr, // const void* pNext;
3031 m_data.useAttachment() ? srImageView : VK_NULL_HANDLE, // VkImageView imageView;
3032 srImageLayout, // VkImageLayout imageLayout;
3033 srTexelSize // VkExtent2D shadingRateAttachmentTexelSize;
3034 };
3035
3036 VkRenderingAttachmentInfoKHR colorAttachment{
3037 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
3038 nullptr, // const void* pNext;
3039 cbImageView, // VkImageView imageView;
3040 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
3041 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
3042 VK_NULL_HANDLE, // VkImageView resolveImageView;
3043 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
3044 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
3045 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
3046 clearColor // VkClearValue clearValue;
3047 };
3048
3049 std::vector<VkRenderingAttachmentInfoKHR> depthStencilAttachments(
3050 2,
3051 {
3052 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
3053 nullptr, // const void* pNext;
3054 dsImageView, // VkImageView imageView;
3055 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
3056 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
3057 VK_NULL_HANDLE, // VkImageView resolveImageView;
3058 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
3059 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
3060 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
3061 clearDepthStencil // VkClearValue clearValue;
3062 });
3063
3064 vk::VkRenderingInfoKHR renderingInfo{
3065 vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
3066 m_data.useAttachment() || m_data.useAttachmentWithoutImageView() ? &shadingRateAttachmentInfo : nullptr,
3067 renderingFlags, // VkRenderingFlagsKHR flags;
3068 renderArea, // VkRect2D renderArea;
3069 m_data.multiView ? 1 : m_data.numColorLayers, // uint32_t layerCount;
3070 m_data.multiView ? 0x3 : 0u, // uint32_t viewMask;
3071 1u, // uint32_t colorAttachmentCount;
3072 &colorAttachment, // const VkRenderingAttachmentInfoKHR* pColorAttachments;
3073 m_data.useDepthStencil ? &depthStencilAttachments[0] :
3074 nullptr, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
3075 m_data.useDepthStencil ? &depthStencilAttachments[1] :
3076 nullptr, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
3077 };
3078
3079 vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
3080 }
3081 #endif // CTS_USES_VULKANSC
3082
preRenderCommands(VkCommandBuffer cmdBuffer,ImageWithMemory * cbImage,ImageWithMemory * dsImage,ImageWithMemory * secCbImage,ImageWithMemory * derivImage,uint32_t derivNumLevels,ImageWithMemory * srImage,VkImageLayout srLayout,BufferWithMemory * srFillBuffer,uint32_t numSRLayers,uint32_t srWidth,uint32_t srHeight,uint32_t srFillBpp,const VkClearValue & clearColor,const VkClearValue & clearDepthStencil)3083 void FSRTestInstance::preRenderCommands(VkCommandBuffer cmdBuffer, ImageWithMemory *cbImage, ImageWithMemory *dsImage,
3084 ImageWithMemory *secCbImage, ImageWithMemory *derivImage,
3085 uint32_t derivNumLevels, ImageWithMemory *srImage, VkImageLayout srLayout,
3086 BufferWithMemory *srFillBuffer, uint32_t numSRLayers, uint32_t srWidth,
3087 uint32_t srHeight, uint32_t srFillBpp, const VkClearValue &clearColor,
3088 const VkClearValue &clearDepthStencil)
3089 {
3090 const DeviceInterface &vk = m_context.getDeviceInterface();
3091 const VkDevice device = m_context.getDevice();
3092
3093 VkFlags allPipelineStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
3094 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
3095 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
3096 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
3097 VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
3098
3099 if (m_data.geometryShader)
3100 allPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
3101
3102 VkImageMemoryBarrier imageBarrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
3103 nullptr, // const void* pNext
3104 0u, // VkAccessFlags srcAccessMask
3105 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
3106 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
3107 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
3108 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
3109 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
3110 cbImage->get(), // VkImage image
3111 {
3112 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
3113 0u, // uint32_t baseMipLevel
3114 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
3115 0u, // uint32_t baseArray
3116 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
3117 }};
3118
3119 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3120 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
3121
3122 imageBarrier.image = derivImage->get();
3123 imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3124
3125 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3126 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
3127
3128 // Clear level to 1<<level
3129 for (uint32_t i = 0; i < derivNumLevels; ++i)
3130 {
3131 VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, i, 1u, 0u, 1u);
3132 VkClearValue clearLevelColor = makeClearValueColorU32(1 << i, 0, 0, 0);
3133 vk.cmdClearColorImage(cmdBuffer, derivImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearLevelColor.color, 1, &range);
3134 }
3135
3136 // Clear color buffer to transparent black
3137 {
3138 VkImageSubresourceRange range =
3139 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
3140 vk.cmdClearColorImage(cmdBuffer, cbImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
3141 }
3142
3143 // Clear the second color buffer to transparent black
3144 if (m_data.multiSubpasses)
3145 {
3146 VkImageSubresourceRange range = makeImageSubresourceRange(
3147 VK_IMAGE_ASPECT_COLOR_BIT, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
3148
3149 imageBarrier.image = secCbImage->get();
3150 imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3151 imageBarrier.subresourceRange = range;
3152
3153 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3154 0u, // dependencyFlags
3155 0u, nullptr, 0u, nullptr, 1u, &imageBarrier);
3156
3157 vk.cmdClearColorImage(cmdBuffer, secCbImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
3158 }
3159
3160 // Clear depth and stencil
3161 if (m_data.useDepthStencil)
3162 {
3163 VkImageSubresourceRange range =
3164 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, m_data.dsBaseMipLevel,
3165 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
3166 VkImageMemoryBarrier dsBarrier = imageBarrier;
3167 dsBarrier.image = dsImage->get();
3168 dsBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3169 dsBarrier.subresourceRange = range;
3170 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3171 0u, // dependencyFlags
3172 0u, nullptr, 0u, nullptr, 1u, &dsBarrier);
3173 if (!m_data.dsClearOp)
3174 vk.cmdClearDepthStencilImage(cmdBuffer, dsImage->get(), VK_IMAGE_LAYOUT_GENERAL,
3175 &clearDepthStencil.depthStencil, 1, &range);
3176 }
3177
3178 // Initialize shading rate image with varying values
3179 if (m_data.useAttachment())
3180 {
3181 imageBarrier.image = srImage->get();
3182 imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3183
3184 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3185 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
3186
3187 uint8_t *fillPtr = (uint8_t *)srFillBuffer->getAllocation().getHostPtr();
3188 for (uint32_t layer = 0; layer < numSRLayers; ++layer)
3189 {
3190 for (uint32_t x = 0; x < srWidth; ++x)
3191 {
3192 for (uint32_t y = 0; y < srHeight; ++y)
3193 {
3194 uint32_t idx = (layer * srHeight + y) * srWidth + x;
3195 uint8_t val = (uint8_t)SanitizeRate(idx & 0xF);
3196 // actual shading rate is always in the LSBs of the first byte of a texel
3197 fillPtr[srFillBpp * idx] = val;
3198 }
3199 }
3200 }
3201 flushAlloc(vk, device, srFillBuffer->getAllocation());
3202
3203 const VkBufferImageCopy copyRegion{
3204 0u, // VkDeviceSize bufferOffset;
3205 0u, // uint32_t bufferRowLength;
3206 0u, // uint32_t bufferImageHeight;
3207 {
3208 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
3209 0u, // uint32_t mipLevel;
3210 0u, // uint32_t baseArrayLayer;
3211 numSRLayers, // uint32_t layerCount;
3212 }, // VkImageSubresourceLayers imageSubresource;
3213 {0, 0, 0}, // VkOffset3D imageOffset;
3214 {srWidth, srHeight, 1}, // VkExtent3D imageExtent;
3215 };
3216
3217 vk.cmdCopyBufferToImage(cmdBuffer, srFillBuffer->get(), srImage->get(), VK_IMAGE_LAYOUT_GENERAL, 1,
3218 ©Region);
3219
3220 auto preShadingRateBarrier = imageBarrier;
3221 preShadingRateBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
3222 preShadingRateBarrier.newLayout = srLayout;
3223 preShadingRateBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
3224 preShadingRateBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
3225
3226 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
3227 VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, (VkDependencyFlags)0, 0,
3228 nullptr, 0, nullptr, 1, &preShadingRateBarrier);
3229 }
3230
3231 VkMemoryBarrier memBarrier{
3232 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
3233 nullptr, // pNext
3234 0u, // srcAccessMask
3235 0u, // dstAccessMask
3236 };
3237
3238 memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
3239 memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
3240 VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR |
3241 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
3242 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
3243 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, allPipelineStages, 0, 1, &memBarrier, 0, nullptr,
3244 0, nullptr);
3245 }
3246
beginLegacyRender(VkCommandBuffer cmdBuffer,RenderPassWrapper & renderPass,VkImageView srImageView,VkImageView cbImageView,VkImageView dsImageView,VkImageView secCbImageView,bool imagelessFB) const3247 void FSRTestInstance::beginLegacyRender(VkCommandBuffer cmdBuffer, RenderPassWrapper &renderPass,
3248 VkImageView srImageView, VkImageView cbImageView, VkImageView dsImageView,
3249 VkImageView secCbImageView, bool imagelessFB) const
3250 {
3251 const DeviceInterface &vk = m_context.getDeviceInterface();
3252 VkRect2D renderArea = makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
3253
3254 std::vector<VkImageView> attachments = {cbImageView};
3255 if (m_data.useAttachment())
3256 attachments.push_back(srImageView);
3257 if (m_data.useDepthStencil)
3258 attachments.push_back(dsImageView);
3259 if (m_data.multiSubpasses)
3260 attachments.push_back(secCbImageView);
3261
3262 const VkRenderPassAttachmentBeginInfo renderPassAttachmentBeginInfo{
3263 VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, // VkStructureType sType;
3264 nullptr, // const void* pNext;
3265 (uint32_t)attachments.size(), // uint32_t attachmentCount;
3266 &attachments[0] // const VkImageView* pAttachments;
3267 };
3268
3269 std::vector<VkClearValue> clearVals;
3270
3271 if (m_data.dsClearOp)
3272 {
3273 clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3274 if (m_data.useAttachment())
3275 clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3276 if (m_data.useDepthStencil)
3277 clearVals.push_back(makeClearValueDepthStencil(0.0f, 0));
3278 if (m_data.multiSubpasses)
3279 clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3280 }
3281
3282 renderPass.begin(vk, cmdBuffer, renderArea, m_data.dsClearOp ? static_cast<uint32_t>(clearVals.size()) : 0,
3283 m_data.dsClearOp ? clearVals.data() : nullptr, VK_SUBPASS_CONTENTS_INLINE,
3284 imagelessFB ? &renderPassAttachmentBeginInfo : nullptr);
3285 }
3286
drawCommandsOnNormalSubpass(VkCommandBuffer cmdBuffer,std::vector<GraphicsPipelineWrapper> & pipelines,const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & pipelineLayout,const RenderPassWrapper & renderPass,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const ShaderWrapper & vertShader,const ShaderWrapper & fragShader,const uint32_t subpass,VkBuffer vertexBuffer)3287 void FSRTestInstance::drawCommandsOnNormalSubpass(
3288 VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
3289 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
3290 const PipelineLayoutWrapper &pipelineLayout, const RenderPassWrapper &renderPass,
3291 const VkPipelineRasterizationStateCreateInfo *rasterizationState,
3292 const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
3293 const VkPipelineMultisampleStateCreateInfo *multisampleState, const ShaderWrapper &vertShader,
3294 const ShaderWrapper &fragShader, const uint32_t subpass, VkBuffer vertexBuffer)
3295 {
3296 const InstanceInterface &vki = m_context.getInstanceInterface();
3297 const DeviceInterface &vk = m_context.getDeviceInterface();
3298 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3299 const VkDevice device = m_context.getDevice();
3300 const auto &deviceExtensions = m_context.getDeviceExtensions();
3301
3302 pipelines.emplace_back(vki, vk, physicalDevice, device, deviceExtensions,
3303 m_data.groupParams->pipelineConstructionType);
3304 auto &pipeline = pipelines.back();
3305
3306 pipeline.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP).setDefaultColorBlendState();
3307
3308 pipeline.setupVertexInputState()
3309 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, subpass, vertShader,
3310 rasterizationState)
3311 .setupFragmentShaderState(pipelineLayout, *renderPass, subpass, fragShader, depthStencilState, multisampleState)
3312 .setupFragmentOutputState(*renderPass, subpass, nullptr, multisampleState)
3313 .setMonolithicPipelineLayout(pipelineLayout)
3314 .buildPipeline();
3315
3316 const VkDeviceSize vertexBufferOffset = 0;
3317
3318 vk.cmdNextSubpass(cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
3319 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3320 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
3321 vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
3322 }
3323
copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer,const ImageWithMemory * image,const BufferWithMemory * outputBuffer,const VkDeviceSize bufferSize)3324 void FSRTestInstance::copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer, const ImageWithMemory *image,
3325 const BufferWithMemory *outputBuffer,
3326 const VkDeviceSize bufferSize)
3327 {
3328 const DeviceInterface &vk = m_context.getDeviceInterface();
3329
3330 // Copy the image to output buffer.
3331 const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3332 const auto postImageBarrier = makeImageMemoryBarrier(
3333 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
3334 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image->get(), subresourceRange);
3335 const auto bufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
3336 outputBuffer->get(), 0ull, bufferSize);
3337
3338 const auto imageExtent = makeExtent3D(m_data.framebufferDim.width, m_data.framebufferDim.height, 1u);
3339 const auto copyRegion =
3340 makeBufferImageCopy(imageExtent, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
3341
3342 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
3343 0u, nullptr, 0u, nullptr, 1u, &postImageBarrier);
3344 vk.cmdCopyImageToBuffer(cmdBuffer, image->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outputBuffer->get(), 1u,
3345 ©Region);
3346 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u,
3347 &bufferBarrier, 0u, nullptr);
3348 }
3349
drawCommands(VkCommandBuffer cmdBuffer,std::vector<GraphicsPipelineWrapper> & pipelines,const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const VkPipelineVertexInputStateCreateInfo * vertexInputState,const VkPipelineDynamicStateCreateInfo * dynamicState,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,VkPipelineFragmentShadingRateStateCreateInfoKHR * shadingRateState,PipelineRenderingCreateInfoWrapper dynamicRenderingState,const ShaderWrapper vertShader,const ShaderWrapper geomShader,const ShaderWrapper meshShader,const ShaderWrapper fragShader,const std::vector<VkDescriptorSet> & descriptorSets,VkBuffer vertexBuffer,const uint32_t pushConstantSize)3350 void FSRTestInstance::drawCommands(VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
3351 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
3352 const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass,
3353 const VkPipelineVertexInputStateCreateInfo *vertexInputState,
3354 const VkPipelineDynamicStateCreateInfo *dynamicState,
3355 const VkPipelineRasterizationStateCreateInfo *rasterizationState,
3356 const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
3357 const VkPipelineMultisampleStateCreateInfo *multisampleState,
3358 VkPipelineFragmentShadingRateStateCreateInfoKHR *shadingRateState,
3359 PipelineRenderingCreateInfoWrapper dynamicRenderingState,
3360 const ShaderWrapper vertShader, const ShaderWrapper geomShader,
3361 const ShaderWrapper meshShader, const ShaderWrapper fragShader,
3362 const std::vector<VkDescriptorSet> &descriptorSets, VkBuffer vertexBuffer,
3363 const uint32_t pushConstantSize)
3364 {
3365 const InstanceInterface &vki = m_context.getInstanceInterface();
3366 const DeviceInterface &vk = m_context.getDeviceInterface();
3367 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3368 const VkDevice device = m_context.getDevice();
3369 const bool useMesh = (meshShader.isSet());
3370
3371 #ifdef CTS_USES_VULKANSC
3372 if (useMesh)
3373 DE_ASSERT(false);
3374 #endif // CTS_USES_VULKANSC
3375
3376 VkFlags allShaderStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
3377
3378 if (useMesh)
3379 {
3380 #ifndef CTS_USES_VULKANSC
3381 allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
3382 #endif // CTS_USES_VULKANSC
3383 }
3384 else
3385 {
3386 allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
3387 if (m_data.geometryShader)
3388 allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
3389 }
3390
3391 VkPipelineCreateFlags pipelineCreateFlags = (VkPipelineCreateFlags)0;
3392
3393 #ifndef CTS_USES_VULKANSC
3394 if (m_data.groupParams->useDynamicRendering)
3395 pipelineCreateFlags |= VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
3396 #endif // CTS_USES_VULKANSC
3397
3398 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0,
3399 static_cast<uint32_t>(descriptorSets.size()), de::dataOrNull(descriptorSets), 0, nullptr);
3400
3401 PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo = dynamicRenderingState;
3402 #ifndef CTS_USES_VULKANSC
3403 vk::VkPipelineRenderingCreateInfo pipelineRenderingCreateInfoWithGarbage;
3404 std::vector<VkFormat> garbageFormats;
3405
3406 if (m_data.garbageAttachment)
3407 {
3408 for (int i = 0; i < 10; i++)
3409 garbageFormats.push_back(VK_FORMAT_UNDEFINED);
3410
3411 pipelineRenderingCreateInfoWithGarbage = *dynamicRenderingState.ptr;
3412 // Just set a bunch of VK_FORMAT_UNDEFINED for garbage_color_attachment tests to make the validation happy.
3413 pipelineRenderingCreateInfoWithGarbage.colorAttachmentCount = static_cast<uint32_t>(garbageFormats.size());
3414 pipelineRenderingCreateInfoWithGarbage.pColorAttachmentFormats = garbageFormats.data();
3415 pipelineRenderingCreateInfo = &pipelineRenderingCreateInfoWithGarbage;
3416 }
3417 #endif
3418
3419 // If using dynamic state, create a single graphics pipeline and bind it
3420 if (m_data.useDynamicState)
3421 {
3422 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
3423 m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
3424 auto &pipeline = pipelines.back();
3425
3426 pipeline.setDefaultColorBlendState().setDynamicState(dynamicState);
3427
3428 if (useMesh)
3429 {
3430 #ifndef CTS_USES_VULKANSC
3431 pipeline.setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3432 ShaderWrapper(), meshShader, rasterizationState, nullptr,
3433 nullptr, shadingRateState, pipelineRenderingCreateInfo);
3434 #endif // CTS_USES_VULKANSC
3435 }
3436 else
3437 {
3438 pipeline.setupVertexInputState(vertexInputState)
3439 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3440 //1u,
3441 vertShader, rasterizationState, ShaderWrapper(), ShaderWrapper(),
3442 geomShader, nullptr, shadingRateState, pipelineRenderingCreateInfo);
3443 }
3444
3445 pipeline
3446 .setupFragmentShaderState(pipelineLayout, renderPass, 0u,
3447 //1u,
3448 fragShader, depthStencilState, multisampleState)
3449 .setupFragmentOutputState(renderPass, 0u, nullptr, multisampleState)
3450 //.setupFragmentOutputState(renderPass, 1u, nullptr, multisampleState)
3451 .setMonolithicPipelineLayout(pipelineLayout)
3452 .buildPipeline();
3453
3454 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3455 }
3456
3457 // Push constant block (must match shaders).
3458 struct
3459 {
3460 int32_t shadingRate;
3461 uint32_t instanceIndex;
3462 } pushConstantBlock;
3463
3464 for (int32_t i = 0; i < NUM_TRIANGLES; ++i)
3465 {
3466 if (!useMesh)
3467 {
3468 // Bind vertex attributes pointing to the next triangle
3469 VkDeviceSize vertexBufferOffset = i * 3 * 2 * sizeof(float);
3470 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
3471 }
3472
3473 // Put primitive shading rate and instance index (used in mesh shading cases) in push constants.
3474 pushConstantBlock.shadingRate = PrimIDToPrimitiveShadingRate(i);
3475 pushConstantBlock.instanceIndex = static_cast<uint32_t>(i);
3476 vk.cmdPushConstants(cmdBuffer, *pipelineLayout, allShaderStages, 0, pushConstantSize, &pushConstantBlock);
3477
3478 if (m_data.useDynamicState)
3479 {
3480 VkExtent2D fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
3481 vk.cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, m_data.combinerOp);
3482 }
3483 else
3484 {
3485 // Create a new pipeline with the desired pipeline shading rate
3486 shadingRateState->fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
3487
3488 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
3489 m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
3490 auto &pipeline = pipelines.back();
3491
3492 pipeline.setDefaultColorBlendState().setDynamicState(dynamicState);
3493
3494 if (useMesh)
3495 {
3496 #ifndef CTS_USES_VULKANSC
3497 pipeline.setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3498 ShaderWrapper(), meshShader, rasterizationState, nullptr,
3499 nullptr, shadingRateState, dynamicRenderingState);
3500 #endif // CTS_USES_VULKANSC
3501 }
3502 else
3503 {
3504 pipeline.setupVertexInputState(vertexInputState)
3505 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vertShader,
3506 rasterizationState, ShaderWrapper(), ShaderWrapper(), geomShader,
3507 nullptr, shadingRateState, dynamicRenderingState);
3508 }
3509
3510 pipeline
3511 .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShader, depthStencilState,
3512 multisampleState)
3513 #ifndef CTS_USES_VULKANSC
3514 .setRenderingColorAttachmentsInfo(dynamicRenderingState)
3515 #endif
3516 .setupFragmentOutputState(renderPass, 0u, nullptr, multisampleState)
3517 .setMonolithicPipelineLayout(pipelineLayout)
3518 .buildPipeline();
3519
3520 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3521 }
3522
3523 if (useMesh)
3524 {
3525 #ifndef CTS_USES_VULKANSC
3526 // Create a single workgroup to draw one triangle. The "primitive id" will be in the push constants.
3527 vk.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
3528 #endif // CTS_USES_VULKANSC
3529 }
3530 else
3531 {
3532 // Draw one triangle, with "primitive ID" in gl_InstanceIndex
3533 vk.cmdDraw(cmdBuffer, 3u, 1, 0u, i);
3534 }
3535 }
3536 }
3537
3538 } // namespace
3539
createBasicTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup,SharedGroupParams groupParams)3540 void createBasicTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *parentGroup, SharedGroupParams groupParams)
3541 {
3542 typedef struct
3543 {
3544 uint32_t count;
3545 const char *name;
3546 } TestGroupCase;
3547
3548 typedef struct
3549 {
3550 VkExtent2D count;
3551 const char *name;
3552 } TestGroupCase2D;
3553
3554 typedef struct
3555 {
3556 AttachmentUsage usage;
3557 const char *name;
3558 } TestGroupUsageCase;
3559
3560 TestGroupCase groupCases[] = {
3561 // basic tests
3562 {0, "basic"},
3563 // use pSampleMask
3564 {1, "apisamplemask"},
3565 // use gl_SampleMaskIn
3566 {2, "samplemaskin"},
3567 // conservative underestimation
3568 {3, "conservativeunder"},
3569 // conservative overestimation
3570 {4, "conservativeover"},
3571 // depth shader output
3572 {5, "fragdepth"},
3573 // stencil shader output
3574 {6, "fragstencil"},
3575 // multiple viewports and gl_ViewportIndex
3576 {7, "multiviewport"},
3577 // multiple layer color, single layer shading rate
3578 {8, "colorlayered"},
3579 // multiple layer color, multiple layers shading rate
3580 {9, "srlayered"},
3581 // multiview
3582 {10, "multiview"},
3583 // multiview and multilayer shading rate
3584 {11, "multiviewsrlayered"},
3585 // multiview with correlation mask
3586 {12, "multiviewcorrelation"},
3587 // fragment shader interlock
3588 {13, "interlock"},
3589 // custom sample locations
3590 {14, "samplelocations"},
3591 // enable sample shading in createinfo
3592 {15, "sampleshadingenable"},
3593 // enable sample shading by using gl_SampleID
3594 {16, "sampleshadinginput"},
3595 #ifndef CTS_USES_VULKANSC
3596 // depth shader output
3597 {17, "fragdepth_early_late"},
3598 // stencil shader output
3599 {18, "fragstencil_early_late"},
3600 #endif
3601 {19, "fragdepth_clear"},
3602 {20, "fragstencil_clear"},
3603 {21, "fragdepth_baselevel"},
3604 {22, "fragstencil_baselevel"},
3605 {23, "multipass"},
3606 {24, "multipass_fragdepth"},
3607 {25, "multipass_fragstencil"},
3608 #ifndef CTS_USES_VULKANSC
3609 {26, "maintenance6"},
3610 #endif
3611 };
3612
3613 TestGroupCase dynCases[] = {
3614 // uses dynamic shading rate state
3615 {1, "dynamic"},
3616 // uses static shading rate state
3617 {0, "static"},
3618 };
3619
3620 TestGroupUsageCase attCases[] = {
3621 // no shading rate attachment
3622 {AttachmentUsage::NO_ATTACHMENT, "noattachment"},
3623 // has shading rate attachment
3624 {AttachmentUsage::WITH_ATTACHMENT, "attachment"},
3625 // no shading rate attachment pointer
3626 {AttachmentUsage::NO_ATTACHMENT_PTR, "noattachmentptr"},
3627 // has shading rate attachment without imageview
3628 {AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW, "attachment_noimageview"},
3629 };
3630
3631 TestGroupCase shdCases[] = {
3632 // shader doesn't write rate
3633 {0, "noshaderrate"},
3634 // shader writes rate
3635 {1, "shaderrate"},
3636 };
3637
3638 TestGroupCase combCases[] = {
3639 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, "keep"},
3640 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR, "replace"},
3641 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR, "min"},
3642 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR, "max"},
3643 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR, "mul"},
3644 };
3645
3646 TestGroupCase2D extentCases[] = {
3647 {{1, 1}, "1x1"}, {{4, 4}, "4x4"}, {{33, 35}, "33x35"}, {{151, 431}, "151x431"}, {{256, 256}, "256x256"},
3648 };
3649
3650 TestGroupCase sampCases[] = {
3651 {VK_SAMPLE_COUNT_1_BIT, "samples1"}, {VK_SAMPLE_COUNT_2_BIT, "samples2"}, {VK_SAMPLE_COUNT_4_BIT, "samples4"},
3652 {VK_SAMPLE_COUNT_8_BIT, "samples8"}, {VK_SAMPLE_COUNT_16_BIT, "samples16"},
3653 };
3654
3655 TestGroupCase shaderCases[] = {
3656 // vertex shader only
3657 {0, "vs"},
3658 // vertex and geometry shader
3659 {1, "gs"},
3660 #ifndef CTS_USES_VULKANSC
3661 // mesh shader
3662 {2, "ms"},
3663 #endif // CTS_USES_VULKANSC
3664 };
3665
3666 int32_t seed = 0;
3667
3668 for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(groupCases); groupNdx++)
3669 {
3670 if (groupParams->useDynamicRendering && (groupNdx == 12 || groupNdx == 26))
3671 continue;
3672
3673 if (groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3674 {
3675 // for graphics pipeline library we need to repeat only selected groups
3676 if (std::set<int>{2, 3, 4, 10, 11, 12, 13, 14, 15}.count(groupNdx) == 0)
3677 continue;
3678 }
3679
3680 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, groupCases[groupNdx].name));
3681 for (int dynNdx = 0; dynNdx < DE_LENGTH_OF_ARRAY(dynCases); dynNdx++)
3682 {
3683 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3684 if (groupParams->useSecondaryCmdBuffer && (dynNdx != 0))
3685 continue;
3686
3687 de::MovePtr<tcu::TestCaseGroup> dynGroup(new tcu::TestCaseGroup(testCtx, dynCases[dynNdx].name));
3688 for (int attNdx = 0; attNdx < DE_LENGTH_OF_ARRAY(attCases); attNdx++)
3689 {
3690 if (groupParams->useDynamicRendering && attCases[attNdx].usage == AttachmentUsage::NO_ATTACHMENT_PTR)
3691 continue;
3692
3693 // WITH_ATTACHMENT_WITHOUT_IMAGEVIEW is only for VkRenderingFragmentShadingRateAttachmentInfoKHR.
3694 if (!groupParams->useDynamicRendering &&
3695 attCases[attNdx].usage == AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW)
3696 continue;
3697
3698 de::MovePtr<tcu::TestCaseGroup> attGroup(new tcu::TestCaseGroup(testCtx, attCases[attNdx].name));
3699 for (int shdNdx = 0; shdNdx < DE_LENGTH_OF_ARRAY(shdCases); shdNdx++)
3700 {
3701 de::MovePtr<tcu::TestCaseGroup> shdGroup(new tcu::TestCaseGroup(testCtx, shdCases[shdNdx].name));
3702 for (int cmb0Ndx = 0; cmb0Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb0Ndx++)
3703 {
3704 de::MovePtr<tcu::TestCaseGroup> cmb0Group(
3705 new tcu::TestCaseGroup(testCtx, combCases[cmb0Ndx].name));
3706 for (int cmb1Ndx = 0; cmb1Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb1Ndx++)
3707 {
3708 de::MovePtr<tcu::TestCaseGroup> cmb1Group(
3709 new tcu::TestCaseGroup(testCtx, combCases[cmb1Ndx].name));
3710 for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
3711 {
3712 // reduce number of cases repeat every other extent case for graphics pipeline library
3713 if ((groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) &&
3714 ((extNdx % 2) == 1))
3715 continue;
3716
3717 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3718 if (groupParams->useSecondaryCmdBuffer && (extNdx != 1))
3719 continue;
3720
3721 de::MovePtr<tcu::TestCaseGroup> extGroup(
3722 new tcu::TestCaseGroup(testCtx, extentCases[extNdx].name));
3723 for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
3724 {
3725 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3726 if (groupParams->useSecondaryCmdBuffer && (sampNdx != 1))
3727 continue;
3728
3729 de::MovePtr<tcu::TestCaseGroup> sampGroup(
3730 new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name));
3731 for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderCases); shaderNdx++)
3732 {
3733 de::MovePtr<tcu::TestCaseGroup> shaderGroup(
3734 new tcu::TestCaseGroup(testCtx, shaderCases[shaderNdx].name));
3735 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3736 if (groupParams->useSecondaryCmdBuffer && (shaderNdx != 0))
3737 continue;
3738
3739 bool useApiSampleMask = groupNdx == 1;
3740 bool useSampleMaskIn = groupNdx == 2;
3741 bool consRast = groupNdx == 3 || groupNdx == 4;
3742 bool fragDepth = groupNdx == 5 || groupNdx == 17 || groupNdx == 19 ||
3743 groupNdx == 21 || groupNdx == 24;
3744 bool fragStencil = groupNdx == 6 || groupNdx == 18 || groupNdx == 20 ||
3745 groupNdx == 22 || groupNdx == 25;
3746 bool multiViewport = groupNdx == 7;
3747 bool colorLayered = groupNdx == 8 || groupNdx == 9;
3748 bool srLayered = groupNdx == 9 || groupNdx == 11;
3749 bool multiView = groupNdx == 10 || groupNdx == 11 || groupNdx == 12;
3750 bool correlationMask = groupNdx == 12;
3751 bool interlock = groupNdx == 13;
3752 bool sampleLocations = groupNdx == 14;
3753 bool sampleShadingEnable = groupNdx == 15;
3754 bool sampleShadingInput = groupNdx == 16;
3755 bool useGeometryShader = (shaderCases[shaderNdx].count == 1u);
3756 bool useMeshShader = (shaderCases[shaderNdx].count == 2u);
3757 bool earlyAndLateTest = groupNdx == 17 || groupNdx == 18;
3758 bool opClear = groupNdx == 19 || groupNdx == 20;
3759 uint32_t baseMipLevel = (groupNdx == 21 || groupNdx == 22) ? 1 : 0;
3760 bool multiPass = (groupNdx == 23 || groupNdx == 24 || groupNdx == 25);
3761 bool maintenance6 = (groupNdx == 26);
3762
3763 VkConservativeRasterizationModeEXT conservativeMode =
3764 (groupNdx == 3) ? VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT :
3765 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3766 uint32_t numColorLayers = (colorLayered || multiView) ? 2u : 1u;
3767
3768 // Don't bother with geometry shader if we're not testing shader writes
3769 if (useGeometryShader && !shdCases[shdNdx].count)
3770 continue;
3771
3772 // reduce number of tests
3773 if ((groupNdx != 0) &&
3774 (!dynCases[dynNdx].count ||
3775 !(combCases[cmb0Ndx].count ==
3776 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR ||
3777 combCases[cmb0Ndx].count ==
3778 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
3779 !(combCases[cmb1Ndx].count ==
3780 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR ||
3781 combCases[cmb1Ndx].count ==
3782 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
3783 continue;
3784
3785 // Don't bother with geometry shader if we're testing conservative raster, sample mask, depth/stencil
3786 if (useGeometryShader && (useApiSampleMask || useSampleMaskIn || consRast ||
3787 fragDepth || fragStencil || maintenance6))
3788 continue;
3789
3790 // Don't bother with geometry shader if we're testing non-dynamic state
3791 if (useGeometryShader && !dynCases[dynNdx].count)
3792 continue;
3793
3794 // Only test multiViewport/layered with shaderWritesRate
3795 if ((multiViewport || colorLayered) && !shdCases[shdNdx].count)
3796 continue;
3797
3798 // Can't test layered shading rate attachment without an attachment
3799 if (srLayered && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
3800 continue;
3801
3802 // Test opClear for DS cases with only attachment and renderpass.
3803 if (opClear && (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3804 groupParams->useDynamicRendering))
3805 continue;
3806
3807 // Test baseLevel for DS cases with only attachment, single sample, and renderpass.
3808 if (baseMipLevel > 0 &&
3809 (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3810 groupParams->useDynamicRendering ||
3811 sampCases[sampNdx].count > VK_SAMPLE_COUNT_1_BIT))
3812 continue;
3813
3814 // Test multipass for DS cases with only attachment, single sample, and renderpass.
3815 if (multiPass && (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3816 groupParams->useDynamicRendering ||
3817 sampCases[sampNdx].count > VK_SAMPLE_COUNT_1_BIT))
3818 continue;
3819
3820 // Skip maintenance6 tests if there is no FSR attachment
3821 if (maintenance6 && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
3822 continue;
3823
3824 CaseDef c{
3825 groupParams, // SharedGroupParams groupParams;
3826 seed++, // int32_t seed;
3827 extentCases[extNdx].count, // VkExtent2D framebufferDim;
3828 (VkSampleCountFlagBits)sampCases[sampNdx]
3829 .count, // VkSampleCountFlagBits samples;
3830 {(VkFragmentShadingRateCombinerOpKHR)combCases[cmb0Ndx].count,
3831 (VkFragmentShadingRateCombinerOpKHR)combCases[cmb1Ndx]
3832 .count}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3833 attCases[attNdx].usage, // AttachmentUsage attachmentUsage;
3834 (bool)shdCases[shdNdx].count, // bool shaderWritesRate;
3835 useGeometryShader, // bool geometryShader;
3836 useMeshShader, // bool meshShader;
3837 (bool)dynCases[dynNdx].count, // bool useDynamicState;
3838 useApiSampleMask, // bool useApiSampleMask;
3839 useSampleMaskIn, // bool useSampleMaskIn;
3840 consRast, // bool conservativeEnable;
3841 conservativeMode, // VkConservativeRasterizationModeEXT conservativeMode;
3842 fragDepth || fragStencil, // bool useDepthStencil;
3843 fragDepth, // bool fragDepth;
3844 fragStencil, // bool fragStencil;
3845 multiViewport, // bool multiViewport;
3846 colorLayered, // bool colorLayered;
3847 srLayered, // bool srLayered;
3848 numColorLayers, // uint32_t numColorLayers;
3849 multiView, // bool multiView;
3850 correlationMask, // bool correlationMask;
3851 interlock, // bool interlock;
3852 sampleLocations, // bool sampleLocations;
3853 sampleShadingEnable, // bool sampleShadingEnable;
3854 sampleShadingInput, // bool sampleShadingInput;
3855 false, // bool sampleMaskTest;
3856 earlyAndLateTest, // bool earlyAndLateTest;
3857 false, // bool garbageAttachment;
3858 opClear, // bool dsClearOp;
3859 baseMipLevel, // uint32_t dsBaseMipLevel;
3860 multiPass, // bool multiSubpasses;
3861 maintenance6, // bool maintenance6;
3862 };
3863
3864 sampGroup->addChild(new FSRTestCase(testCtx, shaderCases[shaderNdx].name, c));
3865 }
3866 extGroup->addChild(sampGroup.release());
3867 }
3868 cmb1Group->addChild(extGroup.release());
3869 }
3870 cmb0Group->addChild(cmb1Group.release());
3871 }
3872 shdGroup->addChild(cmb0Group.release());
3873 }
3874 attGroup->addChild(shdGroup.release());
3875 }
3876 dynGroup->addChild(attGroup.release());
3877 }
3878 group->addChild(dynGroup.release());
3879 }
3880 parentGroup->addChild(group.release());
3881 }
3882
3883 {
3884 // Single tests that don't need to be part of above test matrix
3885 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "misc_tests"));
3886
3887 if (!groupParams->useSecondaryCmdBuffer)
3888 {
3889 group->addChild(new FSRTestCase(
3890 testCtx, "sample_mask_test",
3891 {
3892 groupParams, // SharedGroupParams groupParams;
3893 123, // int32_t seed;
3894 {32, 33}, // VkExtent2D framebufferDim;
3895 VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
3896 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3897 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3898 AttachmentUsage::NO_ATTACHMENT, // AttachmentUsage attachmentUsage;
3899 true, // bool shaderWritesRate;
3900 false, // bool geometryShader;
3901 false, // bool meshShader;
3902 false, // bool useDynamicState;
3903 true, // bool useApiSampleMask;
3904 false, // bool useSampleMaskIn;
3905 false, // bool conservativeEnable;
3906 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, // VkConservativeRasterizationModeEXT conservativeMode;
3907 false, // bool useDepthStencil;
3908 false, // bool fragDepth;
3909 false, // bool fragStencil;
3910 false, // bool multiViewport;
3911 false, // bool colorLayered;
3912 false, // bool srLayered;
3913 1u, // uint32_t numColorLayers;
3914 false, // bool multiView;
3915 false, // bool correlationMask;
3916 false, // bool interlock;
3917 false, // bool sampleLocations;
3918 false, // bool sampleShadingEnable;
3919 false, // bool sampleShadingInput;
3920 true, // bool sampleMaskTest;
3921 false, // bool earlyAndLateTest;
3922 false, // bool garbageAttachment;
3923 false, // bool dsClearOp;
3924 0, // uint32_t dsBaseMipLevel;
3925 false, // bool multiSubpasses;
3926 false, // bool maintenance6;
3927 }));
3928 }
3929
3930 #ifndef CTS_USES_VULKANSC
3931 if (groupParams->useDynamicRendering &&
3932 groupParams->pipelineConstructionType != vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3933 {
3934 group->addChild(new FSRTestCase(
3935 testCtx, "garbage_color_attachment",
3936 {
3937 groupParams, // SharedGroupParams groupParams;
3938 123, // int32_t seed;
3939 {32, 33}, // VkExtent2D framebufferDim;
3940 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
3941 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3942 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3943 AttachmentUsage::NO_ATTACHMENT, // AttachmentUsage attachmentUsage;
3944 false, // bool shaderWritesRate;
3945 false, // bool geometryShader;
3946 false, // bool meshShader;
3947 false, // bool useDynamicState;
3948 false, // bool useApiSampleMask;
3949 false, // bool useSampleMaskIn;
3950 false, // bool conservativeEnable;
3951 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, // VkConservativeRasterizationModeEXT conservativeMode;
3952 false, // bool useDepthStencil;
3953 false, // bool fragDepth;
3954 false, // bool fragStencil;
3955 false, // bool multiViewport;
3956 false, // bool colorLayered;
3957 false, // bool srLayered;
3958 1u, // uint32_t numColorLayers;
3959 false, // bool multiView;
3960 false, // bool correlationMask;
3961 false, // bool interlock;
3962 false, // bool sampleLocations;
3963 false, // bool sampleShadingEnable;
3964 false, // bool sampleShadingInput;
3965 false, // bool sampleMaskTest;
3966 false, // bool earlyAndLateTest;
3967 true, // bool garbageAttachment;
3968 false, // bool dsClearOp;
3969 0, // uint32_t dsBaseMipLevel;
3970 false, // bool multiSubpasses;
3971 false, // bool maintenance6;
3972 }));
3973 }
3974 #endif // CTS_USES_VULKANSC
3975
3976 parentGroup->addChild(group.release());
3977 }
3978 }
3979
3980 } // namespace FragmentShadingRate
3981 } // namespace vkt
3982