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