1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*
20 * \file vktSparseResourcesShaderIntrinsicsSampled.cpp
21 * \brief Sparse Resources Shader Intrinsics for sampled images
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSparseResourcesShaderIntrinsicsSampled.hpp"
25 #include "vkTypeUtil.hpp"
26 #include "vkCmdUtil.hpp"
27 #include "vkObjUtil.hpp"
28 #include "vkBarrierUtil.hpp"
29 #include "vkBufferWithMemory.hpp"
30
31 using namespace vk;
32
33 namespace vkt
34 {
35 namespace sparse
36 {
37 namespace
38 {
39
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const VkShaderModule geometryModule)40 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
41 const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
42 const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
43 const VkShaderModule geometryModule)
44 {
45 const std::vector<VkViewport> noViewports;
46 const std::vector<VkRect2D> noScissors;
47
48 const VkFormat format = VK_FORMAT_R32G32_SFLOAT;
49 const uint32_t size = tcu::getPixelSize(mapVkFormat(format));
50
51 const VkVertexInputBindingDescription vertexBinding = {
52 0u, // uint32_t binding;
53 size * 2, // uint32_t stride;
54 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
55 };
56
57 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
58 // position
59 {
60 0u, // uint32_t location;
61 0u, // uint32_t binding;
62 format, // VkFormat format;
63 0u // uint32_t offset;
64 },
65 // texture coordinates
66 {
67 1u, // uint32_t location;
68 0u, // uint32_t binding;
69 format, // VkFormat format;
70 size // uint32_t offset;
71 },
72 };
73
74 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
75 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
76 DE_NULL, // const void* pNext;
77 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
78 1u, // uint32_t vertexBindingDescriptionCount;
79 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
80 2u, // uint32_t vertexAttributeDescriptionCount;
81 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
82 };
83
84 const VkColorComponentFlags colorComponentsAll =
85 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
86 const VkPipelineColorBlendAttachmentState defaultColorBlendAttachmentState = {
87 VK_FALSE, // VkBool32 blendEnable;
88 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
89 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
90 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
91 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
92 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
93 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
94 colorComponentsAll // VkColorComponentFlags colorWriteMask;
95 };
96
97 const VkPipelineColorBlendAttachmentState colorBlendAttachmentStates[] = {defaultColorBlendAttachmentState,
98 defaultColorBlendAttachmentState};
99
100 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
101 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
102 DE_NULL, // const void* pNext;
103 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
104 VK_FALSE, // VkBool32 logicOpEnable;
105 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
106 DE_LENGTH_OF_ARRAY(colorBlendAttachmentStates), // uint32_t attachmentCount;
107 colorBlendAttachmentStates, // const VkPipelineColorBlendAttachmentState* pAttachments;
108 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
109 };
110
111 return vk::makeGraphicsPipeline(
112 vk, // const DeviceInterface& vk
113 device, // const VkDevice device
114 pipelineLayout, // const VkPipelineLayout pipelineLayout
115 vertexModule, // const VkShaderModule vertexShaderModule
116 DE_NULL, // const VkShaderModule tessellationControlModule
117 DE_NULL, // const VkShaderModule tessellationEvalModule
118 geometryModule, // const VkShaderModule geometryShaderModule
119 fragmentModule, // const VkShaderModule fragmentShaderModule
120 renderPass, // const VkRenderPass renderPass
121 noViewports, // const std::vector<VkViewport>& viewports
122 noScissors, // const std::vector<VkRect2D>& scissors
123 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology topology
124 0u, // const uint32_t subpass
125 0u, // const uint32_t patchControlPoints
126 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
127 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
128 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
129 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
130 &pipelineColorBlendStateInfo); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
131 }
132
133 } // namespace
134
initPrograms(vk::SourceCollections & programCollection) const135 void SparseShaderIntrinsicsCaseSampledBase::initPrograms(vk::SourceCollections &programCollection) const
136 {
137 const PlanarFormatDescription formatDescription = getPlanarFormatDescription(m_format);
138 const uint32_t numLayers = getNumLayers(m_imageType, m_imageSize);
139 const std::string coordString =
140 getShaderImageCoordinates(m_imageType, "%local_texCoord_x", "%local_texCoord_xy", "%local_texCoord_xyz");
141
142 // Create vertex shader
143 std::ostringstream vs;
144
145 vs << "#version 440\n"
146 << "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n"
147 << "#extension GL_EXT_shader_image_int64 : require\n"
148 << "layout(location = 0) in highp vec2 vs_in_position;\n"
149 << "layout(location = 1) in highp vec2 vs_in_texCoord;\n"
150 << "\n"
151 << "layout(location = 0) out highp vec3 vs_out_texCoord;\n"
152 << "\n"
153 << "out gl_PerVertex {\n"
154 << " vec4 gl_Position;\n"
155 << "};\n"
156 << "void main (void)\n"
157 << "{\n"
158 << " gl_Position = vec4(vs_in_position, 0.0f, 1.0f);\n"
159 << " vs_out_texCoord = vec3(vs_in_texCoord, 0.0f);\n"
160 << "}\n";
161
162 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
163
164 if (numLayers > 1u)
165 {
166 const int32_t maxVertices = 3u * numLayers;
167
168 // Create geometry shader
169 std::ostringstream gs;
170
171 gs << "#version 440\n"
172 << "layout(triangles) in;\n"
173 << "layout(triangle_strip, max_vertices = " << static_cast<int32_t>(maxVertices) << ") out;\n"
174 << "\n"
175 << "in gl_PerVertex {\n"
176 << " vec4 gl_Position;\n"
177 << "} gl_in[];\n"
178 << "out gl_PerVertex {\n"
179 << " vec4 gl_Position;\n"
180 << "};\n"
181 << "layout(location = 0) in highp vec3 gs_in_texCoord[];\n"
182 << "\n"
183 << "layout(location = 0) out highp vec3 gs_out_texCoord;\n"
184 << "\n"
185 << "void main (void)\n"
186 << "{\n"
187 << " for (int layerNdx = 0; layerNdx < " << static_cast<int32_t>(numLayers) << "; ++layerNdx)\n"
188 << " {\n"
189 << " for (int vertexNdx = 0; vertexNdx < gl_in.length(); ++vertexNdx)\n"
190 << " {\n"
191 << " gl_Layer = layerNdx;\n"
192 << " gl_Position = gl_in[vertexNdx].gl_Position;\n"
193 << " gs_out_texCoord = vec3(gs_in_texCoord[vertexNdx].xy, float(layerNdx));\n"
194 << " EmitVertex();\n"
195 << " }\n"
196 << " EndPrimitive();\n"
197 << " }\n"
198 << "}\n";
199
200 programCollection.glslSources.add("geometry_shader") << glu::GeometrySource(gs.str());
201 }
202
203 // Create fragment shader
204 std::ostringstream fs;
205
206 const std::string typeImgComp = getImageComponentTypeName(formatDescription);
207 const std::string typeImgCompVec4 = getImageComponentVec4TypeName(formatDescription);
208
209 SpirvVersion spirvVersion = SPIRV_VERSION_1_0;
210 std::string interfaceList = "";
211
212 if (m_operand.find("Nontemporal") != std::string::npos)
213 {
214 spirvVersion = SPIRV_VERSION_1_6;
215 interfaceList = " %uniformconst_image_sparse %uniformblock_instance";
216 }
217
218 fs << "OpCapability Shader\n"
219 << "OpCapability SampledCubeArray\n"
220 << "OpCapability ImageCubeArray\n"
221 << "OpCapability SparseResidency\n"
222 << "OpCapability StorageImageExtendedFormats\n";
223
224 if (formatIsR64(m_format))
225 {
226 fs << "OpCapability Int64\n"
227 << "OpCapability Int64ImageEXT\n"
228 << "OpExtension \"SPV_EXT_shader_image_int64\"\n";
229 }
230
231 fs << "%ext_import = OpExtInstImport \"GLSL.std.450\"\n"
232 << "OpMemoryModel Logical GLSL450\n"
233 << "OpEntryPoint Fragment %func_main \"main\" %varying_texCoord %output_texel %output_residency "
234 << interfaceList << "\n"
235 << "OpExecutionMode %func_main OriginUpperLeft\n"
236 << "OpSource GLSL 440\n"
237
238 << "OpName %func_main \"main\"\n"
239
240 << "OpName %varying_texCoord \"varying_texCoord\"\n"
241
242 << "OpName %output_texel \"out_texel\"\n"
243 << "OpName %output_residency \"out_residency\"\n"
244
245 << "OpName %type_uniformblock \"LodBlock\"\n"
246 << "OpMemberName %type_uniformblock 0 \"lod\"\n"
247 << "OpMemberName %type_uniformblock 1 \"size\"\n"
248 << "OpName %uniformblock_instance \"lodInstance\"\n"
249
250 << "OpName %uniformconst_image_sparse \"u_imageSparse\"\n"
251
252 << "OpDecorate %varying_texCoord Location 0\n"
253
254 << "OpDecorate %output_texel Location 0\n"
255 << "OpDecorate %output_residency Location 1\n"
256
257 << "OpDecorate %type_uniformblock Block\n"
258 << "OpMemberDecorate %type_uniformblock 0 Offset 0\n"
259 << "OpMemberDecorate %type_uniformblock 1 Offset 8\n"
260
261 << "OpDecorate %uniformconst_image_sparse DescriptorSet 0\n"
262 << "OpDecorate %uniformconst_image_sparse Binding " << BINDING_IMAGE_SPARSE << "\n"
263
264 << "%type_void = OpTypeVoid\n"
265 << "%type_void_func = OpTypeFunction %type_void\n"
266
267 << "%type_bool = OpTypeBool\n"
268 << "%type_int = OpTypeInt 32 1\n"
269 << "%type_uint = OpTypeInt 32 0\n"
270 << "%type_float = OpTypeFloat 32\n"
271 << "%type_vec2 = OpTypeVector %type_float 2\n"
272 << "%type_vec3 = OpTypeVector %type_float 3\n"
273 << "%type_vec4 = OpTypeVector %type_float 4\n"
274 << "%type_ivec4 = OpTypeVector %type_int 4\n"
275 << "%type_uvec4 = OpTypeVector %type_uint 4\n"
276 << "%type_uniformblock = OpTypeStruct %type_uint %type_vec2\n";
277
278 if (formatIsR64(m_format))
279 {
280 fs << "%type_int64 = OpTypeInt 64 1\n"
281 << "%type_uint64 = OpTypeInt 64 0\n"
282 << "%type_i64vec2 = OpTypeVector %type_int64 2\n"
283 << "%type_i64vec3 = OpTypeVector %type_int64 3\n"
284 << "%type_i64vec4 = OpTypeVector %type_int64 4\n"
285 << "%type_u64vec3 = OpTypeVector %type_uint64 3\n"
286 << "%type_u64vec4 = OpTypeVector %type_uint64 4\n";
287 }
288
289 fs << "%type_struct_int_img_comp_vec4 = OpTypeStruct %type_int " << typeImgCompVec4 << "\n"
290 << "%type_input_vec3 = OpTypePointer Input %type_vec3\n"
291 << "%type_input_float = OpTypePointer Input %type_float\n";
292
293 if (formatIsR64(m_format))
294 fs << "%type_output_img_comp_vec4 = OpTypePointer Output "
295 << "%type_ivec4"
296 << "\n";
297 else
298 fs << "%type_output_img_comp_vec4 = OpTypePointer Output " << typeImgCompVec4 << "\n";
299
300 fs << "%type_output_uint = OpTypePointer Output %type_uint\n"
301
302 << "%type_function_int = OpTypePointer Function %type_int\n"
303 << "%type_function_img_comp_vec4 = OpTypePointer Function " << typeImgCompVec4 << "\n"
304 << "%type_function_int_img_comp_vec4 = OpTypePointer Function %type_struct_int_img_comp_vec4\n"
305
306 << "%type_pushconstant_uniformblock = OpTypePointer PushConstant %type_uniformblock\n"
307 << "%type_pushconstant_uniformblock_member_lod = OpTypePointer PushConstant %type_uint\n"
308 << "%type_pushconstant_uniformblock_member_size = OpTypePointer PushConstant %type_vec2\n"
309
310 << "%type_image_sparse = " << getOpTypeImageSparse(m_imageType, m_format, typeImgComp, true) << "\n"
311 << "%type_sampled_image_sparse = OpTypeSampledImage %type_image_sparse\n"
312 << "%type_uniformconst_image_sparse = OpTypePointer UniformConstant %type_sampled_image_sparse\n"
313
314 << "%varying_texCoord = OpVariable %type_input_vec3 Input\n"
315
316 << "%output_texel = OpVariable %type_output_img_comp_vec4 Output\n"
317 << "%output_residency = OpVariable %type_output_uint Output\n"
318
319 << "%uniformconst_image_sparse = OpVariable %type_uniformconst_image_sparse UniformConstant\n"
320
321 << "%uniformblock_instance = OpVariable %type_pushconstant_uniformblock PushConstant\n"
322
323 // Declare constants
324 << "%constant_uint_0 = OpConstant %type_uint 0\n"
325 << "%constant_uint_1 = OpConstant %type_uint 1\n"
326 << "%constant_uint_2 = OpConstant %type_uint 2\n"
327 << "%constant_uint_3 = OpConstant %type_uint 3\n"
328 << "%constant_int_0 = OpConstant %type_int 0\n"
329 << "%constant_int_1 = OpConstant %type_int 1\n"
330 << "%constant_int_2 = OpConstant %type_int 2\n"
331 << "%constant_int_3 = OpConstant %type_int 3\n"
332 << "%constant_float_0 = OpConstant %type_float 0.0\n"
333 << "%constant_float_half = OpConstant %type_float 0.5\n"
334 << "%constant_texel_resident = OpConstant %type_uint " << MEMORY_BLOCK_BOUND_VALUE << "\n"
335 << "%constant_texel_not_resident = OpConstant %type_uint " << MEMORY_BLOCK_NOT_BOUND_VALUE
336 << "\n"
337
338 // Call main function
339 << "%func_main = OpFunction %type_void None %type_void_func\n"
340 << "%label_func_main = OpLabel\n"
341
342 << "%local_image_sparse = OpLoad %type_sampled_image_sparse %uniformconst_image_sparse\n"
343
344 << "%texCoord = OpLoad %type_vec3 %varying_texCoord\n"
345
346 << "%local_texCoord_x = OpCompositeExtract %type_float %texCoord 0\n"
347 << "%local_texCoord_y = OpCompositeExtract %type_float %texCoord 1\n"
348 << "%local_texCoord_z = OpCompositeExtract %type_float %texCoord 2\n"
349
350 << "%local_texCoord_xy = OpCompositeConstruct %type_vec2 %local_texCoord_x %local_texCoord_y\n"
351 << "%local_texCoord_xyz = OpCompositeConstruct %type_vec3 %local_texCoord_x %local_texCoord_y "
352 "%local_texCoord_z\n"
353
354 << "%access_uniformblock_member_uint_lod = OpAccessChain %type_pushconstant_uniformblock_member_lod "
355 "%uniformblock_instance %constant_int_0\n"
356 << "%local_uniformblock_member_uint_lod = OpLoad %type_uint %access_uniformblock_member_uint_lod\n"
357 << "%local_uniformblock_member_float_lod = OpConvertUToF %type_float %local_uniformblock_member_uint_lod\n"
358 << "%access_uniformblock_member_size = OpAccessChain %type_pushconstant_uniformblock_member_size "
359 "%uniformblock_instance %constant_int_1\n"
360 << "%local_uniformblock_member_size = OpLoad %type_vec2 %access_uniformblock_member_size\n"
361
362 << sparseImageOpString("%local_sparse_op_result", "%type_struct_int_img_comp_vec4", "%local_image_sparse",
363 coordString, "%local_uniformblock_member_float_lod")
364 << "\n"
365
366 // Load texel value
367 << "%local_img_comp_vec4 = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_op_result 1\n";
368
369 if (formatIsR64(m_format))
370 {
371 fs << "%local_img_comp32b = OpSConvert %type_ivec4 %local_img_comp_vec4\n"
372 << "OpStore %output_texel %local_img_comp32b\n";
373 }
374 else
375 {
376 fs << "OpStore %output_texel %local_img_comp_vec4\n";
377 }
378
379 // Load residency code
380 fs << "%local_residency_code = OpCompositeExtract %type_int %local_sparse_op_result 0\n"
381
382 // Check if loaded texel is placed in resident memory
383 << "%local_texel_resident = OpImageSparseTexelsResident %type_bool %local_residency_code\n"
384 << "OpSelectionMerge %branch_texel_resident None\n"
385 << "OpBranchConditional %local_texel_resident %label_texel_resident %label_texel_not_resident\n"
386 << "%label_texel_resident = OpLabel\n"
387
388 // Loaded texel is in resident memory
389 << "OpStore %output_residency %constant_texel_resident\n"
390
391 << "OpBranch %branch_texel_resident\n"
392 << "%label_texel_not_resident = OpLabel\n"
393
394 // Loaded texel is not in resident memory
395 << "OpStore %output_residency %constant_texel_not_resident\n"
396
397 << "OpBranch %branch_texel_resident\n"
398 << "%branch_texel_resident = OpLabel\n"
399
400 << "OpReturn\n"
401 << "OpFunctionEnd\n";
402
403 programCollection.spirvAsmSources.add("fragment_shader")
404 << fs.str() << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, spirvVersion);
405 }
406
sparseImageOpString(const std::string & resultVariable,const std::string & resultType,const std::string & image,const std::string & coord,const std::string & miplevel) const407 std::string SparseCaseOpImageSparseSampleExplicitLod::sparseImageOpString(const std::string &resultVariable,
408 const std::string &resultType,
409 const std::string &image,
410 const std::string &coord,
411 const std::string &miplevel) const
412 {
413 std::ostringstream src;
414 std::string additionalOperand = (m_operand.empty() ? " " : (std::string("|") + m_operand + " "));
415
416 src << resultVariable << " = OpImageSparseSampleExplicitLod " << resultType << " " << image << " " << coord
417 << " Lod" << additionalOperand << miplevel << "\n";
418
419 return src.str();
420 }
421
sparseImageOpString(const std::string & resultVariable,const std::string & resultType,const std::string & image,const std::string & coord,const std::string & miplevel) const422 std::string SparseCaseOpImageSparseSampleImplicitLod::sparseImageOpString(const std::string &resultVariable,
423 const std::string &resultType,
424 const std::string &image,
425 const std::string &coord,
426 const std::string &miplevel) const
427 {
428 DE_UNREF(miplevel);
429
430 std::ostringstream src;
431
432 src << resultVariable << " = OpImageSparseSampleImplicitLod " << resultType << " " << image << " " << coord << " "
433 << m_operand << "\n";
434
435 return src.str();
436 }
437
sparseImageOpString(const std::string & resultVariable,const std::string & resultType,const std::string & image,const std::string & coord,const std::string & miplevel) const438 std::string SparseCaseOpImageSparseGather::sparseImageOpString(const std::string &resultVariable,
439 const std::string &resultType, const std::string &image,
440 const std::string &coord,
441 const std::string &miplevel) const
442 {
443 DE_UNREF(miplevel);
444
445 std::ostringstream src;
446
447 const PlanarFormatDescription formatDescription = getPlanarFormatDescription(m_format);
448 const std::string typeImgComp = getImageComponentTypeName(formatDescription);
449 const std::string typeImgCompVec4 = getImageComponentVec4TypeName(formatDescription);
450
451 // Bias the coord value by half a texel, so we sample from center of 2x2 gather rectangle
452
453 src << "%local_image_width = OpCompositeExtract %type_float %local_uniformblock_member_size 0\n";
454 src << "%local_image_height = OpCompositeExtract %type_float %local_uniformblock_member_size 1\n";
455 src << "%local_coord_x_bias = OpFDiv %type_float %constant_float_half %local_image_width\n";
456 src << "%local_coord_y_bias = OpFDiv %type_float %constant_float_half %local_image_height\n";
457
458 switch (m_imageType)
459 {
460 case IMAGE_TYPE_2D:
461 {
462 src << "%local_coord_bias = OpCompositeConstruct %type_vec2 %local_coord_x_bias %local_coord_y_bias\n";
463 src << "%local_coord_biased = OpFAdd %type_vec2 " << coord << " %local_coord_bias\n";
464
465 break;
466 }
467
468 case IMAGE_TYPE_2D_ARRAY:
469 case IMAGE_TYPE_3D:
470 {
471 src << "%local_coord_bias = OpCompositeConstruct %type_vec3 %local_coord_x_bias %local_coord_y_bias "
472 "%constant_float_0\n";
473 src << "%local_coord_biased = OpFAdd %type_vec3 " << coord << " %local_coord_bias\n";
474
475 break;
476 }
477
478 default:
479 {
480 DE_FATAL("Unexpected image type");
481 }
482 }
483
484 src << "%local_sparse_gather_result_x = OpImageSparseGather " << resultType << " " << image
485 << " %local_coord_biased %constant_int_0 " + m_operand + "\n";
486 src << "%local_sparse_gather_result_y = OpImageSparseGather " << resultType << " " << image
487 << " %local_coord_biased %constant_int_1 " + m_operand + "\n";
488 src << "%local_sparse_gather_result_z = OpImageSparseGather " << resultType << " " << image
489 << " %local_coord_biased %constant_int_2 " + m_operand + "\n";
490 src << "%local_sparse_gather_result_w = OpImageSparseGather " << resultType << " " << image
491 << " %local_coord_biased %constant_int_3 " + m_operand + "\n";
492
493 src << "%local_gather_residency_code = OpCompositeExtract %type_int %local_sparse_gather_result_x 0\n";
494
495 src << "%local_gather_texels_x = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_x 1\n";
496 src << "%local_gather_texels_y = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_y 1\n";
497 src << "%local_gather_texels_z = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_z 1\n";
498 src << "%local_gather_texels_w = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_w 1\n";
499
500 src << "%local_gather_primary_texel_x = OpCompositeExtract " << typeImgComp << " %local_gather_texels_x 3\n";
501 src << "%local_gather_primary_texel_y = OpCompositeExtract " << typeImgComp << " %local_gather_texels_y 3\n";
502 src << "%local_gather_primary_texel_z = OpCompositeExtract " << typeImgComp << " %local_gather_texels_z 3\n";
503 src << "%local_gather_primary_texel_w = OpCompositeExtract " << typeImgComp << " %local_gather_texels_w 3\n";
504
505 src << "%local_gather_primary_texel = OpCompositeConstruct " << typeImgCompVec4
506 << " %local_gather_primary_texel_x %local_gather_primary_texel_y %local_gather_primary_texel_z "
507 "%local_gather_primary_texel_w\n";
508 src << resultVariable << " = OpCompositeConstruct " << resultType
509 << " %local_gather_residency_code %local_gather_primary_texel\n";
510
511 return src.str();
512 }
513
514 class SparseShaderIntrinsicsInstanceSampledBase : public SparseShaderIntrinsicsInstanceBase
515 {
516 public:
SparseShaderIntrinsicsInstanceSampledBase(Context & context,const SpirVFunction function,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)517 SparseShaderIntrinsicsInstanceSampledBase(Context &context, const SpirVFunction function, const ImageType imageType,
518 const tcu::UVec3 &imageSize, const VkFormat format)
519 : SparseShaderIntrinsicsInstanceBase(context, function, imageType, imageSize, format)
520 {
521 }
522
523 VkImageUsageFlags imageSparseUsageFlags(void) const;
524 VkImageUsageFlags imageOutputUsageFlags(void) const;
525
526 VkQueueFlags getQueueFlags(void) const;
527
528 void recordCommands(const VkCommandBuffer commandBuffer, const VkImageCreateInfo &imageSparseInfo,
529 const VkImage imageSparse, const VkImage imageTexels, const VkImage imageResidency);
530
531 virtual void checkSupport(VkImageCreateInfo imageSparseInfo) const;
532
533 virtual VkImageSubresourceRange sampledImageRangeToBind(const VkImageCreateInfo &imageSparseInfo,
534 const uint32_t mipLevel) const = 0;
535
536 private:
537 typedef de::SharedPtr<vk::Unique<VkFramebuffer>> VkFramebufferSp;
538
539 Move<VkBuffer> m_vertexBuffer;
540 de::MovePtr<Allocation> m_vertexBufferAlloc;
541 std::vector<VkFramebufferSp> m_framebuffers;
542 Move<VkRenderPass> m_renderPass;
543 Move<VkSampler> m_sampler;
544 };
545
imageSparseUsageFlags(void) const546 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageSparseUsageFlags(void) const
547 {
548 return VK_IMAGE_USAGE_SAMPLED_BIT;
549 }
550
imageOutputUsageFlags(void) const551 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageOutputUsageFlags(void) const
552 {
553 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
554 }
555
getQueueFlags(void) const556 VkQueueFlags SparseShaderIntrinsicsInstanceSampledBase::getQueueFlags(void) const
557 {
558 return VK_QUEUE_GRAPHICS_BIT;
559 }
560
checkSupport(VkImageCreateInfo imageSparseInfo) const561 void SparseShaderIntrinsicsInstanceSampledBase::checkSupport(VkImageCreateInfo imageSparseInfo) const
562 {
563 const InstanceInterface &instance = m_context.getInstanceInterface();
564 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
565 const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
566
567 SparseShaderIntrinsicsInstanceBase::checkSupport(imageSparseInfo);
568
569 if (imageSparseInfo.extent.width > deviceProperties.limits.maxFramebufferWidth ||
570 imageSparseInfo.extent.height > deviceProperties.limits.maxFramebufferHeight ||
571 imageSparseInfo.arrayLayers > deviceProperties.limits.maxFramebufferLayers)
572 {
573 TCU_THROW(NotSupportedError, "Image size exceeds allowed framebuffer dimensions");
574 }
575
576 // Check if device supports image format for sampled images
577 if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format,
578 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
579 TCU_THROW(NotSupportedError, "Device does not support image format for sampled images");
580
581 // Check if device supports image format for color attachment
582 if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format,
583 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
584 TCU_THROW(NotSupportedError, "Device does not support image format for color attachment");
585
586 // Make sure device supports VK_FORMAT_R32_UINT format for color attachment
587 if (!checkImageFormatFeatureSupport(instance, physicalDevice, mapTextureFormat(m_residencyFormat),
588 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
589 TCU_THROW(TestError, "Device does not support VK_FORMAT_R32_UINT format for color attachment");
590 }
591
recordCommands(const VkCommandBuffer commandBuffer,const VkImageCreateInfo & imageSparseInfo,const VkImage imageSparse,const VkImage imageTexels,const VkImage imageResidency)592 void SparseShaderIntrinsicsInstanceSampledBase::recordCommands(const VkCommandBuffer commandBuffer,
593 const VkImageCreateInfo &imageSparseInfo,
594 const VkImage imageSparse, const VkImage imageTexels,
595 const VkImage imageResidency)
596 {
597 const InstanceInterface &instance = m_context.getInstanceInterface();
598 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
599 const DeviceInterface &deviceInterface = getDeviceInterface();
600
601 // Create buffer storing vertex data
602 std::vector<tcu::Vec2> vertexData;
603
604 vertexData.push_back(tcu::Vec2(-1.0f, -1.0f));
605 vertexData.push_back(tcu::Vec2(0.0f, 0.0f));
606
607 vertexData.push_back(tcu::Vec2(-1.0f, 1.0f));
608 vertexData.push_back(tcu::Vec2(0.0f, 1.0f));
609
610 vertexData.push_back(tcu::Vec2(1.0f, -1.0f));
611 vertexData.push_back(tcu::Vec2(1.0f, 0.0f));
612
613 vertexData.push_back(tcu::Vec2(1.0f, 1.0f));
614 vertexData.push_back(tcu::Vec2(1.0f, 1.0f));
615
616 const VkDeviceSize vertexDataSizeInBytes = sizeInBytes(vertexData);
617 const VkBufferCreateInfo vertexBufferCreateInfo =
618 makeBufferCreateInfo(vertexDataSizeInBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
619
620 m_vertexBuffer = createBuffer(deviceInterface, getDevice(), &vertexBufferCreateInfo);
621 m_vertexBufferAlloc =
622 bindBuffer(deviceInterface, getDevice(), getAllocator(), *m_vertexBuffer, MemoryRequirement::HostVisible);
623
624 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &vertexData[0], static_cast<std::size_t>(vertexDataSizeInBytes));
625 flushAlloc(deviceInterface, getDevice(), *m_vertexBufferAlloc);
626
627 // Create render pass
628 const VkAttachmentDescription texelsAttachmentDescription = {
629 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
630 imageSparseInfo.format, // VkFormat format;
631 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
632 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
633 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
634 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
635 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
636 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
637 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
638 };
639
640 const VkAttachmentDescription residencyAttachmentDescription = {
641 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
642 mapTextureFormat(m_residencyFormat), // VkFormat format;
643 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
644 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
645 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
646 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
647 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
648 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
649 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
650 };
651
652 const VkAttachmentDescription colorAttachmentsDescription[] = {texelsAttachmentDescription,
653 residencyAttachmentDescription};
654
655 const VkAttachmentReference texelsAttachmentReference = {
656 0u, // uint32_t attachment;
657 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
658 };
659
660 const VkAttachmentReference residencyAttachmentReference = {
661 1u, // uint32_t attachment;
662 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
663 };
664
665 const VkAttachmentReference colorAttachmentsReference[] = {texelsAttachmentReference, residencyAttachmentReference};
666
667 const VkAttachmentReference depthAttachmentReference = {
668 VK_ATTACHMENT_UNUSED, // uint32_t attachment;
669 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout;
670 };
671
672 const VkSubpassDescription subpassDescription = {
673 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
674 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
675 0u, // uint32_t inputAttachmentCount;
676 DE_NULL, // const VkAttachmentReference* pInputAttachments;
677 2u, // uint32_t colorAttachmentCount;
678 colorAttachmentsReference, // const VkAttachmentReference* pColorAttachments;
679 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
680 &depthAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
681 0u, // uint32_t preserveAttachmentCount;
682 DE_NULL // const uint32_t* pPreserveAttachments;
683 };
684
685 const VkRenderPassCreateInfo renderPassInfo = {
686 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
687 DE_NULL, // const void* pNext;
688 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
689 2u, // uint32_t attachmentCount;
690 colorAttachmentsDescription, // const VkAttachmentDescription* pAttachments;
691 1u, // uint32_t subpassCount;
692 &subpassDescription, // const VkSubpassDescription* pSubpasses;
693 0u, // uint32_t dependencyCount;
694 DE_NULL // const VkSubpassDependency* pDependencies;
695 };
696
697 m_renderPass = createRenderPass(deviceInterface, getDevice(), &renderPassInfo);
698
699 // Create descriptor set layout
700 DescriptorSetLayoutBuilder descriptorLayerBuilder;
701
702 descriptorLayerBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
703
704 const Unique<VkDescriptorSetLayout> descriptorSetLayout(descriptorLayerBuilder.build(deviceInterface, getDevice()));
705
706 // Create descriptor pool
707 DescriptorPoolBuilder descriptorPoolBuilder;
708
709 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageSparseInfo.mipLevels);
710
711 descriptorPool = descriptorPoolBuilder.build(
712 deviceInterface, getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageSparseInfo.mipLevels);
713
714 VkSamplerCreateInfo samplerCreateInfo = {
715 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
716 DE_NULL,
717 (VkSamplerCreateFlags)0,
718 mapFilterMode(tcu::Sampler::NEAREST), // magFilter
719 mapFilterMode(tcu::Sampler::NEAREST_MIPMAP_NEAREST), // minFilter
720 mapMipmapMode(tcu::Sampler::NEAREST_MIPMAP_NEAREST), // mipMode
721 mapWrapMode(tcu::Sampler::REPEAT_GL), // addressU
722 mapWrapMode(tcu::Sampler::REPEAT_GL), // addressV
723 mapWrapMode(tcu::Sampler::REPEAT_GL), // addressW
724 0.0f, // mipLodBias
725 VK_FALSE, // anisotropyEnable
726 1.0f, // maxAnisotropy
727 VK_FALSE, // compareEnable
728 mapCompareMode(tcu::Sampler::COMPAREMODE_ALWAYS), // compareOp
729 0.0f, // minLod
730 1000.0f, // maxLod
731 VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // borderColor
732 VK_FALSE, // unnormalizedCoords
733 };
734 m_sampler = createSampler(deviceInterface, getDevice(), &samplerCreateInfo);
735
736 struct PushConstants
737 {
738 uint32_t lod;
739 uint32_t padding; // padding needed to satisfy std430 rules
740 float lodWidth;
741 float lodHeight;
742 };
743
744 // Create pipeline layout
745 const VkPushConstantRange lodConstantRange = {
746 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
747 0u, // uint32_t offset;
748 sizeof(PushConstants), // uint32_t size;
749 };
750
751 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
752 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
753 DE_NULL, // const void* pNext;
754 0u, // VkPipelineLayoutCreateFlags flags;
755 1u, // uint32_t setLayoutCount;
756 &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
757 1u, // uint32_t pushConstantRangeCount;
758 &lodConstantRange, // const VkPushConstantRange* pPushConstantRanges;
759 };
760
761 pipelineLayout = createPipelineLayout(deviceInterface, getDevice(), &pipelineLayoutParams);
762
763 // Create graphics pipeline
764 {
765 Move<VkShaderModule> vertexModule =
766 createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("vertex_shader"),
767 (VkShaderModuleCreateFlags)0);
768 Move<VkShaderModule> fragmentModule =
769 createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("fragment_shader"),
770 (VkShaderModuleCreateFlags)0);
771 Move<VkShaderModule> geometryModule;
772
773 if (imageSparseInfo.arrayLayers > 1u)
774 {
775 requireFeatures(instance, physicalDevice, FEATURE_GEOMETRY_SHADER);
776 geometryModule =
777 createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("geometry_shader"),
778 (VkShaderModuleCreateFlags)0);
779 }
780
781 pipelines.push_back(
782 makeVkSharedPtr(makeGraphicsPipeline(deviceInterface, getDevice(), *pipelineLayout, *m_renderPass,
783 *vertexModule, *fragmentModule, *geometryModule)));
784 }
785
786 const VkPipeline graphicsPipeline = **pipelines[0];
787
788 {
789 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(
790 VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
791
792 VkImageMemoryBarrier imageShaderAccessBarriers[3];
793
794 imageShaderAccessBarriers[0] = makeImageMemoryBarrier(
795 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
796 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, imageSparse, fullImageSubresourceRange);
797
798 imageShaderAccessBarriers[1] =
799 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
800 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, imageTexels, fullImageSubresourceRange);
801
802 imageShaderAccessBarriers[2] =
803 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
804 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, imageResidency, fullImageSubresourceRange);
805
806 deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
807 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
808 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
809 0u, 0u, DE_NULL, 0u, DE_NULL, 3u, imageShaderAccessBarriers);
810 }
811
812 imageSparseViews.resize(imageSparseInfo.mipLevels);
813 imageTexelsViews.resize(imageSparseInfo.mipLevels);
814 imageResidencyViews.resize(imageSparseInfo.mipLevels);
815 m_framebuffers.resize(imageSparseInfo.mipLevels);
816 descriptorSets.resize(imageSparseInfo.mipLevels);
817
818 std::vector<VkClearValue> clearValues;
819 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
820 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
821
822 for (uint32_t mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
823 {
824 const VkExtent3D mipLevelSize = mipLevelExtents(imageSparseInfo.extent, mipLevelNdx);
825 const VkRect2D renderArea = makeRect2D(mipLevelSize);
826 const VkViewport viewport = makeViewport(mipLevelSize);
827 const VkImageSubresourceRange mipLevelRange =
828 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevelNdx, 1u, 0u, imageSparseInfo.arrayLayers);
829
830 // Create color attachments image views
831 imageTexelsViews[mipLevelNdx] =
832 makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageTexels, mapImageViewType(m_imageType),
833 imageSparseInfo.format, mipLevelRange));
834 imageResidencyViews[mipLevelNdx] =
835 makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageResidency, mapImageViewType(m_imageType),
836 mapTextureFormat(m_residencyFormat), mipLevelRange));
837
838 const VkImageView attachmentsViews[] = {**imageTexelsViews[mipLevelNdx], **imageResidencyViews[mipLevelNdx]};
839
840 // Create framebuffer
841 const VkFramebufferCreateInfo framebufferInfo = {
842 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
843 DE_NULL, // const void* pNext;
844 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
845 *m_renderPass, // VkRenderPass renderPass;
846 2u, // uint32_t attachmentCount;
847 attachmentsViews, // const VkImageView* pAttachments;
848 mipLevelSize.width, // uint32_t width;
849 mipLevelSize.height, // uint32_t height;
850 imageSparseInfo.arrayLayers, // uint32_t layers;
851 };
852
853 m_framebuffers[mipLevelNdx] =
854 makeVkSharedPtr(createFramebuffer(deviceInterface, getDevice(), &framebufferInfo));
855
856 // Create descriptor set
857 descriptorSets[mipLevelNdx] =
858 makeVkSharedPtr(makeDescriptorSet(deviceInterface, getDevice(), *descriptorPool, *descriptorSetLayout));
859 const VkDescriptorSet descriptorSet = **descriptorSets[mipLevelNdx];
860
861 // Update descriptor set
862 const VkImageSubresourceRange sparseImageSubresourceRange =
863 sampledImageRangeToBind(imageSparseInfo, mipLevelNdx);
864
865 imageSparseViews[mipLevelNdx] =
866 makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageSparse, mapImageViewType(m_imageType),
867 imageSparseInfo.format, sparseImageSubresourceRange));
868
869 const VkDescriptorImageInfo imageSparseDescInfo = makeDescriptorImageInfo(
870 *m_sampler, **imageSparseViews[mipLevelNdx], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
871
872 DescriptorSetUpdateBuilder descriptorUpdateBuilder;
873
874 descriptorUpdateBuilder.writeSingle(descriptorSet,
875 DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_SPARSE),
876 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSparseDescInfo);
877 descriptorUpdateBuilder.update(deviceInterface, getDevice());
878
879 beginRenderPass(deviceInterface, commandBuffer, *m_renderPass, **m_framebuffers[mipLevelNdx], renderArea,
880 (uint32_t)clearValues.size(), &clearValues[0]);
881
882 // Bind graphics pipeline
883 deviceInterface.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
884
885 // Bind descriptor set
886 deviceInterface.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
887 &descriptorSet, 0u, DE_NULL);
888
889 // Bind vertex buffer
890 {
891 const VkDeviceSize offset = 0ull;
892 deviceInterface.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &m_vertexBuffer.get(), &offset);
893 }
894
895 // Bind Viewport
896 deviceInterface.cmdSetViewport(commandBuffer, 0u, 1u, &viewport);
897
898 // Bind Scissor Rectangle
899 deviceInterface.cmdSetScissor(commandBuffer, 0u, 1u, &renderArea);
900
901 const PushConstants pushConstants = {mipLevelNdx,
902 0u, // padding
903 static_cast<float>(mipLevelSize.width),
904 static_cast<float>(mipLevelSize.height)};
905
906 // Update push constants
907 deviceInterface.cmdPushConstants(commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u,
908 sizeof(PushConstants), &pushConstants);
909
910 // Draw full screen quad
911 deviceInterface.cmdDraw(commandBuffer, 4u, 1u, 0u, 0u);
912
913 // End render pass
914 endRenderPass(deviceInterface, commandBuffer);
915 }
916
917 {
918 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(
919 VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
920
921 VkImageMemoryBarrier imageOutputTransferSrcBarriers[2];
922
923 imageOutputTransferSrcBarriers[0] = makeImageMemoryBarrier(
924 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
925 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageTexels, fullImageSubresourceRange);
926
927 imageOutputTransferSrcBarriers[1] = makeImageMemoryBarrier(
928 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
929 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageResidency, fullImageSubresourceRange);
930
931 deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
932 VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u,
933 imageOutputTransferSrcBarriers);
934 }
935 }
936
937 class SparseShaderIntrinsicsInstanceSampledExplicit : public SparseShaderIntrinsicsInstanceSampledBase
938 {
939 public:
SparseShaderIntrinsicsInstanceSampledExplicit(Context & context,const SpirVFunction function,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)940 SparseShaderIntrinsicsInstanceSampledExplicit(Context &context, const SpirVFunction function,
941 const ImageType imageType, const tcu::UVec3 &imageSize,
942 const VkFormat format)
943 : SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format)
944 {
945 }
946
sampledImageRangeToBind(const VkImageCreateInfo & imageSparseInfo,const uint32_t mipLevel) const947 VkImageSubresourceRange sampledImageRangeToBind(const VkImageCreateInfo &imageSparseInfo,
948 const uint32_t mipLevel) const
949 {
950 DE_UNREF(mipLevel);
951 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u,
952 imageSparseInfo.arrayLayers);
953 }
954 };
955
createInstance(Context & context) const956 TestInstance *SparseShaderIntrinsicsCaseSampledExplicit::createInstance(Context &context) const
957 {
958 return new SparseShaderIntrinsicsInstanceSampledExplicit(context, m_function, m_imageType, m_imageSize, m_format);
959 }
960
961 class SparseShaderIntrinsicsInstanceSampledImplicit : public SparseShaderIntrinsicsInstanceSampledBase
962 {
963 public:
SparseShaderIntrinsicsInstanceSampledImplicit(Context & context,const SpirVFunction function,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)964 SparseShaderIntrinsicsInstanceSampledImplicit(Context &context, const SpirVFunction function,
965 const ImageType imageType, const tcu::UVec3 &imageSize,
966 const VkFormat format)
967 : SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format)
968 {
969 }
970
sampledImageRangeToBind(const VkImageCreateInfo & imageSparseInfo,const uint32_t mipLevel) const971 VkImageSubresourceRange sampledImageRangeToBind(const VkImageCreateInfo &imageSparseInfo,
972 const uint32_t mipLevel) const
973 {
974 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, 0u, imageSparseInfo.arrayLayers);
975 }
976 };
977
createInstance(Context & context) const978 TestInstance *SparseShaderIntrinsicsCaseSampledImplicit::createInstance(Context &context) const
979 {
980 return new SparseShaderIntrinsicsInstanceSampledImplicit(context, m_function, m_imageType, m_imageSize, m_format);
981 }
982
983 } // namespace sparse
984 } // namespace vkt
985