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::__anonc5b06d950111::CaseDef126 bool useAttachment() const
127 {
128 return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT);
129 }
130
useAttachmentWithoutImageViewvkt::FragmentShadingRate::__anonc5b06d950111::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, DE_NULL);
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 = DE_NULL;
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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // pImmutableSamplers
1499 },
1500 {
1501 1u, // binding
1502 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1503 1u, // descriptorCount
1504 allShaderStages, // stageFlags
1505 DE_NULL, // pImmutableSamplers
1506 },
1507 {
1508 2u, // binding
1509 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1510 1u, // descriptorCount
1511 allShaderStages, // stageFlags
1512 DE_NULL, // pImmutableSamplers
1513 },
1514 {
1515 3u, // binding
1516 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // descriptorType
1517 1u, // descriptorCount
1518 allShaderStages, // stageFlags
1519 DE_NULL, // pImmutableSamplers
1520 },
1521 {
1522 4u, // binding
1523 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1524 1u, // descriptorCount
1525 allShaderStages, // stageFlags
1526 DE_NULL, // pImmutableSamplers
1527 },
1528 {
1529 5u, // binding
1530 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1531 1u, // descriptorCount
1532 allShaderStages, // stageFlags
1533 DE_NULL, // pImmutableSamplers
1534 },
1535 {
1536 6u, // binding
1537 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1538 1u, // descriptorCount
1539 allShaderStages, // stageFlags
1540 DE_NULL, // pImmutableSamplers
1541 },
1542 {
1543 7u, // binding
1544 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1545 1u, // descriptorCount
1546 allShaderStages, // stageFlags
1547 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // pImmutableSamplers
1572 };
1573
1574 const VkDescriptorSetLayoutCreateInfo extraSetLayoutCreateInfo = {
1575 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1576 DE_NULL, // 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 DE_NULL, // 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 DE_NULL,
1620 (VkPipelineShaderStageCreateFlags)0,
1621 VK_SHADER_STAGE_COMPUTE_BIT, // stage
1622 *cs, // shader
1623 "main",
1624 DE_NULL, // pSpecializationInfo
1625 };
1626
1627 const VkComputePipelineCreateInfo pipelineCreateInfo = {
1628 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1629 DE_NULL,
1630 0u, // flags
1631 csShaderCreateInfo, // cs
1632 *pipelineLayout, // layout
1633 (vk::VkPipeline)0, // basePipelineHandle
1634 0u, // basePipelineIndex
1635 };
1636 Move<VkPipeline> computePipeline = createComputePipeline(vk, device, DE_NULL, &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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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(DE_NULL, *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(DE_NULL, *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(DE_NULL, *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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // pInputAttachments
1944 1, // colorCount
1945 &colorAttachmentReference, // pColorAttachments
1946 DE_NULL, // pResolveAttachments
1947 m_data.useDepthStencil ? &depthAttachmentReference : DE_NULL, // depthStencilAttachment
1948 0u, // preserveCount
1949 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 : DE_NULL // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 : DE_NULL, // pNext
2154 (vk::VkFramebufferCreateFlags)(imagelessFB ? VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT : 0),
2155 *renderPass, // renderPass
2156 (uint32_t)attachments.size(), // attachmentCount
2157 imagelessFB ? DE_NULL : &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 DE_NULL, // 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 DE_NULL, // 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 : DE_NULL, // 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 : DE_NULL;
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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL,
2298 m_data.multiView ? 0x3 : 0u,
2299 1u,
2300 &cbFormat,
2301 dsFormat,
2302 dsFormat};
2303 renderingCreateInfoWrapper.ptr =
2304 m_data.groupParams->useDynamicRendering ? &renderingCreateInfo : DE_NULL;
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 DE_NULL, // 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 DE_NULL, // 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, DE_NULL,
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 DE_NULL, 0, DE_NULL);
2505
2506 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1,
2507 &mainDescriptorSet, 0u, DE_NULL);
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, DE_NULL, 0, DE_NULL);
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 = DE_NULL;
2529 uint32_t *stencilptr = DE_NULL;
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 DE_NULL, // 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 DE_NULL, // 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 DE_NULL, // const void* pNext;
3031 m_data.useAttachment() ? srImageView : DE_NULL, // 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 DE_NULL, // const void* pNext;
3039 cbImageView, // VkImageView imageView;
3040 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
3041 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
3042 DE_NULL, // 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 DE_NULL, // const void* pNext;
3054 dsImageView, // VkImageView imageView;
3055 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
3056 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
3057 DE_NULL, // 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 : DE_NULL,
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 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
3075 m_data.useDepthStencil ? &depthStencilAttachments[1] :
3076 DE_NULL, // 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 DE_NULL, // 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, (const VkMemoryBarrier *)DE_NULL, 0,
3121 (const VkBufferMemoryBarrier *)DE_NULL, 1, &imageBarrier);
3122
3123 imageBarrier.image = derivImage->get();
3124 imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3125
3126 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3127 (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3128 (const VkBufferMemoryBarrier *)DE_NULL, 1, &imageBarrier);
3129
3130 // Clear level to 1<<level
3131 for (uint32_t i = 0; i < derivNumLevels; ++i)
3132 {
3133 VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, i, 1u, 0u, 1u);
3134 VkClearValue clearLevelColor = makeClearValueColorU32(1 << i, 0, 0, 0);
3135 vk.cmdClearColorImage(cmdBuffer, derivImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearLevelColor.color, 1, &range);
3136 }
3137
3138 // Clear color buffer to transparent black
3139 {
3140 VkImageSubresourceRange range =
3141 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
3142 vk.cmdClearColorImage(cmdBuffer, cbImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
3143 }
3144
3145 // Clear the second color buffer to transparent black
3146 if (m_data.multiSubpasses)
3147 {
3148 VkImageSubresourceRange range = makeImageSubresourceRange(
3149 VK_IMAGE_ASPECT_COLOR_BIT, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
3150
3151 imageBarrier.image = secCbImage->get();
3152 imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3153 imageBarrier.subresourceRange = range;
3154
3155 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3156 0u, // dependencyFlags
3157 0u, nullptr, 0u, nullptr, 1u, &imageBarrier);
3158
3159 vk.cmdClearColorImage(cmdBuffer, secCbImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
3160 }
3161
3162 // Clear depth and stencil
3163 if (m_data.useDepthStencil)
3164 {
3165 VkImageSubresourceRange range =
3166 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, m_data.dsBaseMipLevel,
3167 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
3168 VkImageMemoryBarrier dsBarrier = imageBarrier;
3169 dsBarrier.image = dsImage->get();
3170 dsBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3171 dsBarrier.subresourceRange = range;
3172 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3173 0u, // dependencyFlags
3174 0u, nullptr, 0u, nullptr, 1u, &dsBarrier);
3175 if (!m_data.dsClearOp)
3176 vk.cmdClearDepthStencilImage(cmdBuffer, dsImage->get(), VK_IMAGE_LAYOUT_GENERAL,
3177 &clearDepthStencil.depthStencil, 1, &range);
3178 }
3179
3180 // Initialize shading rate image with varying values
3181 if (m_data.useAttachment())
3182 {
3183 imageBarrier.image = srImage->get();
3184 imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
3185
3186 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3187 (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3188 (const VkBufferMemoryBarrier *)DE_NULL, 1, &imageBarrier);
3189
3190 uint8_t *fillPtr = (uint8_t *)srFillBuffer->getAllocation().getHostPtr();
3191 for (uint32_t layer = 0; layer < numSRLayers; ++layer)
3192 {
3193 for (uint32_t x = 0; x < srWidth; ++x)
3194 {
3195 for (uint32_t y = 0; y < srHeight; ++y)
3196 {
3197 uint32_t idx = (layer * srHeight + y) * srWidth + x;
3198 uint8_t val = (uint8_t)SanitizeRate(idx & 0xF);
3199 // actual shading rate is always in the LSBs of the first byte of a texel
3200 fillPtr[srFillBpp * idx] = val;
3201 }
3202 }
3203 }
3204 flushAlloc(vk, device, srFillBuffer->getAllocation());
3205
3206 const VkBufferImageCopy copyRegion{
3207 0u, // VkDeviceSize bufferOffset;
3208 0u, // uint32_t bufferRowLength;
3209 0u, // uint32_t bufferImageHeight;
3210 {
3211 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
3212 0u, // uint32_t mipLevel;
3213 0u, // uint32_t baseArrayLayer;
3214 numSRLayers, // uint32_t layerCount;
3215 }, // VkImageSubresourceLayers imageSubresource;
3216 {0, 0, 0}, // VkOffset3D imageOffset;
3217 {srWidth, srHeight, 1}, // VkExtent3D imageExtent;
3218 };
3219
3220 vk.cmdCopyBufferToImage(cmdBuffer, srFillBuffer->get(), srImage->get(), VK_IMAGE_LAYOUT_GENERAL, 1,
3221 ©Region);
3222
3223 auto preShadingRateBarrier = imageBarrier;
3224 preShadingRateBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
3225 preShadingRateBarrier.newLayout = srLayout;
3226 preShadingRateBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
3227 preShadingRateBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
3228
3229 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
3230 VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, (VkDependencyFlags)0, 0,
3231 (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL, 1,
3232 &preShadingRateBarrier);
3233 }
3234
3235 VkMemoryBarrier memBarrier{
3236 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
3237 DE_NULL, // pNext
3238 0u, // srcAccessMask
3239 0u, // dstAccessMask
3240 };
3241
3242 memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
3243 memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
3244 VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR |
3245 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
3246 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
3247 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, allPipelineStages, 0, 1, &memBarrier, 0, DE_NULL,
3248 0, DE_NULL);
3249 }
3250
beginLegacyRender(VkCommandBuffer cmdBuffer,RenderPassWrapper & renderPass,VkImageView srImageView,VkImageView cbImageView,VkImageView dsImageView,VkImageView secCbImageView,bool imagelessFB) const3251 void FSRTestInstance::beginLegacyRender(VkCommandBuffer cmdBuffer, RenderPassWrapper &renderPass,
3252 VkImageView srImageView, VkImageView cbImageView, VkImageView dsImageView,
3253 VkImageView secCbImageView, bool imagelessFB) const
3254 {
3255 const DeviceInterface &vk = m_context.getDeviceInterface();
3256 VkRect2D renderArea = makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
3257
3258 std::vector<VkImageView> attachments = {cbImageView};
3259 if (m_data.useAttachment())
3260 attachments.push_back(srImageView);
3261 if (m_data.useDepthStencil)
3262 attachments.push_back(dsImageView);
3263 if (m_data.multiSubpasses)
3264 attachments.push_back(secCbImageView);
3265
3266 const VkRenderPassAttachmentBeginInfo renderPassAttachmentBeginInfo{
3267 VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, // VkStructureType sType;
3268 DE_NULL, // const void* pNext;
3269 (uint32_t)attachments.size(), // uint32_t attachmentCount;
3270 &attachments[0] // const VkImageView* pAttachments;
3271 };
3272
3273 std::vector<VkClearValue> clearVals;
3274
3275 if (m_data.dsClearOp)
3276 {
3277 clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3278 if (m_data.useAttachment())
3279 clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3280 if (m_data.useDepthStencil)
3281 clearVals.push_back(makeClearValueDepthStencil(0.0f, 0));
3282 if (m_data.multiSubpasses)
3283 clearVals.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f));
3284 }
3285
3286 renderPass.begin(vk, cmdBuffer, renderArea, m_data.dsClearOp ? static_cast<uint32_t>(clearVals.size()) : 0,
3287 m_data.dsClearOp ? clearVals.data() : nullptr, VK_SUBPASS_CONTENTS_INLINE,
3288 imagelessFB ? &renderPassAttachmentBeginInfo : DE_NULL);
3289 }
3290
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)3291 void FSRTestInstance::drawCommandsOnNormalSubpass(
3292 VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
3293 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
3294 const PipelineLayoutWrapper &pipelineLayout, const RenderPassWrapper &renderPass,
3295 const VkPipelineRasterizationStateCreateInfo *rasterizationState,
3296 const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
3297 const VkPipelineMultisampleStateCreateInfo *multisampleState, const ShaderWrapper &vertShader,
3298 const ShaderWrapper &fragShader, const uint32_t subpass, VkBuffer vertexBuffer)
3299 {
3300 const InstanceInterface &vki = m_context.getInstanceInterface();
3301 const DeviceInterface &vk = m_context.getDeviceInterface();
3302 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3303 const VkDevice device = m_context.getDevice();
3304 const auto &deviceExtensions = m_context.getDeviceExtensions();
3305
3306 pipelines.emplace_back(vki, vk, physicalDevice, device, deviceExtensions,
3307 m_data.groupParams->pipelineConstructionType);
3308 auto &pipeline = pipelines.back();
3309
3310 pipeline.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP).setDefaultColorBlendState();
3311
3312 pipeline.setupVertexInputState()
3313 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, subpass, vertShader,
3314 rasterizationState)
3315 .setupFragmentShaderState(pipelineLayout, *renderPass, subpass, fragShader, depthStencilState, multisampleState)
3316 .setupFragmentOutputState(*renderPass, subpass, nullptr, multisampleState)
3317 .setMonolithicPipelineLayout(pipelineLayout)
3318 .buildPipeline();
3319
3320 const VkDeviceSize vertexBufferOffset = 0;
3321
3322 vk.cmdNextSubpass(cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
3323 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3324 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
3325 vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
3326 }
3327
copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer,const ImageWithMemory * image,const BufferWithMemory * outputBuffer,const VkDeviceSize bufferSize)3328 void FSRTestInstance::copyImageToBufferOnNormalSubpass(VkCommandBuffer cmdBuffer, const ImageWithMemory *image,
3329 const BufferWithMemory *outputBuffer,
3330 const VkDeviceSize bufferSize)
3331 {
3332 const DeviceInterface &vk = m_context.getDeviceInterface();
3333
3334 // Copy the image to output buffer.
3335 const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3336 const auto postImageBarrier = makeImageMemoryBarrier(
3337 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
3338 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image->get(), subresourceRange);
3339 const auto bufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
3340 outputBuffer->get(), 0ull, bufferSize);
3341
3342 const auto imageExtent = makeExtent3D(m_data.framebufferDim.width, m_data.framebufferDim.height, 1u);
3343 const auto copyRegion =
3344 makeBufferImageCopy(imageExtent, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
3345
3346 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
3347 0u, nullptr, 0u, nullptr, 1u, &postImageBarrier);
3348 vk.cmdCopyImageToBuffer(cmdBuffer, image->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outputBuffer->get(), 1u,
3349 ©Region);
3350 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u,
3351 &bufferBarrier, 0u, nullptr);
3352 }
3353
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)3354 void FSRTestInstance::drawCommands(VkCommandBuffer cmdBuffer, std::vector<GraphicsPipelineWrapper> &pipelines,
3355 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
3356 const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass,
3357 const VkPipelineVertexInputStateCreateInfo *vertexInputState,
3358 const VkPipelineDynamicStateCreateInfo *dynamicState,
3359 const VkPipelineRasterizationStateCreateInfo *rasterizationState,
3360 const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
3361 const VkPipelineMultisampleStateCreateInfo *multisampleState,
3362 VkPipelineFragmentShadingRateStateCreateInfoKHR *shadingRateState,
3363 PipelineRenderingCreateInfoWrapper dynamicRenderingState,
3364 const ShaderWrapper vertShader, const ShaderWrapper geomShader,
3365 const ShaderWrapper meshShader, const ShaderWrapper fragShader,
3366 const std::vector<VkDescriptorSet> &descriptorSets, VkBuffer vertexBuffer,
3367 const uint32_t pushConstantSize)
3368 {
3369 const InstanceInterface &vki = m_context.getInstanceInterface();
3370 const DeviceInterface &vk = m_context.getDeviceInterface();
3371 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3372 const VkDevice device = m_context.getDevice();
3373 const bool useMesh = (meshShader.isSet());
3374
3375 #ifdef CTS_USES_VULKANSC
3376 if (useMesh)
3377 DE_ASSERT(false);
3378 #endif // CTS_USES_VULKANSC
3379
3380 VkFlags allShaderStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
3381
3382 if (useMesh)
3383 {
3384 #ifndef CTS_USES_VULKANSC
3385 allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
3386 #endif // CTS_USES_VULKANSC
3387 }
3388 else
3389 {
3390 allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
3391 if (m_data.geometryShader)
3392 allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
3393 }
3394
3395 VkPipelineCreateFlags pipelineCreateFlags = (VkPipelineCreateFlags)0;
3396
3397 #ifndef CTS_USES_VULKANSC
3398 if (m_data.groupParams->useDynamicRendering)
3399 pipelineCreateFlags |= VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
3400 #endif // CTS_USES_VULKANSC
3401
3402 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0,
3403 static_cast<uint32_t>(descriptorSets.size()), de::dataOrNull(descriptorSets), 0, DE_NULL);
3404
3405 PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo = dynamicRenderingState;
3406 #ifndef CTS_USES_VULKANSC
3407 vk::VkPipelineRenderingCreateInfo pipelineRenderingCreateInfoWithGarbage;
3408 std::vector<VkFormat> garbageFormats;
3409
3410 if (m_data.garbageAttachment)
3411 {
3412 for (int i = 0; i < 10; i++)
3413 garbageFormats.push_back(VK_FORMAT_UNDEFINED);
3414
3415 pipelineRenderingCreateInfoWithGarbage = *dynamicRenderingState.ptr;
3416 // Just set a bunch of VK_FORMAT_UNDEFINED for garbage_color_attachment tests to make the validation happy.
3417 pipelineRenderingCreateInfoWithGarbage.colorAttachmentCount = static_cast<uint32_t>(garbageFormats.size());
3418 pipelineRenderingCreateInfoWithGarbage.pColorAttachmentFormats = garbageFormats.data();
3419 pipelineRenderingCreateInfo = &pipelineRenderingCreateInfoWithGarbage;
3420 }
3421 #endif
3422
3423 // If using dynamic state, create a single graphics pipeline and bind it
3424 if (m_data.useDynamicState)
3425 {
3426 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
3427 m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
3428 auto &pipeline = pipelines.back();
3429
3430 pipeline.setDefaultColorBlendState().setDynamicState(dynamicState);
3431
3432 if (useMesh)
3433 {
3434 #ifndef CTS_USES_VULKANSC
3435 pipeline.setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3436 ShaderWrapper(), meshShader, rasterizationState, nullptr,
3437 nullptr, shadingRateState, pipelineRenderingCreateInfo);
3438 #endif // CTS_USES_VULKANSC
3439 }
3440 else
3441 {
3442 pipeline.setupVertexInputState(vertexInputState)
3443 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3444 //1u,
3445 vertShader, rasterizationState, ShaderWrapper(), ShaderWrapper(),
3446 geomShader, DE_NULL, shadingRateState, pipelineRenderingCreateInfo);
3447 }
3448
3449 pipeline
3450 .setupFragmentShaderState(pipelineLayout, renderPass, 0u,
3451 //1u,
3452 fragShader, depthStencilState, multisampleState)
3453 .setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
3454 //.setupFragmentOutputState(renderPass, 1u, DE_NULL, multisampleState)
3455 .setMonolithicPipelineLayout(pipelineLayout)
3456 .buildPipeline();
3457
3458 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3459 }
3460
3461 // Push constant block (must match shaders).
3462 struct
3463 {
3464 int32_t shadingRate;
3465 uint32_t instanceIndex;
3466 } pushConstantBlock;
3467
3468 for (int32_t i = 0; i < NUM_TRIANGLES; ++i)
3469 {
3470 if (!useMesh)
3471 {
3472 // Bind vertex attributes pointing to the next triangle
3473 VkDeviceSize vertexBufferOffset = i * 3 * 2 * sizeof(float);
3474 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
3475 }
3476
3477 // Put primitive shading rate and instance index (used in mesh shading cases) in push constants.
3478 pushConstantBlock.shadingRate = PrimIDToPrimitiveShadingRate(i);
3479 pushConstantBlock.instanceIndex = static_cast<uint32_t>(i);
3480 vk.cmdPushConstants(cmdBuffer, *pipelineLayout, allShaderStages, 0, pushConstantSize, &pushConstantBlock);
3481
3482 if (m_data.useDynamicState)
3483 {
3484 VkExtent2D fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
3485 vk.cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, m_data.combinerOp);
3486 }
3487 else
3488 {
3489 // Create a new pipeline with the desired pipeline shading rate
3490 shadingRateState->fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
3491
3492 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
3493 m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
3494 auto &pipeline = pipelines.back();
3495
3496 pipeline.setDefaultColorBlendState().setDynamicState(dynamicState);
3497
3498 if (useMesh)
3499 {
3500 #ifndef CTS_USES_VULKANSC
3501 pipeline.setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u,
3502 ShaderWrapper(), meshShader, rasterizationState, nullptr,
3503 nullptr, shadingRateState, dynamicRenderingState);
3504 #endif // CTS_USES_VULKANSC
3505 }
3506 else
3507 {
3508 pipeline.setupVertexInputState(vertexInputState)
3509 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vertShader,
3510 rasterizationState, ShaderWrapper(), ShaderWrapper(), geomShader,
3511 DE_NULL, shadingRateState, dynamicRenderingState);
3512 }
3513
3514 pipeline
3515 .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShader, depthStencilState,
3516 multisampleState)
3517 #ifndef CTS_USES_VULKANSC
3518 .setRenderingColorAttachmentsInfo(dynamicRenderingState)
3519 #endif
3520 .setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
3521 .setMonolithicPipelineLayout(pipelineLayout)
3522 .buildPipeline();
3523
3524 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3525 }
3526
3527 if (useMesh)
3528 {
3529 #ifndef CTS_USES_VULKANSC
3530 // Create a single workgroup to draw one triangle. The "primitive id" will be in the push constants.
3531 vk.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
3532 #endif // CTS_USES_VULKANSC
3533 }
3534 else
3535 {
3536 // Draw one triangle, with "primitive ID" in gl_InstanceIndex
3537 vk.cmdDraw(cmdBuffer, 3u, 1, 0u, i);
3538 }
3539 }
3540 }
3541
3542 } // namespace
3543
createBasicTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup,SharedGroupParams groupParams)3544 void createBasicTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *parentGroup, SharedGroupParams groupParams)
3545 {
3546 typedef struct
3547 {
3548 uint32_t count;
3549 const char *name;
3550 } TestGroupCase;
3551
3552 typedef struct
3553 {
3554 VkExtent2D count;
3555 const char *name;
3556 } TestGroupCase2D;
3557
3558 typedef struct
3559 {
3560 AttachmentUsage usage;
3561 const char *name;
3562 } TestGroupUsageCase;
3563
3564 TestGroupCase groupCases[] = {
3565 // basic tests
3566 {0, "basic"},
3567 // use pSampleMask
3568 {1, "apisamplemask"},
3569 // use gl_SampleMaskIn
3570 {2, "samplemaskin"},
3571 // conservative underestimation
3572 {3, "conservativeunder"},
3573 // conservative overestimation
3574 {4, "conservativeover"},
3575 // depth shader output
3576 {5, "fragdepth"},
3577 // stencil shader output
3578 {6, "fragstencil"},
3579 // multiple viewports and gl_ViewportIndex
3580 {7, "multiviewport"},
3581 // multiple layer color, single layer shading rate
3582 {8, "colorlayered"},
3583 // multiple layer color, multiple layers shading rate
3584 {9, "srlayered"},
3585 // multiview
3586 {10, "multiview"},
3587 // multiview and multilayer shading rate
3588 {11, "multiviewsrlayered"},
3589 // multiview with correlation mask
3590 {12, "multiviewcorrelation"},
3591 // fragment shader interlock
3592 {13, "interlock"},
3593 // custom sample locations
3594 {14, "samplelocations"},
3595 // enable sample shading in createinfo
3596 {15, "sampleshadingenable"},
3597 // enable sample shading by using gl_SampleID
3598 {16, "sampleshadinginput"},
3599 #ifndef CTS_USES_VULKANSC
3600 // depth shader output
3601 {17, "fragdepth_early_late"},
3602 // stencil shader output
3603 {18, "fragstencil_early_late"},
3604 #endif
3605 {19, "fragdepth_clear"},
3606 {20, "fragstencil_clear"},
3607 {21, "fragdepth_baselevel"},
3608 {22, "fragstencil_baselevel"},
3609 {23, "multipass"},
3610 {24, "multipass_fragdepth"},
3611 {25, "multipass_fragstencil"},
3612 #ifndef CTS_USES_VULKANSC
3613 {26, "maintenance6"},
3614 #endif
3615 };
3616
3617 TestGroupCase dynCases[] = {
3618 // uses dynamic shading rate state
3619 {1, "dynamic"},
3620 // uses static shading rate state
3621 {0, "static"},
3622 };
3623
3624 TestGroupUsageCase attCases[] = {
3625 // no shading rate attachment
3626 {AttachmentUsage::NO_ATTACHMENT, "noattachment"},
3627 // has shading rate attachment
3628 {AttachmentUsage::WITH_ATTACHMENT, "attachment"},
3629 // no shading rate attachment pointer
3630 {AttachmentUsage::NO_ATTACHMENT_PTR, "noattachmentptr"},
3631 // has shading rate attachment without imageview
3632 {AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW, "attachment_noimageview"},
3633 };
3634
3635 TestGroupCase shdCases[] = {
3636 // shader doesn't write rate
3637 {0, "noshaderrate"},
3638 // shader writes rate
3639 {1, "shaderrate"},
3640 };
3641
3642 TestGroupCase combCases[] = {
3643 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, "keep"},
3644 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR, "replace"},
3645 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR, "min"},
3646 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR, "max"},
3647 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR, "mul"},
3648 };
3649
3650 TestGroupCase2D extentCases[] = {
3651 {{1, 1}, "1x1"}, {{4, 4}, "4x4"}, {{33, 35}, "33x35"}, {{151, 431}, "151x431"}, {{256, 256}, "256x256"},
3652 };
3653
3654 TestGroupCase sampCases[] = {
3655 {VK_SAMPLE_COUNT_1_BIT, "samples1"}, {VK_SAMPLE_COUNT_2_BIT, "samples2"}, {VK_SAMPLE_COUNT_4_BIT, "samples4"},
3656 {VK_SAMPLE_COUNT_8_BIT, "samples8"}, {VK_SAMPLE_COUNT_16_BIT, "samples16"},
3657 };
3658
3659 TestGroupCase shaderCases[] = {
3660 // vertex shader only
3661 {0, "vs"},
3662 // vertex and geometry shader
3663 {1, "gs"},
3664 #ifndef CTS_USES_VULKANSC
3665 // mesh shader
3666 {2, "ms"},
3667 #endif // CTS_USES_VULKANSC
3668 };
3669
3670 int32_t seed = 0;
3671
3672 for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(groupCases); groupNdx++)
3673 {
3674 if (groupParams->useDynamicRendering && (groupNdx == 12 || groupNdx == 26))
3675 continue;
3676
3677 if (groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3678 {
3679 // for graphics pipeline library we need to repeat only selected groups
3680 if (std::set<int>{2, 3, 4, 10, 11, 12, 13, 14, 15}.count(groupNdx) == 0)
3681 continue;
3682 }
3683
3684 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, groupCases[groupNdx].name));
3685 for (int dynNdx = 0; dynNdx < DE_LENGTH_OF_ARRAY(dynCases); dynNdx++)
3686 {
3687 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3688 if (groupParams->useSecondaryCmdBuffer && (dynNdx != 0))
3689 continue;
3690
3691 de::MovePtr<tcu::TestCaseGroup> dynGroup(new tcu::TestCaseGroup(testCtx, dynCases[dynNdx].name));
3692 for (int attNdx = 0; attNdx < DE_LENGTH_OF_ARRAY(attCases); attNdx++)
3693 {
3694 if (groupParams->useDynamicRendering && attCases[attNdx].usage == AttachmentUsage::NO_ATTACHMENT_PTR)
3695 continue;
3696
3697 // WITH_ATTACHMENT_WITHOUT_IMAGEVIEW is only for VkRenderingFragmentShadingRateAttachmentInfoKHR.
3698 if (!groupParams->useDynamicRendering &&
3699 attCases[attNdx].usage == AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW)
3700 continue;
3701
3702 de::MovePtr<tcu::TestCaseGroup> attGroup(new tcu::TestCaseGroup(testCtx, attCases[attNdx].name));
3703 for (int shdNdx = 0; shdNdx < DE_LENGTH_OF_ARRAY(shdCases); shdNdx++)
3704 {
3705 de::MovePtr<tcu::TestCaseGroup> shdGroup(new tcu::TestCaseGroup(testCtx, shdCases[shdNdx].name));
3706 for (int cmb0Ndx = 0; cmb0Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb0Ndx++)
3707 {
3708 de::MovePtr<tcu::TestCaseGroup> cmb0Group(
3709 new tcu::TestCaseGroup(testCtx, combCases[cmb0Ndx].name));
3710 for (int cmb1Ndx = 0; cmb1Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb1Ndx++)
3711 {
3712 de::MovePtr<tcu::TestCaseGroup> cmb1Group(
3713 new tcu::TestCaseGroup(testCtx, combCases[cmb1Ndx].name));
3714 for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
3715 {
3716 // reduce number of cases repeat every other extent case for graphics pipeline library
3717 if ((groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) &&
3718 ((extNdx % 2) == 1))
3719 continue;
3720
3721 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3722 if (groupParams->useSecondaryCmdBuffer && (extNdx != 1))
3723 continue;
3724
3725 de::MovePtr<tcu::TestCaseGroup> extGroup(
3726 new tcu::TestCaseGroup(testCtx, extentCases[extNdx].name));
3727 for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
3728 {
3729 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3730 if (groupParams->useSecondaryCmdBuffer && (sampNdx != 1))
3731 continue;
3732
3733 de::MovePtr<tcu::TestCaseGroup> sampGroup(
3734 new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name));
3735 for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderCases); shaderNdx++)
3736 {
3737 de::MovePtr<tcu::TestCaseGroup> shaderGroup(
3738 new tcu::TestCaseGroup(testCtx, shaderCases[shaderNdx].name));
3739 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
3740 if (groupParams->useSecondaryCmdBuffer && (shaderNdx != 0))
3741 continue;
3742
3743 bool useApiSampleMask = groupNdx == 1;
3744 bool useSampleMaskIn = groupNdx == 2;
3745 bool consRast = groupNdx == 3 || groupNdx == 4;
3746 bool fragDepth = groupNdx == 5 || groupNdx == 17 || groupNdx == 19 ||
3747 groupNdx == 21 || groupNdx == 24;
3748 bool fragStencil = groupNdx == 6 || groupNdx == 18 || groupNdx == 20 ||
3749 groupNdx == 22 || groupNdx == 25;
3750 bool multiViewport = groupNdx == 7;
3751 bool colorLayered = groupNdx == 8 || groupNdx == 9;
3752 bool srLayered = groupNdx == 9 || groupNdx == 11;
3753 bool multiView = groupNdx == 10 || groupNdx == 11 || groupNdx == 12;
3754 bool correlationMask = groupNdx == 12;
3755 bool interlock = groupNdx == 13;
3756 bool sampleLocations = groupNdx == 14;
3757 bool sampleShadingEnable = groupNdx == 15;
3758 bool sampleShadingInput = groupNdx == 16;
3759 bool useGeometryShader = (shaderCases[shaderNdx].count == 1u);
3760 bool useMeshShader = (shaderCases[shaderNdx].count == 2u);
3761 bool earlyAndLateTest = groupNdx == 17 || groupNdx == 18;
3762 bool opClear = groupNdx == 19 || groupNdx == 20;
3763 uint32_t baseMipLevel = (groupNdx == 21 || groupNdx == 22) ? 1 : 0;
3764 bool multiPass = (groupNdx == 23 || groupNdx == 24 || groupNdx == 25);
3765 bool maintenance6 = (groupNdx == 26);
3766
3767 VkConservativeRasterizationModeEXT conservativeMode =
3768 (groupNdx == 3) ? VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT :
3769 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3770 uint32_t numColorLayers = (colorLayered || multiView) ? 2u : 1u;
3771
3772 // Don't bother with geometry shader if we're not testing shader writes
3773 if (useGeometryShader && !shdCases[shdNdx].count)
3774 continue;
3775
3776 // reduce number of tests
3777 if ((groupNdx != 0) &&
3778 (!dynCases[dynNdx].count ||
3779 !(combCases[cmb0Ndx].count ==
3780 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR ||
3781 combCases[cmb0Ndx].count ==
3782 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
3783 !(combCases[cmb1Ndx].count ==
3784 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR ||
3785 combCases[cmb1Ndx].count ==
3786 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
3787 continue;
3788
3789 // Don't bother with geometry shader if we're testing conservative raster, sample mask, depth/stencil
3790 if (useGeometryShader && (useApiSampleMask || useSampleMaskIn || consRast ||
3791 fragDepth || fragStencil || maintenance6))
3792 continue;
3793
3794 // Don't bother with geometry shader if we're testing non-dynamic state
3795 if (useGeometryShader && !dynCases[dynNdx].count)
3796 continue;
3797
3798 // Only test multiViewport/layered with shaderWritesRate
3799 if ((multiViewport || colorLayered) && !shdCases[shdNdx].count)
3800 continue;
3801
3802 // Can't test layered shading rate attachment without an attachment
3803 if (srLayered && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
3804 continue;
3805
3806 // Test opClear for DS cases with only attachment and renderpass.
3807 if (opClear && (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3808 groupParams->useDynamicRendering))
3809 continue;
3810
3811 // Test baseLevel for DS cases with only attachment, single sample, and renderpass.
3812 if (baseMipLevel > 0 &&
3813 (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3814 groupParams->useDynamicRendering ||
3815 sampCases[sampNdx].count > VK_SAMPLE_COUNT_1_BIT))
3816 continue;
3817
3818 // Test multipass for DS cases with only attachment, single sample, and renderpass.
3819 if (multiPass && (attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT ||
3820 groupParams->useDynamicRendering ||
3821 sampCases[sampNdx].count > VK_SAMPLE_COUNT_1_BIT))
3822 continue;
3823
3824 // Skip maintenance6 tests if there is no FSR attachment
3825 if (maintenance6 && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
3826 continue;
3827
3828 CaseDef c{
3829 groupParams, // SharedGroupParams groupParams;
3830 seed++, // int32_t seed;
3831 extentCases[extNdx].count, // VkExtent2D framebufferDim;
3832 (VkSampleCountFlagBits)sampCases[sampNdx]
3833 .count, // VkSampleCountFlagBits samples;
3834 {(VkFragmentShadingRateCombinerOpKHR)combCases[cmb0Ndx].count,
3835 (VkFragmentShadingRateCombinerOpKHR)combCases[cmb1Ndx]
3836 .count}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3837 attCases[attNdx].usage, // AttachmentUsage attachmentUsage;
3838 (bool)shdCases[shdNdx].count, // bool shaderWritesRate;
3839 useGeometryShader, // bool geometryShader;
3840 useMeshShader, // bool meshShader;
3841 (bool)dynCases[dynNdx].count, // bool useDynamicState;
3842 useApiSampleMask, // bool useApiSampleMask;
3843 useSampleMaskIn, // bool useSampleMaskIn;
3844 consRast, // bool conservativeEnable;
3845 conservativeMode, // VkConservativeRasterizationModeEXT conservativeMode;
3846 fragDepth || fragStencil, // bool useDepthStencil;
3847 fragDepth, // bool fragDepth;
3848 fragStencil, // bool fragStencil;
3849 multiViewport, // bool multiViewport;
3850 colorLayered, // bool colorLayered;
3851 srLayered, // bool srLayered;
3852 numColorLayers, // uint32_t numColorLayers;
3853 multiView, // bool multiView;
3854 correlationMask, // bool correlationMask;
3855 interlock, // bool interlock;
3856 sampleLocations, // bool sampleLocations;
3857 sampleShadingEnable, // bool sampleShadingEnable;
3858 sampleShadingInput, // bool sampleShadingInput;
3859 false, // bool sampleMaskTest;
3860 earlyAndLateTest, // bool earlyAndLateTest;
3861 false, // bool garbageAttachment;
3862 opClear, // bool dsClearOp;
3863 baseMipLevel, // uint32_t dsBaseMipLevel;
3864 multiPass, // bool multiSubpasses;
3865 maintenance6, // bool maintenance6;
3866 };
3867
3868 sampGroup->addChild(new FSRTestCase(testCtx, shaderCases[shaderNdx].name, c));
3869 }
3870 extGroup->addChild(sampGroup.release());
3871 }
3872 cmb1Group->addChild(extGroup.release());
3873 }
3874 cmb0Group->addChild(cmb1Group.release());
3875 }
3876 shdGroup->addChild(cmb0Group.release());
3877 }
3878 attGroup->addChild(shdGroup.release());
3879 }
3880 dynGroup->addChild(attGroup.release());
3881 }
3882 group->addChild(dynGroup.release());
3883 }
3884 parentGroup->addChild(group.release());
3885 }
3886
3887 {
3888 // Single tests that don't need to be part of above test matrix
3889 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "misc_tests"));
3890
3891 if (!groupParams->useSecondaryCmdBuffer)
3892 {
3893 group->addChild(new FSRTestCase(
3894 testCtx, "sample_mask_test",
3895 {
3896 groupParams, // SharedGroupParams groupParams;
3897 123, // int32_t seed;
3898 {32, 33}, // VkExtent2D framebufferDim;
3899 VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
3900 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3901 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3902 AttachmentUsage::NO_ATTACHMENT, // AttachmentUsage attachmentUsage;
3903 true, // bool shaderWritesRate;
3904 false, // bool geometryShader;
3905 false, // bool meshShader;
3906 false, // bool useDynamicState;
3907 true, // bool useApiSampleMask;
3908 false, // bool useSampleMaskIn;
3909 false, // bool conservativeEnable;
3910 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, // VkConservativeRasterizationModeEXT conservativeMode;
3911 false, // bool useDepthStencil;
3912 false, // bool fragDepth;
3913 false, // bool fragStencil;
3914 false, // bool multiViewport;
3915 false, // bool colorLayered;
3916 false, // bool srLayered;
3917 1u, // uint32_t numColorLayers;
3918 false, // bool multiView;
3919 false, // bool correlationMask;
3920 false, // bool interlock;
3921 false, // bool sampleLocations;
3922 false, // bool sampleShadingEnable;
3923 false, // bool sampleShadingInput;
3924 true, // bool sampleMaskTest;
3925 false, // bool earlyAndLateTest;
3926 false, // bool garbageAttachment;
3927 false, // bool dsClearOp;
3928 0, // uint32_t dsBaseMipLevel;
3929 false, // bool multiSubpasses;
3930 false, // bool maintenance6;
3931 }));
3932 }
3933
3934 #ifndef CTS_USES_VULKANSC
3935 if (groupParams->useDynamicRendering &&
3936 groupParams->pipelineConstructionType != vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3937 {
3938 group->addChild(new FSRTestCase(
3939 testCtx, "garbage_color_attachment",
3940 {
3941 groupParams, // SharedGroupParams groupParams;
3942 123, // int32_t seed;
3943 {32, 33}, // VkExtent2D framebufferDim;
3944 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
3945 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3946 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3947 AttachmentUsage::NO_ATTACHMENT, // AttachmentUsage attachmentUsage;
3948 false, // bool shaderWritesRate;
3949 false, // bool geometryShader;
3950 false, // bool meshShader;
3951 false, // bool useDynamicState;
3952 false, // bool useApiSampleMask;
3953 false, // bool useSampleMaskIn;
3954 false, // bool conservativeEnable;
3955 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, // VkConservativeRasterizationModeEXT conservativeMode;
3956 false, // bool useDepthStencil;
3957 false, // bool fragDepth;
3958 false, // bool fragStencil;
3959 false, // bool multiViewport;
3960 false, // bool colorLayered;
3961 false, // bool srLayered;
3962 1u, // uint32_t numColorLayers;
3963 false, // bool multiView;
3964 false, // bool correlationMask;
3965 false, // bool interlock;
3966 false, // bool sampleLocations;
3967 false, // bool sampleShadingEnable;
3968 false, // bool sampleShadingInput;
3969 false, // bool sampleMaskTest;
3970 false, // bool earlyAndLateTest;
3971 true, // bool garbageAttachment;
3972 false, // bool dsClearOp;
3973 0, // uint32_t dsBaseMipLevel;
3974 false, // bool multiSubpasses;
3975 false, // bool maintenance6;
3976 }));
3977 }
3978 #endif // CTS_USES_VULKANSC
3979
3980 parentGroup->addChild(group.release());
3981 }
3982 }
3983
3984 } // namespace FragmentShadingRate
3985 } // namespace vkt
3986