1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Multisampled image load/store Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktImageMultisampleLoadStoreTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageLoadStoreUtil.hpp"
29 #include "vktImageTexture.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkImageUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "deUniquePtr.hpp"
45
46 #include "tcuTextureUtil.hpp"
47 #include "tcuTestLog.hpp"
48
49 #include <string>
50 #include <vector>
51
52 namespace vkt
53 {
54 namespace image
55 {
56 namespace
57 {
58 using namespace vk;
59 using de::MovePtr;
60 using de::UniquePtr;
61 using tcu::IVec3;
62
63 static const VkFormat CHECKSUM_IMAGE_FORMAT = VK_FORMAT_R32_SINT;
64
65 struct CaseDef
66 {
67 Texture texture;
68 VkFormat format;
69 VkSampleCountFlagBits numSamples;
70 bool singleLayerBind;
71 };
72
73 // Multisampled storage image test.
74 //
75 // Pass 1: Write a slightly different color pattern per-sample to the whole image.
76 // Pass 2: Read samples of the same image and check if color values are in the expected range.
77 // Write back results as a checksum image and verify them on the host.
78 // Each checksum image pixel should contain an integer equal to the number of samples.
79
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)80 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
81 {
82 const int dimension = (caseDef.singleLayerBind ? caseDef.texture.layerDimension() : caseDef.texture.dimension());
83 const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
84
85 const ImageType usedImageType = (caseDef.singleLayerBind ? getImageTypeForSingleLayer(caseDef.texture.type()) : caseDef.texture.type());
86 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(caseDef.format));
87 const std::string msImageTypeStr = getShaderImageType(mapVkFormat(caseDef.format), usedImageType, (caseDef.texture.numSamples() > 1));
88
89 const std::string xMax = de::toString(caseDef.texture.size().x() - 1);
90 const std::string yMax = de::toString(caseDef.texture.size().y() - 1);
91 const std::string signednessPrefix = isUintFormat(caseDef.format) ? "u" : isIntFormat(caseDef.format) ? "i" : "";
92 const std::string gvec4Expr = signednessPrefix + "vec4";
93 const int numColorComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.format).order);
94
95 const float storeColorScale = computeStoreColorScale(caseDef.format, caseDef.texture.size());
96 const float storeColorBias = computeStoreColorBias(caseDef.format);
97 DE_ASSERT(colorScaleAndBiasAreValid(caseDef.format, storeColorScale, storeColorBias));
98
99 const std::string colorScaleExpr = (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
100 + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
101 const std::string colorExpr =
102 gvec4Expr + "("
103 + "gx^gy^gz^(sampleNdx >> 5)^(sampleNdx & 31), " // we "split" sampleNdx to keep this value in [0, 31] range for numSamples = 64 case
104 + (numColorComponents > 1 ? "(" + xMax + "-gx)^gy^gz, " : "0, ")
105 + (numColorComponents > 2 ? "gx^(" + yMax + "-gy)^gz, " : "0, ")
106 + (numColorComponents > 3 ? "(" + xMax + "-gx)^(" + yMax + "-gy)^gz" : "1")
107 + ")" + colorScaleExpr;
108
109 // Store shader
110 {
111 std::ostringstream src;
112 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
113 << "\n"
114 << "layout(local_size_x = 1) in;\n"
115 << "layout(set = 0, binding = 1, " << formatQualifierStr << ") writeonly uniform " << msImageTypeStr << " u_msImage;\n";
116
117 if (caseDef.singleLayerBind)
118 src << "layout(set = 0, binding = 0) readonly uniform Constants {\n"
119 << " int u_layerNdx;\n"
120 << "};\n";
121
122 src << "\n"
123 << "void main (void)\n"
124 << "{\n"
125 << " int gx = int(gl_GlobalInvocationID.x);\n"
126 << " int gy = int(gl_GlobalInvocationID.y);\n"
127 << " int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
128 << "\n"
129 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n"
130 << " imageStore(u_msImage, " << texelCoordStr << ", sampleNdx, " << colorExpr << ");\n"
131 << " }\n"
132 << "}\n";
133
134 programCollection.glslSources.add("comp_store") << glu::ComputeSource(src.str());
135 }
136
137 // Load shader
138 {
139 const tcu::TextureFormat checksumFormat = mapVkFormat(CHECKSUM_IMAGE_FORMAT);
140 const std::string checksumImageTypeStr = getShaderImageType(checksumFormat, usedImageType);
141 const bool useExactCompare = isIntegerFormat(caseDef.format);
142
143 std::ostringstream src;
144 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
145 << "\n"
146 << "layout(local_size_x = 1) in;\n"
147 << "layout(set = 0, binding = 1, " << formatQualifierStr << ") readonly uniform " << msImageTypeStr << " u_msImage;\n"
148 << "layout(set = 0, binding = 2, " << getShaderImageFormatQualifier(checksumFormat) << ") writeonly uniform " << checksumImageTypeStr << " u_checksumImage;\n";
149
150 if (caseDef.singleLayerBind)
151 src << "layout(set = 0, binding = 0) readonly uniform Constants {\n"
152 << " int u_layerNdx;\n"
153 << "};\n";
154
155 src << "\n"
156 << "void main (void)\n"
157 << "{\n"
158 << " int gx = int(gl_GlobalInvocationID.x);\n"
159 << " int gy = int(gl_GlobalInvocationID.y);\n"
160 << " int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
161 << "\n"
162 << " int checksum = 0;\n"
163 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n"
164 << " " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n";
165
166 if (useExactCompare)
167 src << " if (color == " << colorExpr << ")\n"
168 << " ++checksum;\n";
169 else
170 src << " " << gvec4Expr << " diff = abs(abs(color) - abs(" << colorExpr << "));\n"
171 << " if (all(lessThan(diff, " << gvec4Expr << "(0.02))))\n"
172 << " ++checksum;\n";
173
174 src << " }\n"
175 << "\n"
176 << " imageStore(u_checksumImage, " << texelCoordStr << ", ivec4(checksum));\n"
177 << "}\n";
178
179 programCollection.glslSources.add("comp_load") << glu::ComputeSource(src.str());
180 }
181 }
182
checkSupport(Context & context,const CaseDef caseDef)183 void checkSupport (Context& context, const CaseDef caseDef)
184 {
185 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_MULTISAMPLE);
186
187 VkImageFormatProperties imageFormatProperties;
188 const VkResult imageFormatResult = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
189 context.getPhysicalDevice(), caseDef.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_STORAGE_BIT, (VkImageCreateFlags)0, &imageFormatProperties);
190
191 if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
192 TCU_THROW(NotSupportedError, "Format is not supported");
193
194 if ((imageFormatProperties.sampleCounts & caseDef.numSamples) != caseDef.numSamples)
195 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
196 }
197
198 //! Helper function to deal with per-layer resources.
insertImageViews(const DeviceInterface & vk,const VkDevice device,const CaseDef & caseDef,const VkFormat format,const VkImage image,std::vector<SharedVkImageView> * const pOutImageViews)199 void insertImageViews (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkFormat format, const VkImage image, std::vector<SharedVkImageView>* const pOutImageViews)
200 {
201 if (caseDef.singleLayerBind)
202 {
203 pOutImageViews->clear();
204 pOutImageViews->resize(caseDef.texture.numLayers());
205 for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx)
206 {
207 (*pOutImageViews)[layerNdx] = makeVkSharedPtr(makeImageView(
208 vk, device, image, mapImageViewType(getImageTypeForSingleLayer(caseDef.texture.type())), format,
209 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
210 }
211 }
212 else // bind all layers at once
213 {
214 pOutImageViews->clear();
215 pOutImageViews->resize(1);
216 (*pOutImageViews)[0] = makeVkSharedPtr(makeImageView(
217 vk, device, image, mapImageViewType(caseDef.texture.type()), format,
218 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers())));
219 }
220 }
221
222 //! Helper function to deal with per-layer resources.
insertDescriptorSets(const DeviceInterface & vk,const VkDevice device,const CaseDef & caseDef,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout descriptorSetLayout,std::vector<SharedVkDescriptorSet> * const pOutDescriptorSets)223 void insertDescriptorSets (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkDescriptorPool descriptorPool, const VkDescriptorSetLayout descriptorSetLayout, std::vector<SharedVkDescriptorSet>* const pOutDescriptorSets)
224 {
225 if (caseDef.singleLayerBind)
226 {
227 pOutDescriptorSets->clear();
228 pOutDescriptorSets->resize(caseDef.texture.numLayers());
229 for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx)
230 (*pOutDescriptorSets)[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout));
231 }
232 else // bind all layers at once
233 {
234 pOutDescriptorSets->clear();
235 pOutDescriptorSets->resize(1);
236 (*pOutDescriptorSets)[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout));
237 }
238 }
239
test(Context & context,const CaseDef caseDef)240 tcu::TestStatus test (Context& context, const CaseDef caseDef)
241 {
242 const InstanceInterface& vki = context.getInstanceInterface();
243 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
244 const DeviceInterface& vk = context.getDeviceInterface();
245 const VkDevice device = context.getDevice();
246 const VkQueue queue = context.getUniversalQueue();
247 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
248 Allocator& allocator = context.getDefaultAllocator();
249
250 // Images
251
252 const UniquePtr<Image> msImage(new Image(
253 vk, device, allocator, makeImageCreateInfo(caseDef.texture, caseDef.format, VK_IMAGE_USAGE_STORAGE_BIT, 0u), MemoryRequirement::Any));
254
255 const UniquePtr<Image> checksumImage(new Image(
256 vk, device, allocator,
257 makeImageCreateInfo(Texture(caseDef.texture, 1), CHECKSUM_IMAGE_FORMAT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
258 MemoryRequirement::Any));
259
260 // Buffer used to pass constants to the shader.
261
262 const int numLayers = caseDef.texture.numLayers();
263 const VkDeviceSize bufferChunkSize = getOptimalUniformBufferChunkSize(vki, physDevice, sizeof(deInt32));
264 const VkDeviceSize constantsBufferSizeBytes = numLayers * bufferChunkSize;
265 UniquePtr<Buffer> constantsBuffer (new Buffer(vk, device, allocator, makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
266 MemoryRequirement::HostVisible));
267
268 {
269 const Allocation& alloc = constantsBuffer->getAllocation();
270 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
271
272 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
273
274 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
275 {
276 deInt32* const valuePtr = reinterpret_cast<deInt32*>(basePtr + layerNdx * bufferChunkSize);
277 *valuePtr = layerNdx;
278 }
279
280 flushAlloc(vk, device, alloc);
281 }
282
283 const VkDeviceSize resultBufferSizeBytes = getImageSizeBytes(caseDef.texture.size(), CHECKSUM_IMAGE_FORMAT);
284 UniquePtr<Buffer> resultBuffer (new Buffer(vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
285 MemoryRequirement::HostVisible));
286
287 {
288 const Allocation& alloc = resultBuffer->getAllocation();
289 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(resultBufferSizeBytes));
290 flushAlloc(vk, device, alloc);
291 }
292
293 // Descriptors
294
295 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
296 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
297 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
298 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
299 .build(vk, device));
300
301 Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
302 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
303 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
304 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
305 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers));
306
307 std::vector<SharedVkDescriptorSet> allDescriptorSets;
308 std::vector<SharedVkImageView> allMultisampledImageViews;
309 std::vector<SharedVkImageView> allChecksumImageViews;
310
311 insertDescriptorSets(vk, device, caseDef, *descriptorPool, *descriptorSetLayout, &allDescriptorSets);
312 insertImageViews (vk, device, caseDef, caseDef.format, **msImage, &allMultisampledImageViews);
313 insertImageViews (vk, device, caseDef, CHECKSUM_IMAGE_FORMAT, **checksumImage, &allChecksumImageViews);
314
315 // Prepare commands
316
317 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
318 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
319 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
320
321 const tcu::IVec3 workSize = (caseDef.singleLayerBind ? caseDef.texture.layerSize() : caseDef.texture.size());
322 const int loopNumLayers = (caseDef.singleLayerBind ? numLayers : 1);
323 const VkImageSubresourceRange subresourceAllLayers = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers());
324
325 // Pass 1: Write MS image
326 {
327 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp_store"), 0));
328 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
329
330 beginCommandBuffer(vk, *cmdBuffer);
331 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
332
333 {
334 const VkImageMemoryBarrier barriers[] =
335 {
336 makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers),
337 makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **checksumImage, subresourceAllLayers),
338 };
339
340 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
341 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
342 }
343
344 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
345 {
346 const VkDescriptorSet descriptorSet = **allDescriptorSets[layerNdx];
347 const VkDescriptorImageInfo descriptorMultiImageInfo = makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
348 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize);
349
350 DescriptorSetUpdateBuilder()
351 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
352 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo)
353 .update(vk, device);
354
355 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
356 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
357 }
358
359 endCommandBuffer(vk, *cmdBuffer);
360 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
361 }
362
363 // Pass 2: "Resolve" MS image in compute shader
364 {
365 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp_load"), 0));
366 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
367
368 beginCommandBuffer(vk, *cmdBuffer);
369 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
370
371 {
372 const VkImageMemoryBarrier barriers[] =
373 {
374 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers),
375 };
376
377 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
378 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
379 }
380
381 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
382 {
383 const VkDescriptorSet descriptorSet = **allDescriptorSets[layerNdx];
384 const VkDescriptorImageInfo descriptorMultiImageInfo = makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
385 const VkDescriptorImageInfo descriptorChecksumImageInfo = makeDescriptorImageInfo(DE_NULL, **allChecksumImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
386 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize);
387
388 DescriptorSetUpdateBuilder()
389 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
390 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo)
391 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorChecksumImageInfo)
392 .update(vk, device);
393
394 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
395 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
396 }
397
398 endCommandBuffer(vk, *cmdBuffer);
399 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
400 }
401
402 // Retrieve result
403 {
404 beginCommandBuffer(vk, *cmdBuffer);
405
406 {
407 const VkImageMemoryBarrier barriers[] =
408 {
409 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **checksumImage, subresourceAllLayers),
410 };
411 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
412 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
413 }
414 {
415 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(caseDef.texture.layerSize()), caseDef.texture.numLayers());
416 vk.cmdCopyImageToBuffer(*cmdBuffer, **checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultBuffer, 1u, ©Region);
417 }
418 {
419 const VkBufferMemoryBarrier barriers[] =
420 {
421 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **resultBuffer, 0ull, resultBufferSizeBytes),
422 };
423 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
424 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, 0u, DE_NULL);
425 }
426
427 endCommandBuffer(vk, *cmdBuffer);
428 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
429 }
430
431 // Verify
432 {
433 const Allocation& alloc = resultBuffer->getAllocation();
434 invalidateAlloc(vk, device, alloc);
435
436 const IVec3 imageSize = caseDef.texture.size();
437 const deInt32* pDataPtr = static_cast<deInt32*>(alloc.getHostPtr());
438 const deInt32 expectedChecksum = caseDef.texture.numSamples();
439
440 for (int layer = 0; layer < imageSize.z(); ++layer)
441 for (int y = 0; y < imageSize.y(); ++y)
442 for (int x = 0; x < imageSize.x(); ++x)
443 {
444 if (*pDataPtr != expectedChecksum)
445 {
446 context.getTestContext().getLog()
447 << tcu::TestLog::Message << "Some sample colors were incorrect at (x, y, layer) = (" << x << ", " << y << ", " << layer << ")" << tcu::TestLog::EndMessage
448 << tcu::TestLog::Message << "Checksum value is " << *pDataPtr << " but expected " << expectedChecksum << tcu::TestLog::EndMessage;
449
450 return tcu::TestStatus::fail("Some sample colors were incorrect");
451 }
452 ++pDataPtr;
453 }
454
455 return tcu::TestStatus::pass("OK");
456 }
457 }
458
459 } // anonymous ns
460
createImageMultisampleLoadStoreTests(tcu::TestContext & testCtx)461 tcu::TestCaseGroup* createImageMultisampleLoadStoreTests (tcu::TestContext& testCtx)
462 {
463 const Texture textures[] =
464 {
465 // \note Shader code is tweaked to work with image size of 32, take a look if this needs to be modified.
466 Texture(IMAGE_TYPE_2D, tcu::IVec3(32, 32, 1), 1),
467 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(32, 32, 1), 4),
468 };
469
470 static const VkFormat formats[] =
471 {
472 VK_FORMAT_R32G32B32A32_SFLOAT,
473 VK_FORMAT_R16G16B16A16_SFLOAT,
474 VK_FORMAT_R32_SFLOAT,
475
476 VK_FORMAT_R32G32B32A32_UINT,
477 VK_FORMAT_R16G16B16A16_UINT,
478 VK_FORMAT_R8G8B8A8_UINT,
479 VK_FORMAT_R32_UINT,
480
481 VK_FORMAT_R32G32B32A32_SINT,
482 VK_FORMAT_R16G16B16A16_SINT,
483 VK_FORMAT_R8G8B8A8_SINT,
484 VK_FORMAT_R32_SINT,
485
486 VK_FORMAT_R8G8B8A8_UNORM,
487
488 VK_FORMAT_R8G8B8A8_SNORM,
489 };
490
491 static const VkSampleCountFlagBits samples[] =
492 {
493 VK_SAMPLE_COUNT_2_BIT,
494 VK_SAMPLE_COUNT_4_BIT,
495 VK_SAMPLE_COUNT_8_BIT,
496 VK_SAMPLE_COUNT_16_BIT,
497 VK_SAMPLE_COUNT_32_BIT,
498 VK_SAMPLE_COUNT_64_BIT,
499 };
500
501 MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_multisample", "Multisampled image store and load"));
502
503 for (int baseTextureNdx = 0; baseTextureNdx < DE_LENGTH_OF_ARRAY(textures); ++baseTextureNdx)
504 {
505 const Texture& baseTexture = textures[baseTextureNdx];
506 MovePtr<tcu::TestCaseGroup> imageViewGroup (new tcu::TestCaseGroup(testCtx, getImageTypeName(baseTexture.type()).c_str(), ""));
507 const int numLayerBindModes = (baseTexture.numLayers() == 1 ? 1 : 2);
508
509 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
510 for (int layerBindMode = 0; layerBindMode < numLayerBindModes; ++layerBindMode)
511 {
512 const bool singleLayerBind = (layerBindMode != 0);
513 const std::string formatGroupName = getFormatShortString(formats[formatNdx]) + (singleLayerBind ? "_single_layer" : "");
514 MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatGroupName.c_str(), ""));
515
516 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
517 {
518 const std::string samplesCaseName = "samples_" + de::toString(samples[samplesNdx]);
519
520 const CaseDef caseDef =
521 {
522 Texture(baseTexture, samples[samplesNdx]),
523 formats[formatNdx],
524 samples[samplesNdx],
525 singleLayerBind,
526 };
527
528 addFunctionCaseWithPrograms(formatGroup.get(), samplesCaseName, "", checkSupport, initPrograms, test, caseDef);
529 }
530 imageViewGroup->addChild(formatGroup.release());
531 }
532 testGroup->addChild(imageViewGroup.release());
533 }
534
535 return testGroup.release();
536 }
537
538 } // image
539 } // vkt
540