• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021-2022 Google LLC.
6  *
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 Tests that images using a block-compressed format are sampled
23  * correctly
24  *
25  * These tests create a storage image using a 128-bit or a 64-bit
26  * block-compressed image format and an ImageView using an uncompressed
27  * format. Each test case then fills the storage image with compressed
28  * color values in a compute shader and samples the storage image. If the
29  * sampled values are pure blue, the test passes.
30  *//*--------------------------------------------------------------------*/
31 
32 #include "deUniquePtr.hpp"
33 #include "deStringUtil.hpp"
34 
35 #include "tcuCompressedTexture.hpp"
36 #include "tcuVectorType.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuTexture.hpp"
40 
41 #include "vkDefs.hpp"
42 #include "vkRef.hpp"
43 #include "vkRefUtil.hpp"
44 #include "vkPrograms.hpp"
45 #include "vkMemUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vkImageUtil.hpp"
48 #include "vkCmdUtil.hpp"
49 #include "vkObjUtil.hpp"
50 #include "vkTypeUtil.hpp"
51 #include "vkImageWithMemory.hpp"
52 #include "vktImageTestsUtil.hpp"
53 #include "vkBarrierUtil.hpp"
54 
55 #include "vktTestCaseUtil.hpp"
56 #include "tcuTestLog.hpp"
57 
58 #include <string>
59 
60 using namespace vk;
61 
62 namespace vkt
63 {
64 namespace image
65 {
66 namespace
67 {
68 using tcu::IVec3;
69 using tcu::Vec2;
70 using tcu::Vec4;
71 using std::vector;
72 using de::MovePtr;
73 using tcu::TextureLevel;
74 using tcu::ConstPixelBufferAccess;
75 
76 const VkDeviceSize	BUFFERSIZE	= 100u * 1024;
77 const int			WIDTH		= 80;
78 const int			HEIGHT		= 80;
79 const int			FACES		= 6;
80 
getLayerCount(const bool cubemap)81 uint32_t getLayerCount (const bool cubemap)
82 {
83 	return (cubemap ? static_cast<uint32_t>(FACES) : 1u);
84 }
85 
makeImageCreateInfo(const IVec3 & size,const VkFormat & format,bool storageImage,bool cubemap)86 inline VkImageCreateInfo makeImageCreateInfo (const IVec3& size, const VkFormat& format, bool storageImage, bool cubemap)
87 {
88 	VkImageUsageFlags	usageFlags	= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
89 									  | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
90 	VkImageCreateFlags	createFlags	= cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : DE_NULL;
91 	const deUint32		layerCount	= getLayerCount(cubemap);
92 
93 	if (storageImage)
94 	{
95 		usageFlags	= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
96 					  | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
97 		createFlags	|= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
98 					  | VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
99 	}
100 
101 	const VkImageCreateInfo	imageParams	=
102 	{
103 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//  VkStructureType         sType;
104 		DE_NULL,								//  const void*             pNext;
105 		createFlags,							//  VkImageCreateFlags      flags;
106 		VK_IMAGE_TYPE_2D,						//  VkImageType             imageType;
107 		format,									//  VkFormat                format;
108 		makeExtent3D(size.x(), size.y(), 1u),	//  VkExtent3D              extent;
109 		1u,										//  deUint32                mipLevels;
110 		layerCount,								//  deUint32                arrayLayers;
111 		VK_SAMPLE_COUNT_1_BIT,					//  VkSampleCountFlagBits   samples;
112 		VK_IMAGE_TILING_OPTIMAL,				//  VkImageTiling           tiling;
113 		usageFlags,								//  VkImageUsageFlags       usage;
114 		VK_SHARING_MODE_EXCLUSIVE,				//  VkSharingMode           sharingMode;
115 		0u,										//  deUint32                queueFamilyIndexCount;
116 		DE_NULL,								//  const deUint32*         pQueueFamilyIndices;
117 		VK_IMAGE_LAYOUT_UNDEFINED,				//  VkImageLayout           initialLayout;
118 	};
119 
120 	return imageParams;
121 }
122 
makeVertexBuffer(const DeviceInterface & vk,const VkDevice device,const deUint32 queueFamilyIndex)123 Move<VkBuffer> makeVertexBuffer (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
124 {
125 	const VkBufferCreateInfo	vertexBufferParams =
126 	{
127 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType      sType;
128 		DE_NULL,								// const void*          pNext;
129 		0u,										// VkBufferCreateFlags  flags;
130 		BUFFERSIZE,								// VkDeviceSize         size;
131 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		// VkBufferUsageFlags   usage;
132 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode        sharingMode;
133 		1u,										// deUint32             queueFamilyIndexCount;
134 		&queueFamilyIndex						// const deUint32*      pQueueFamilyIndices;
135 	};
136 
137 	Move<VkBuffer>				vertexBuffer		= createBuffer(vk, device, &vertexBufferParams);
138 	return vertexBuffer;
139 }
140 
141 class SampleDrawnTextureTestInstance : public TestInstance
142 {
143 public:
144 	SampleDrawnTextureTestInstance (Context&			context,
145 									const VkFormat	imageFormat,
146 									const VkFormat	imageViewFormat,
147 									const bool		twoSamplers,
148 									const bool		cubemap);
149 
150 	tcu::TestStatus iterate			(void);
151 
152 private:
153 	const VkFormat	m_imageFormat;
154 	const VkFormat	m_imageViewFormat;
155 	const bool		m_twoSamplers;
156 	const bool		m_cubemap;
157 };
158 
SampleDrawnTextureTestInstance(Context & context,const VkFormat imageFormat,const VkFormat imageViewFormat,const bool twoSamplers,const bool cubemap)159 SampleDrawnTextureTestInstance::SampleDrawnTextureTestInstance (Context& context, const VkFormat imageFormat, const VkFormat imageViewFormat,
160 																const bool twoSamplers, const bool cubemap)
161 	: TestInstance											   (context)
162 	, m_imageFormat		(imageFormat)
163 	, m_imageViewFormat	(imageViewFormat)
164 	, m_twoSamplers		(twoSamplers)
165 	, m_cubemap			(cubemap)
166 {
167 }
168 
makeSampler(const DeviceInterface & vk,const VkDevice & device)169 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice& device)
170 {
171 	const VkSamplerCreateInfo samplerParams =
172 	{
173 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType          sType;
174 		DE_NULL,									// const void*              pNext;
175 		(VkSamplerCreateFlags)0,					// VkSamplerCreateFlags     flags;
176 		VK_FILTER_NEAREST,							// VkFilter                 magFilter;
177 		VK_FILTER_NEAREST,							// VkFilter                 minFilter;
178 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode      mipmapMode;
179 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode     addressModeU;
180 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode     addressModeV;
181 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode     addressModeW;
182 		0.0f,										// float                    mipLodBias;
183 		VK_FALSE,									// VkBool32                 anisotropyEnable;
184 		1.0f,										// float                    maxAnisotropy;
185 		VK_FALSE,									// VkBool32                 compareEnable;
186 		VK_COMPARE_OP_ALWAYS,						// VkCompareOp              compareOp;
187 		0.0f,										// float                    minLod;
188 		0.0f,										// float                    maxLod;
189 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor            borderColor;
190 		VK_FALSE,									// VkBool32                 unnormalizedCoordinates;
191 	};
192 
193 	return createSampler(vk, device, &samplerParams);
194 }
195 
196 struct Vertex
197 {
Vertexvkt::image::__anon78095fa40111::Vertex198 	Vertex(Vec4 position_, Vec2 uv_) : position(position_), uv(uv_) {}
199 	Vec4 position;
200 	Vec2 uv;
201 
202 	static VkVertexInputBindingDescription				getBindingDescription		(void);
203 	static vector<VkVertexInputAttributeDescription>	getAttributeDescriptions	(void);
204 };
205 
getBindingDescription(void)206 VkVertexInputBindingDescription Vertex::getBindingDescription (void)
207 {
208 	static const VkVertexInputBindingDescription desc =
209 	{
210 		0u,										// deUint32             binding;
211 		static_cast<deUint32>(sizeof(Vertex)),	// deUint32             stride;
212 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate    inputRate;
213 	};
214 
215 	return desc;
216 }
217 
getAttributeDescriptions(void)218 vector<VkVertexInputAttributeDescription> Vertex::getAttributeDescriptions (void)
219 {
220 	static const vector<VkVertexInputAttributeDescription> desc =
221 	{
222 		{
223 			0u,													// deUint32    location;
224 			0u,													// deUint32    binding;
225 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,					// VkFormat    format;
226 			static_cast<deUint32>(offsetof(Vertex, position)),	// deUint32    offset;
227 		},
228 		{
229 			1u,													// deUint32    location;
230 			0u,													// deUint32    binding;
231 			vk::VK_FORMAT_R32G32_SFLOAT,						// VkFormat    format;
232 			static_cast<deUint32>(offsetof(Vertex, uv)),		// deUint32    offset;
233 		},
234 	};
235 
236 	return desc;
237 }
238 
239 // Generates the vertices of a full quad and texture coordinates of each vertex.
generateVertices(void)240 vector<Vertex> generateVertices (void)
241 {
242 	vector<Vertex> vertices;
243 	vertices.push_back(Vertex(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), Vec2(0.0f, 0.0f)));
244 	vertices.push_back(Vertex(Vec4( 1.0f, -1.0f, 0.0f, 1.0f), Vec2(1.0f, 0.0f)));
245 	vertices.push_back(Vertex(Vec4(-1.0f,  1.0f, 0.0f, 1.0f), Vec2(0.0f, 1.0f)));
246 	vertices.push_back(Vertex(Vec4( 1.0f, -1.0f, 0.0f, 1.0f), Vec2(1.0f, 0.0f)));
247 	vertices.push_back(Vertex(Vec4( 1.0f,  1.0f, 0.0f, 1.0f), Vec2(1.0f, 1.0f)));
248 	vertices.push_back(Vertex(Vec4(-1.0f,  1.0f, 0.0f, 1.0f), Vec2(0.0f, 1.0f)));
249 
250 	return vertices;
251 }
252 
253 // Generates a reference image filled with pure blue.
makeReferenceImage(const VkFormat format,int width,int height)254 TextureLevel makeReferenceImage (const VkFormat format, int width, int height)
255 {
256 	TextureLevel referenceImage(mapVkFormat(format), width, height, 1);
257 	for (int y = 0; y < height; y++)
258 		for (int x = 0; x < width; x++)
259 			referenceImage.getAccess().setPixel(tcu::IVec4(0, 0, 255, 255), x, y, 0);
260 
261 	return referenceImage;
262 }
263 
iterate(void)264 tcu::TestStatus SampleDrawnTextureTestInstance::iterate (void)
265 {
266 	DE_ASSERT(m_imageFormat == VK_FORMAT_BC1_RGB_UNORM_BLOCK || m_imageFormat == VK_FORMAT_BC3_UNORM_BLOCK);
267 
268 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
269 	const VkDevice					device					= m_context.getDevice();
270 	Allocator&						allocator				= m_context.getDefaultAllocator();
271 	const VkQueue					queue					= m_context.getUniversalQueue();
272 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
273 
274 	const IVec3						imageSize				= {static_cast<int>(WIDTH), HEIGHT, 1};
275 	const VkExtent2D				renderSize				= {deUint32(WIDTH), deUint32(HEIGHT)};
276 	const VkRect2D					renderArea				= makeRect2D(makeExtent3D(WIDTH, HEIGHT, 1u));
277 	const vector<VkRect2D>			scissors				(1u, renderArea);
278 	const vector<VkViewport>		viewports				(1u, makeViewport(makeExtent3D(WIDTH, HEIGHT, 1u)));
279 
280 	const Move<VkCommandPool>		cmdPool					= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
281 	const Move<VkCommandBuffer>		cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
282 
283 	const Unique<VkDescriptorPool>	descriptorPool			(DescriptorPoolBuilder()
284 															 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 6)
285 															 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 12)
286 															 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 21u));
287 
288 	const VkFormat					renderedImageFormat		= VK_FORMAT_R8G8B8A8_UNORM;
289 	tcu::CompressedTexFormat		compressedFormat		(mapVkCompressedFormat(m_imageFormat));
290 	IVec3							blockSize				= tcu::getBlockPixelSize(compressedFormat);
291 
292 	DE_ASSERT(blockSize.z() == 1);
293 
294 	IVec3							storageImageViewSize = imageSize / blockSize;
295 
296 	// Create a storage image. The first pipeline fills it and the second pipeline
297 	// uses it as a sampling source.
298 	const VkImageCreateInfo			imageCreateInfo			= makeImageCreateInfo(imageSize, m_imageFormat, true, m_cubemap);
299 	const auto						layerCount				= getLayerCount(m_cubemap);
300 	const VkImageSubresourceRange	imageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, layerCount);
301 	const ImageWithMemory			storageImage			(vk, device, m_context.getDefaultAllocator(), imageCreateInfo, MemoryRequirement::Any);
302 
303 	// Create image views and descriptor sets for the first pipeline
304 	Move<VkDescriptorSetLayout>		descriptorSetLayout		= DescriptorSetLayoutBuilder()
305 			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
306 			.build(vk, device);
307 
308 	Move<VkImageView>				storageImageImageView;
309 	VkDescriptorImageInfo			storageImageDscrInfo;
310 	Move<VkDescriptorSet>			storageImageDescriptorSet;
311 
312 	// Cubemap tests use separate image views for each side of a cubemap.
313 	vector<VkImageSubresourceRange>	cubeSubresourceRanges;
314 	vector<Move<VkImageView>>		cubeStorageImageViews;
315 	vector<VkDescriptorImageInfo>	cubeStorageDscrImageInfos;
316 	vector<Move<VkDescriptorSet>>	cubeStorageDscrSets;
317 
318 	if (m_cubemap)
319 	{
320 		DescriptorSetUpdateBuilder updateBuilder;
321 		for (int i = 0; i < FACES; i++)
322 		{
323 			cubeSubresourceRanges.emplace_back(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, i, 1));
324 			cubeStorageImageViews.emplace_back(makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, cubeSubresourceRanges[i]));
325 			cubeStorageDscrImageInfos.emplace_back(makeDescriptorImageInfo(DE_NULL, *cubeStorageImageViews[i], VK_IMAGE_LAYOUT_GENERAL));
326 			cubeStorageDscrSets.emplace_back(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
327 			updateBuilder.writeSingle(*cubeStorageDscrSets[i], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &cubeStorageDscrImageInfos[i]);
328 		}
329 		updateBuilder.update(vk, device);
330 	}
331 	else
332 	{
333 		storageImageImageView		= makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, imageSubresourceRange);
334 		storageImageDscrInfo		= makeDescriptorImageInfo(DE_NULL, *storageImageImageView, VK_IMAGE_LAYOUT_GENERAL);
335 		storageImageDescriptorSet	= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
336 
337 		DescriptorSetUpdateBuilder()
338 			.writeSingle(*storageImageDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImageDscrInfo)
339 			.update(vk, device);
340 	}
341 
342 	// Create a compute pipeline.
343 	Move<VkShaderModule>			computeShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u);
344 	const VkPushConstantRange		pushConstantRange		=
345 	{
346 		VK_SHADER_STAGE_COMPUTE_BIT,	// VkShaderStageFlags    stageFlags;
347 		0u,								// uint32_t              offset;
348 		(deUint32)sizeof(deUint32),		// uint32_t              size;
349 	};
350 
351 	const Move<VkPipelineLayout>	computePipelineLayout	= makePipelineLayout(vk, device, 1, &(*descriptorSetLayout), 1, &pushConstantRange);
352 	Move<VkPipeline>				computePipeline			= makeComputePipeline(vk, device, *computePipelineLayout, *computeShader);
353 
354 
355 	// Create a graphics pipeline and all the necessary components for sampling the storage image
356 
357 	// The first sampler uses an uncompressed format.
358 	const Unique<VkSampler>			sampler					(makeSampler(vk, device));
359 
360 	// The second sampler uses the same format as the image.
361 	const Unique<VkSampler>			sampler2				(makeSampler(vk, device));
362 
363 	// Image views implicitly derive the usage flags from the image. Drop the storage image flag since it's incompatible
364 	// with the compressed format and unnecessary in sampling.
365 	VkImageUsageFlags				usageFlags				= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
366 	VkImageViewUsageCreateInfo		imageViewUsageInfo		=
367 	{
368 		VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,		//VkStructureType		sType;
369 		DE_NULL,											//const void*			pNext;
370 		usageFlags,											//VkImageUsageFlags		usage;
371 	};
372 
373 	Move<VkImageView>				sampledImageView;
374 	Move<VkImageView>				sampledImageView2;
375 	VkDescriptorImageInfo			samplerDscrImageInfo;
376 	VkDescriptorImageInfo			samplerDscrImageInfo2;
377 	Move<VkDescriptorSet>			graphicsDescriptorSet;
378 
379 	// Cubemap tests use separate image views for each side of a cubemap.
380 	vector<Move<VkImageView>>		cubeSamplerImageViews;
381 	vector<Move<VkImageView>>		cubeSampler2ImageViews;
382 	vector<VkDescriptorImageInfo>	cubeSamplerDscrImageInfos;
383 	vector<VkDescriptorImageInfo>	cubeSampler2DscrImageInfos;
384 	vector<Move<VkDescriptorSet>>	cubeSamplerDescriptorSets;
385 
386 	const auto						graphicsDscrSetLayout	(DescriptorSetLayoutBuilder()
387 											.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &sampler2.get())
388 											.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &sampler.get())
389 											.build(vk, device));
390 
391 	if (m_cubemap)
392 	{
393 		DescriptorSetUpdateBuilder updateBuilder;
394 		for (int i = 0; i < FACES; i++)
395 		{
396 			cubeSamplerImageViews.emplace_back(makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageFormat, cubeSubresourceRanges[i], &imageViewUsageInfo));
397 			cubeSamplerDscrImageInfos.emplace_back(makeDescriptorImageInfo(sampler2.get(), *cubeSamplerImageViews[i], VK_IMAGE_LAYOUT_GENERAL));
398 			cubeSamplerDescriptorSets.emplace_back(makeDescriptorSet(vk, device, *descriptorPool, *graphicsDscrSetLayout));
399 			updateBuilder.writeSingle(*cubeSamplerDescriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &cubeSamplerDscrImageInfos[i]);
400 		}
401 
402 		if (m_twoSamplers)
403 		{
404 			for (int i = 0; i < FACES; i++)
405 			{
406 				cubeSampler2ImageViews.emplace_back(makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, cubeSubresourceRanges[i]));
407 				cubeSampler2DscrImageInfos.emplace_back(makeDescriptorImageInfo(sampler.get(), *cubeSampler2ImageViews[i], VK_IMAGE_LAYOUT_GENERAL));
408 				updateBuilder.writeSingle(*cubeSamplerDescriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &cubeSampler2DscrImageInfos[i]);
409 			}
410 		}
411 		updateBuilder.update(vk, device);
412 	}
413 	else
414 	{
415 		const VkImageSubresourceRange	subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, 1);
416 		DescriptorSetUpdateBuilder		updateBuilder;
417 
418 		sampledImageView2 = makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageFormat, subresourceRange, &imageViewUsageInfo);
419 		samplerDscrImageInfo2 = makeDescriptorImageInfo(sampler2.get(), *sampledImageView2, VK_IMAGE_LAYOUT_GENERAL);
420 		graphicsDescriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *graphicsDscrSetLayout);
421 
422 		if (m_twoSamplers)
423 		{
424 			sampledImageView = makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, subresourceRange);
425 			samplerDscrImageInfo = makeDescriptorImageInfo(sampler.get(), *sampledImageView, VK_IMAGE_LAYOUT_GENERAL);
426 		}
427 
428 		updateBuilder.writeSingle(*graphicsDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &samplerDscrImageInfo2);
429 		if (m_twoSamplers)
430 			updateBuilder.writeSingle(*graphicsDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &samplerDscrImageInfo);
431 
432 		updateBuilder.update(vk, device);
433 	}
434 
435 	// Sampled values will be rendered on this image.
436 	const VkImageSubresourceRange	targetSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, 1);
437 	const VkImageCreateInfo			targetImageCreateInfo	= makeImageCreateInfo(imageSize, renderedImageFormat, false, false);
438 
439 	const ImageWithMemory			targetImage				(vk, device, m_context.getDefaultAllocator(), targetImageCreateInfo, MemoryRequirement::Any);
440 	Move<VkImageView>				targetImageView			= makeImageView(vk, device, *targetImage, VK_IMAGE_VIEW_TYPE_2D, renderedImageFormat, targetSubresourceRange);
441 
442 	// Clear the render target image as black and do a layout transition.
443 	const auto clearColor = makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 0.0f)).color;
444 	clearColorImage(vk, device, m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), targetImage.get(),
445 					clearColor, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
446 					(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
447 					VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
448 
449 	const VkPushConstantRange		pushConstantRange2		=
450 	{
451 		VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags    stageFlags;
452 		0u,								// uint32_t              offset;
453 		(deUint32)sizeof(deUint32),		// uint32_t              size;
454 	};
455 
456 	const Move<VkPipelineLayout>	graphicsPipelineLayout	= makePipelineLayout(vk, device, 1, &(*graphicsDscrSetLayout), 1, &pushConstantRange2);
457 
458 	// Vertices for a full quad and texture coordinates for each vertex.
459 	const vector<Vertex>			vertices				= generateVertices();
460 	const uint32_t					vertexCount				= static_cast<uint32_t>(vertices.size());
461 	Move<VkBuffer>					vertexBuffer			= makeVertexBuffer(vk, device, queueFamilyIndex);
462 	de::MovePtr<Allocation>			vertexBufferAlloc		= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
463 	const VkDeviceSize				vertexBufferOffset		= 0ull;
464 	deMemcpy(vertexBufferAlloc->getHostPtr(), de::dataOrNull(vertices), de::dataSize(vertices));
465 	flushAlloc(vk, device, *vertexBufferAlloc);
466 
467 	const auto						vtxBindingDescription	= Vertex::getBindingDescription();
468 	const auto						vtxAttrDescriptions		= Vertex::getAttributeDescriptions();
469 
470 	const VkPipelineVertexInputStateCreateInfo vtxInputInfo	=
471 	{
472 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType
473 		nullptr,													// const void*                                 pNext
474 		0u,															// VkPipelineVertexInputStateCreateFlags       flags
475 		1u,															// deUint32                                    vertexBindingDescriptionCount
476 		&vtxBindingDescription,										// const VkVertexInputBindingDescription*      pVertexBindingDescriptions
477 		static_cast<deUint32>(vtxAttrDescriptions.size()),			// deUint32                                    vertexAttributeDescriptionCount
478 		vtxAttrDescriptions.data(),									// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
479 	};
480 
481 	Move<VkShaderModule>			vertexShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
482 	Move<VkShaderModule>			fragmentShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
483 
484 	// Create a render pass, a framebuffer, and the second pipeline.
485 	Move<VkRenderPass>				renderPass				= makeRenderPass(vk, device, renderedImageFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD,
486 																			 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
487 	Move<VkFramebuffer>				framebuffer				= makeFramebuffer(vk, device, *renderPass, targetImageView.get(), renderSize.width, renderSize.height);
488 	const Move<VkPipeline>			graphicsPipeline		= makeGraphicsPipeline(vk, device, graphicsPipelineLayout.get(), vertexShader.get(), DE_NULL,
489 																				   DE_NULL, DE_NULL, fragmentShader.get(), renderPass.get(), viewports, scissors,
490 																				   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &vtxInputInfo);
491 
492 	// Create a result buffer.
493 	const VkBufferCreateInfo		resultBufferCreateInfo	= makeBufferCreateInfo(BUFFERSIZE, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
494 	Move<VkBuffer>					resultBuffer			= createBuffer(vk, device, &resultBufferCreateInfo);
495 	MovePtr<Allocation>				resultBufferMemory		= allocator.allocate(getBufferMemoryRequirements(vk, device, *resultBuffer), MemoryRequirement::HostVisible);
496 	TextureLevel					resultImage				(mapVkFormat(renderedImageFormat), renderSize.width, renderSize.height, 1);
497 	VK_CHECK(vk.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
498 
499 	// Generate a reference image.
500 	TextureLevel					expectedImage			= makeReferenceImage(renderedImageFormat, WIDTH, HEIGHT);
501 
502 	beginCommandBuffer(vk, *cmdBuffer);
503 
504 	// Do a layout transition for the storage image.
505 	const auto						barrier1				= makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT,
506 																					 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
507 																					 storageImage.get(), imageSubresourceRange);
508 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier1);
509 
510 	// Bind the vertices and the descriptors used in the graphics pipeline.
511 	vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
512 
513 	// Fill the storage image and sample it twice.
514 	for (int pass = 0; pass < 2; pass++)
515 	{
516 		// If both samplers are enabled, it's not necessary to run the compute shader twice since it already writes
517 		// the expected values on the first pass. The first sampler uses an uncompressed image format so the result
518 		// image will contain garbage if the second sampler doesn't work properly.
519 		if (!m_twoSamplers || pass == 0)
520 		{
521 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
522 			vk.cmdPushConstants(*cmdBuffer, *computePipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(deInt32), &pass);
523 
524 			// If cubemaps are enabled, loop over six times and bind the next face of the cubemap image on each iteration.
525 			if (m_cubemap)
526 			{
527 				for (int face = 0; face < FACES; face++)
528 				{
529 					vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &(cubeStorageDscrSets[face].get()), 0u, DE_NULL);
530 					vk.cmdDispatch(*cmdBuffer, storageImageViewSize.x(), storageImageViewSize.y(), 1u);
531 				}
532 			}
533 			else
534 			{
535 				vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &storageImageDescriptorSet.get(), 0u, DE_NULL);
536 				vk.cmdDispatch(*cmdBuffer, storageImageViewSize.x(), storageImageViewSize.y(), 1u);
537 			}
538 
539 			const auto barrier2 = makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
540 														 VK_IMAGE_LAYOUT_GENERAL, storageImage.get(), imageSubresourceRange);
541 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier2);
542 		}
543 
544 		vk.cmdPushConstants(*cmdBuffer, *graphicsPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(deInt32), &pass);
545 
546 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
547 
548 		// If cubemaps are enabled, loop over six times and bind the next face of the cubemap image on each iteration.
549 		if (m_cubemap)
550 		{
551 			for (int face = 0; face < FACES; face++)
552 			{
553 				vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0u, 1u, &(cubeSamplerDescriptorSets[face].get()), 0u, DE_NULL);
554 
555 				beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, imageSize.x(), imageSize.y()),0u, DE_NULL);
556 				vk.cmdDraw(*cmdBuffer, vertexCount, 1u, 0u, 0u);
557 				endRenderPass(vk, *cmdBuffer);
558 
559 				if (face < FACES-1)
560 				{
561 					const auto barrier4 = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT),
562 																 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
563 																 targetImage.get(), targetSubresourceRange);
564 					vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
565 										  0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier4);
566 				}
567 			}
568 		}
569 		else
570 		{
571 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0u, 1u, &(graphicsDescriptorSet.get()), 0u, DE_NULL);
572 
573 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, imageSize.x(), imageSize.y()),0u, DE_NULL);
574 			vk.cmdDraw(*cmdBuffer, vertexCount, 1u, 0u, 0u);
575 			endRenderPass(vk, *cmdBuffer);
576 		}
577 
578 		if (pass == 0)
579 		{
580 			const auto barrier3 = makeImageMemoryBarrier(VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL,
581 														 VK_IMAGE_LAYOUT_GENERAL, storageImage.get(), imageSubresourceRange);
582 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier3);
583 
584 			const auto barrier4 = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT),
585 														 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
586 														 targetImage.get(), targetSubresourceRange);
587 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier4);
588 		}
589 	}
590 
591 	// Copy the sampled values from the target image into the result image.
592 	copyImageToBuffer(vk, *cmdBuffer, *targetImage, *resultBuffer, tcu::IVec2(WIDTH, HEIGHT), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
593 
594 	endCommandBuffer(vk, *cmdBuffer);
595 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
596 
597 	invalidateAlloc(vk, device, *resultBufferMemory);
598 
599 	clear(resultImage.getAccess(), tcu::IVec4(0));
600 	copy(resultImage.getAccess(), ConstPixelBufferAccess(resultImage.getFormat(), resultImage.getSize(), resultBufferMemory->getHostPtr()));
601 
602 	bool							result					= true;
603 
604 	if (m_cubemap)
605 	{
606 		// The first pass draws pure red on the faces and the second pass redraws them with pure blue.
607 		// Sampling anywhere should produce colors with a 0.0 red component and > 0.0 blue and alpha components.
608 		for (deUint32 y = 0; y < renderSize.height; y++)
609 		{
610 			for (deUint32 x = 0; x < renderSize.width; x++)
611 			{
612 				const deUint8* ptr = static_cast<const deUint8 *>(resultImage.getAccess().getPixelPtr(x, y, 0));
613 				const tcu::IVec4 val = tcu::IVec4(ptr[0], ptr[1], ptr[2], ptr[3]);
614 				if (!(val[0] == 0 && val[2] > 0 && val[3] > 0))
615 					result = false;
616 			}
617 		}
618 
619 		// Log attachment contents.
620 		m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Attachment ", "")
621 											<< tcu::TestLog::Image("Rendered image", "Rendered image", resultImage.getAccess())
622 											<< tcu::TestLog::EndImageSet;
623 	}
624 	else
625 	{
626 		// Each test case should render pure blue as the result.
627 		result = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Image Comparison", "",
628 											expectedImage.getAccess(), resultImage.getAccess(),
629 											tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
630 	}
631 
632 	if (result)
633 		return tcu::TestStatus::pass("pass");
634 	else
635 		return tcu::TestStatus::fail("fail");
636 }
637 
638 class SampleDrawnTextureTest : public TestCase
639 {
640 public:
641 						SampleDrawnTextureTest	(tcu::TestContext&	testCtx,
642 												 const std::string&	name,
643 												 const VkFormat		imageFormat,
644 												 const VkFormat		imageViewFormat,
645 												 const bool			twoSamplers,
646 												 const bool			cubemap);
647 
648 	void				initPrograms			(SourceCollections& programCollection) const;
649 	TestInstance*		createInstance			(Context&			context) const;
650 	virtual void		checkSupport			(Context& context) const;
651 
652 private:
653 	const VkFormat		m_imageFormat;
654 	const VkFormat		m_imageViewFormat;
655 	const bool			m_twoSamplers;
656 	const bool			m_cubemap;
657 };
658 
SampleDrawnTextureTest(tcu::TestContext & testCtx,const std::string & name,const VkFormat imageFormat,const VkFormat imageViewFormat,const bool twoSamplers,const bool cubemap)659 SampleDrawnTextureTest::SampleDrawnTextureTest (tcu::TestContext&	testCtx,
660 												const std::string&	name,
661 												const VkFormat		imageFormat,
662 												const VkFormat		imageViewFormat,
663 												const bool			twoSamplers,
664 												const bool			cubemap)
665 	: TestCase	(testCtx, name)
666 	, m_imageFormat	(imageFormat)
667 	, m_imageViewFormat	(imageViewFormat)
668 	, m_twoSamplers (twoSamplers)
669 	, m_cubemap (cubemap)
670 {
671 }
672 
checkSupport(Context & context) const673 void SampleDrawnTextureTest::checkSupport(Context& context) const
674 {
675 	const auto&				vki					= context.getInstanceInterface();
676 	const auto				usageFlags			= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
677 												  | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
678 	auto					creationFlags		= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
679 												  | VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
680 	if (m_cubemap)
681 		creationFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
682 
683 	// Check that:
684 	// - VkImageViewUsageCreateInfo can be used to override implicit usage flags derived from the image.
685 	// - A compressed image can be created with usage flags that are not supported for the format but are
686 	//   supported by an image view that is using uncompressed format where each texel corresponds to
687 	//   a compressed texel block of the image.
688 
689 	if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance2"))
690 		TCU_THROW(NotSupportedError, "Device does not support extended image usage flags nor overriding implicit usage flags");
691 
692 	VkImageFormatProperties	imageFormatProperties;
693 
694 	if (vki.getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), m_imageFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
695 												   usageFlags, creationFlags, &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
696 	{
697 		std::string	algorithmName	= (m_imageFormat == vk::VK_FORMAT_BC3_UNORM_BLOCK) ?  "BC3" : "BC1";
698 		std::string	errorMsg		= algorithmName;
699 
700 		errorMsg += m_cubemap ? " compressed cubemap images" : " compressed images";
701 		errorMsg += " created with VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT";
702 		errorMsg += " and VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT flags not supported.";
703 		TCU_THROW(NotSupportedError, errorMsg);
704 	}
705 }
706 
initPrograms(SourceCollections & programCollection) const707 void SampleDrawnTextureTest::initPrograms (SourceCollections& programCollection) const
708 {
709 	// Pure red, green, and blue compressed with the BC1 and BC3 algorithms.
710 	std::string					bc1_red				= "uvec4(4160813056u, 0u, 4160813056u, 0u);\n";
711 	std::string					bc1_blue			= "uvec4(2031647, 0u, 2031647, 0u);\n";
712 	std::string					bc3_red				= "uvec4(4294967295u, 4294967295u, 4160813056u, 0u);\n";
713 	std::string					bc3_blue			= "uvec4(4294967295u, 4294967295u, 2031647, 0u);\n";
714 
715 	std::string					red					= (m_imageFormat == VK_FORMAT_BC1_RGB_UNORM_BLOCK) ? bc1_red : bc3_red;
716 	std::string					blue				= (m_imageFormat == VK_FORMAT_BC1_RGB_UNORM_BLOCK) ? bc1_blue : bc3_blue;
717 
718 	std::ostringstream			computeSrc;
719 
720 	// Generate the compute shader.
721 	computeSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
722 	computeSrc << "layout(set = 0, binding = 0, rgba32ui) uniform highp uimage2D img;\n";
723 	computeSrc << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
724 
725 	if (!m_twoSamplers)
726 	{
727 		computeSrc
728 			<< "layout(push_constant) uniform constants {\n"
729 			<< "    int pass;\n"
730 			<< "} pc;\n";
731 	}
732 
733 	computeSrc << "void main() {\n";
734 
735 	if (m_twoSamplers)
736 		computeSrc << "    uvec4 color = " << blue;
737 	else
738 	{
739 		computeSrc << "    uvec4 color = " << red;
740 		computeSrc << "    if (pc.pass == 1)\n";
741 		computeSrc << "        color = " << blue;
742 	}
743 
744 	computeSrc
745 	<< "    imageStore(img, ivec2(gl_GlobalInvocationID.xy), color);\n"
746 	<< "}\n";
747 
748 	// Generate the vertex shader.
749 	std::ostringstream			vertexSrc;
750 	vertexSrc
751 		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
752 		<< "layout(location = 0) in highp vec4 a_position;\n"
753 		<< "layout(location = 1) in vec2 inTexCoord;\n"
754 		<< "layout(location = 1) out vec2 fragTexCoord;\n"
755 		<< "void main (void) {\n"
756 		<< "    gl_Position = a_position;\n"
757 		<< "    fragTexCoord = inTexCoord;\n"
758 		<< "}\n";
759 
760 	// Generate the fragment shader.
761 	std::ostringstream			fragmentSrc;
762 	fragmentSrc
763 		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
764 		<< "layout(location = 0) out vec4 outColor;\n"
765 		<< "layout(location = 1) in vec2 fragTexCoord;\n";
766 
767 	fragmentSrc << "layout(binding = 0) uniform sampler2D compTexSampler;\n";
768 
769 	if (m_twoSamplers)
770 	{
771 		fragmentSrc
772 			<< "layout(binding = 1) uniform usampler2D texSampler;\n"
773 			<< "layout(push_constant) uniform constants {\n"
774 			<< "    int pass;\n"
775 			<< "} pc;\n"
776 			<< "void main() {\n"
777 			<< "    if (pc.pass == 1)\n"
778 			<< "        outColor = texture(compTexSampler, fragTexCoord);\n"
779 			<< "    else"
780 			<< "        outColor = texture(texSampler, fragTexCoord);\n";
781 	}
782 	else
783 	{
784 		fragmentSrc
785 			<< "void main() {\n"
786 			<< "    outColor = texture(compTexSampler, fragTexCoord);\n";
787 	}
788 
789 	fragmentSrc << "}\n";
790 
791 	programCollection.glslSources.add("comp") << glu::ComputeSource(computeSrc.str());
792 	programCollection.glslSources.add("vert") << glu::VertexSource(vertexSrc.str());
793 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSrc.str());
794 }
795 
createInstance(Context & context) const796 TestInstance* SampleDrawnTextureTest::createInstance (Context& context) const
797 {
798 	return new SampleDrawnTextureTestInstance(context, m_imageFormat, m_imageViewFormat, m_twoSamplers, m_cubemap);
799 }
800 
801 } // anonymous ns
802 
createImageSampleDrawnTextureTests(tcu::TestContext & testCtx)803 tcu::TestCaseGroup* createImageSampleDrawnTextureTests	(tcu::TestContext& testCtx)
804 {
805 	/* If both samplers are enabled, the test works as follows:
806 	 *
807 	 * Pass 0:
808 	 * - Compute shader fills a storage image with values that are pure blue compressed with
809 	 *   either the BC1 or BC3 algorithm.
810 	 * - Fragment shader samples the image and draws the values on a target image.
811 	 * - As the sampled values are accessed through an image view using an uncompressed
812 	 *   format, they remain compressed and the drawn image ends up being garbage.
813 	 * Pass 1:
814 	 * - Fragment shader samples the image. On this pass, the image view uses
815 	 *   a block-compressed format and correctly interprets the sampled values.
816 	 * - As the values are uncompressed now, the target image is filled
817 	 *   with pure blue and the test passes.
818 
819 	 * Only one sampler enabled:
820 	 * Pass 0:
821 	 * - Compute shader fills a storage image with values that are pure red compressed
822 	 *   with either the BC1 or BC3 algorithm.
823 	 * - Fragment shader samples the image through an image view which interprets the values
824 	 *   correctly. The values are drawn on a target image. The test doesn't pass yet
825 	 *   since the image is red.
826 	 * Pass 1:
827 	 * - Compute shader fills the storage image with values that are pure blue compressed
828 	 *   with the same algorithm as on the previous pass.
829 	 * - Fragment shader samples the image through an image view which interprets the values
830 	 *   correctly. The values are drawn on the target image and the test passes.
831 	 *
832 	 * If cubemaps are enabled:
833 	 * Pass 0:
834 	 * - If both samplers are enabled, draw compressed pure blue on the faces. Otherwise pure red.
835 	 * - Sample the image through an image view with or without compressed format as in the cases
836 	 *   without cubemaps.
837 	 * Pass 1:
838 	 * - If only one sampler is enabled, redraw the faces with pure blue
839 	 * - Sample the image. Sampling should produce colors with a 0.0 red component and with > 0.0
840 	 *   blue and alpha components.
841 	 */
842 
843 	const bool twoSamplers	= true;
844 	const bool cubemap		= true;
845 
846 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "sample_texture"));
847 
848 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format_cubemap", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, !twoSamplers, cubemap));
849 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format_cubemap", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, !twoSamplers, cubemap));
850 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format_two_samplers_cubemap", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, twoSamplers, cubemap));
851 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format_two_samplers_cubemap", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, twoSamplers, cubemap));
852 
853 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, !twoSamplers, false));
854 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format_two_samplers", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, twoSamplers, false));
855 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, !twoSamplers, false));
856 	testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format_two_samplers", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, twoSamplers, false));
857 
858 	return testGroup.release();
859 }
860 
861 } // image
862 } // vkt
863