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