• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * ------------------------
3  *
4  * Copyright (c) 2021 Google LLC.
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Sample cube faces that has been rendered to tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deUniquePtr.hpp"
25 #include "deStringUtil.hpp"
26 
27 #include "tcuVectorType.hpp"
28 #include "tcuTextureUtil.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuTexture.hpp"
31 
32 #include "vkDefs.hpp"
33 #include "vkRef.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 #include "vkImageWithMemory.hpp"
43 #include "vkBarrierUtil.hpp"
44 
45 #include "vktTestCaseUtil.hpp"
46 #include "tcuTestLog.hpp"
47 
48 #include <string>
49 
50 using namespace vk;
51 
52 namespace vkt
53 {
54 namespace image
55 {
56 namespace
57 {
58 
59 using tcu::TestLog;
60 using tcu::IVec2;
61 using tcu::IVec3;
62 using tcu::IVec4;
63 using tcu::Vec2;
64 using tcu::Vec4;
65 using std::vector;
66 using de::MovePtr;
67 using tcu::TextureLevel;
68 using tcu::PixelBufferAccess;
69 using tcu::ConstPixelBufferAccess;
70 
makeImageCreateInfo(const IVec3 & size,const VkFormat & format,bool cubemap)71 inline VkImageCreateInfo makeImageCreateInfo (const IVec3& size, const VkFormat& format, bool cubemap)
72 {
73 	const VkImageUsageFlags		usage		= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
74 											  | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
75 											  | VK_IMAGE_USAGE_SAMPLED_BIT;
76 	const VkImageCreateFlags flags = cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
77 	const VkImageCreateInfo	imageParams	=
78 	{
79 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					//  VkStructureType         sType;
80 		DE_NULL,												//  const void*             pNext;
81 		flags,													//  VkImageCreateFlags      flags;
82 		VK_IMAGE_TYPE_2D,										//  VkImageType             imageType;
83 		format,													//  VkFormat                format;
84 		makeExtent3D(size.x(), size.y(), 1u),					//  VkExtent3D              extent;
85 		1u,														//  deUint32                mipLevels;
86 		(cubemap ? 6u : 1u),									//  deUint32                arrayLayers;
87 		VK_SAMPLE_COUNT_1_BIT,									//  VkSampleCountFlagBits   samples;
88 		VK_IMAGE_TILING_OPTIMAL,								//  VkImageTiling           tiling;
89 		usage,													//  VkImageUsageFlags       usage;
90 		VK_SHARING_MODE_EXCLUSIVE,								//  VkSharingMode           sharingMode;
91 		0u,														//  deUint32                queueFamilyIndexCount;
92 		DE_NULL,												//  const deUint32*         pQueueFamilyIndices;
93 		VK_IMAGE_LAYOUT_UNDEFINED,								//  VkImageLayout           initialLayout;
94 	};
95 
96 	return imageParams;
97 }
98 
makeVertexBuffer(const DeviceInterface & vk,const VkDevice device,const deUint32 queueFamilyIndex)99 Move<VkBuffer> makeVertexBuffer (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
100 {
101 	const VkBufferCreateInfo vertexBufferParams =
102 	{
103 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType      sType;
104 		DE_NULL,									// const void*          pNext;
105 		0u,											// VkBufferCreateFlags  flags;
106 		1024u,										// VkDeviceSize     size;
107 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags   usage;
108 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode        sharingMode;
109 		1u,											// deUint32             queueFamilyIndexCount;
110 		&queueFamilyIndex							// const deUint32*      pQueueFamilyIndices;
111 	};
112 
113 	Move<VkBuffer>			vertexBuffer		= createBuffer(vk, device, &vertexBufferParams);;
114 	return vertexBuffer;
115 }
116 
117 class SampleDrawnCubeFaceTestInstance : public TestInstance
118 {
119 public:
120 					SampleDrawnCubeFaceTestInstance	(Context&			context,
121 													 const IVec2&		size,
122 													 const VkFormat		format);
123 	tcu::TestStatus	iterate							(void);
124 
125 private:
126 	const tcu::IVec2&	m_size;
127 	const VkFormat		m_format;
128 };
129 
SampleDrawnCubeFaceTestInstance(Context & context,const IVec2 & size,const VkFormat format)130 SampleDrawnCubeFaceTestInstance::SampleDrawnCubeFaceTestInstance (Context& context, const IVec2& size, const VkFormat format)
131 	: TestInstance	(context)
132 	, m_size		(size)
133 	, m_format		(format)
134 {
135 }
136 
137 template<typename T>
sizeInBytes(const vector<T> & vec)138 inline size_t sizeInBytes (const vector<T>& vec)
139 {
140 	return vec.size() * sizeof(vec[0]);
141 }
142 
makeSampler(const DeviceInterface & vk,const VkDevice & device)143 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice& device)
144 {
145 	const VkSamplerCreateInfo samplerParams =
146 	{
147 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType          sType;
148 		DE_NULL,									// const void*              pNext;
149 		(VkSamplerCreateFlags)0,					// VkSamplerCreateFlags     flags;
150 		VK_FILTER_LINEAR,							// VkFilter                 magFilter;
151 		VK_FILTER_LINEAR,							// VkFilter                 minFilter;
152 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode      mipmapMode;
153 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode     addressModeU;
154 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode     addressModeV;
155 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode     addressModeW;
156 		0.0f,										// float                    mipLodBias;
157 		VK_FALSE,									// VkBool32                 anisotropyEnable;
158 		1.0f,										// float                    maxAnisotropy;
159 		VK_FALSE,									// VkBool32                 compareEnable;
160 		VK_COMPARE_OP_ALWAYS,						// VkCompareOp              compareOp;
161 		0.0f,										// float                    minLod;
162 		0.0f,										// float                    maxLod;
163 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor            borderColor;
164 		VK_FALSE,									// VkBool32                 unnormalizedCoordinates;
165 	};
166 
167 	return createSampler(vk, device, &samplerParams);
168 }
169 
170 // Draw a quad covering the whole framebuffer
genFullQuadVertices(void)171 vector<Vec4> genFullQuadVertices (void)
172 {
173 	vector<Vec4> vertices;
174 	vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
175 	vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
176 	vertices.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
177 	vertices.push_back(Vec4(1.0f,  -1.0f, 0.0f, 1.0f));
178 	vertices.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
179 	vertices.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
180 
181 	return vertices;
182 }
183 
184 struct Vertex
185 {
Vertexvkt::image::__anonf8ffaf260111::Vertex186 	Vertex(Vec4 vertices_, Vec2 uv_) : vertices(vertices_), uv(uv_) {}
187 	Vec4 vertices;
188 	Vec2 uv;
189 
190 	static VkVertexInputBindingDescription					getBindingDescription		(void);
191 	static vector<VkVertexInputAttributeDescription>		getAttributeDescriptions	(void);
192 };
193 
getBindingDescription(void)194 VkVertexInputBindingDescription Vertex::getBindingDescription (void)
195 {
196 	static const VkVertexInputBindingDescription desc =
197 	{
198 		0u,										// deUint32             binding;
199 		static_cast<deUint32>(sizeof(Vertex)),	// deUint32             stride;
200 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate    inputRate;
201 	};
202 
203 	return desc;
204 }
205 
getAttributeDescriptions(void)206 vector<VkVertexInputAttributeDescription> Vertex::getAttributeDescriptions (void)
207 {
208 	static const vector<VkVertexInputAttributeDescription> desc =
209 	{
210 		{
211 			0u,													// deUint32    location;
212 			0u,													// deUint32    binding;
213 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,					// VkFormat    format;
214 			static_cast<deUint32>(offsetof(Vertex, vertices)),	// deUint32    offset;
215 		},
216 		{
217 			1u,													// deUint32    location;
218 			0u,													// deUint32    binding;
219 			vk::VK_FORMAT_R32G32_SFLOAT,						// VkFormat    format;
220 			static_cast<deUint32>(offsetof(Vertex, uv)),		// deUint32    offset;
221 		},
222 	};
223 
224 	return desc;
225 }
226 
genTextureCoordinates(void)227 vector<Vertex> genTextureCoordinates (void)
228 {
229 	vector<Vertex> vertices;
230 	vertices.push_back(Vertex(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), Vec2(0.0f, 0.0f)));
231 	vertices.push_back(Vertex(Vec4( 1.0f, -1.0f, 0.0f, 1.0f), Vec2(1.0f, 0.0f)));
232 	vertices.push_back(Vertex(Vec4(-1.0f,  1.0f, 0.0f, 1.0f), Vec2(0.0f, 1.0f)));
233 	vertices.push_back(Vertex(Vec4(1.0f,  -1.0f, 0.0f, 1.0f), Vec2(1.0f, 0.0f)));
234 	vertices.push_back(Vertex(Vec4(1.0f, 1.0f, 0.0f, 1.0f), Vec2(1.0f, 1.0f)));
235 	vertices.push_back(Vertex(Vec4(-1.0f,  1.0f, 0.0f, 1.0f), Vec2(0.0f, 1.0f)));
236 
237 	return vertices;
238 }
239 
iterate(void)240 tcu::TestStatus SampleDrawnCubeFaceTestInstance::iterate (void)
241 {
242 	DE_ASSERT(m_format == VK_FORMAT_R8G8B8A8_UNORM);
243 
244 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
245 	const VkDevice					device					= m_context.getDevice();
246 	Allocator&						allocator				= m_context.getDefaultAllocator();
247 	const VkQueue					queue					= m_context.getUniversalQueue();
248 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
249 	const VkDeviceSize				bufferSize				= 1024;
250 
251 	const deUint32					layerStart				= 0;
252 	const deUint32					layerCount				= 6;
253 	const deUint32					levelCount				= 1;
254 
255 	const IVec3						imageSize				= {m_size.x(), m_size.y(), (deInt32)layerCount};
256 	const VkExtent2D				renderSize				= {deUint32(m_size.x()), deUint32(m_size.y())};
257 	const VkRect2D					renderArea				= makeRect2D(makeExtent3D(m_size.x(), m_size.y(), 1u));
258 	const vector<VkRect2D>			scissors				(1u, renderArea);
259 	const vector<VkViewport>		viewports				(1u, makeViewport(makeExtent3D(m_size.x(), m_size.y(), 1u)));
260 
261 	const vector<Vec4>				vertices				= genFullQuadVertices();
262 	Move<VkBuffer>					vertexBuffer			= makeVertexBuffer(vk, device, queueFamilyIndex);
263 	MovePtr<Allocation>				vertexBufferAlloc		= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
264 	const VkDeviceSize				vertexBufferOffset		= 0ull;
265 
266 	deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], sizeInBytes(vertices));
267 	flushAlloc(vk, device, *vertexBufferAlloc);
268 
269 	// Create a cubemap image.
270 	const VkImageCreateInfo			cubemapCreateInfo		= makeImageCreateInfo(imageSize, m_format, true);
271 	const VkImageSubresourceRange	cubemapSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, levelCount, layerStart, layerCount);
272 	const ImageWithMemory			cubemapImage			(vk, device, m_context.getDefaultAllocator(), cubemapCreateInfo, MemoryRequirement::Any);
273 	Move<VkImageView>				cubemapImageView		= makeImageView(vk, device, *cubemapImage, VK_IMAGE_VIEW_TYPE_CUBE, m_format, cubemapSubresourceRange);
274 
275 	// Create a sampler for the cubemap and bind it.
276 	Move<VkImageView>				sampledImageView		= makeImageView(vk, device, *cubemapImage, VK_IMAGE_VIEW_TYPE_CUBE, m_format, cubemapSubresourceRange);
277 	const Unique<VkSampler>			cubemapSampler			(makeSampler(vk, device));
278 	const VkDescriptorImageInfo		descriptorImageInfo		= makeDescriptorImageInfo(cubemapSampler.get(), *sampledImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
279 
280 	const auto						descriptorSetLayout	(DescriptorSetLayoutBuilder()
281 										.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &cubemapSampler.get())
282 										.build(vk, device));
283 
284 	const Unique<VkDescriptorPool>	descriptorPool			(DescriptorPoolBuilder()
285 										.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u)
286 										.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
287 
288 	const Unique<VkDescriptorSet>	descriptorSet			(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
289 
290 	DescriptorSetUpdateBuilder()
291 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
292 						 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo)
293 			.update(vk, device);
294 
295 	// Generate texture coordinates for the sampler.
296 	vector<Vertex>					uvCoordinates			= genTextureCoordinates();
297 	Move<VkBuffer>					uvBuffer				= makeVertexBuffer(vk, device, queueFamilyIndex);
298 	de::MovePtr<Allocation>			uvBufferAlloc			= bindBuffer(vk, device, allocator, *uvBuffer, MemoryRequirement::HostVisible);
299 	const VkDeviceSize				uvBufferOffset			= 0ull;
300 
301 	deMemcpy(uvBufferAlloc->getHostPtr(), &uvCoordinates[0], uvCoordinates.size() * sizeof (Vertex));
302 	flushAlloc(vk, device, *uvBufferAlloc);
303 
304 	// Sampled values will be written to this image.
305 	const VkImageSubresourceRange	targetSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, levelCount, layerStart, 1);
306 	const VkImageCreateInfo			targetImageCreateInfo	= makeImageCreateInfo(imageSize, m_format, false);
307 	const ImageWithMemory			targetImage				(vk, device, m_context.getDefaultAllocator(), targetImageCreateInfo, MemoryRequirement::Any);
308 	Move<VkImageView>				targetImageView			= makeImageView(vk, device, *targetImage, VK_IMAGE_VIEW_TYPE_2D, m_format, targetSubresourceRange);
309 
310 	// We use a push constant to hold count for how many times the shader has written to the cubemap.
311 	const VkPushConstantRange		pushConstantRange		= {
312 			VK_SHADER_STAGE_FRAGMENT_BIT,		// VkShaderStageFlags    stageFlags;
313 			0u,									// uint32_t              offset;
314 			(deUint32)sizeof(deUint32),			// uint32_t              size;
315 	};
316 
317 	const Move<VkCommandPool>		cmdPool					= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
318 	const Move<VkCommandBuffer>		cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
319 
320 	// Create two graphic pipelines. One for writing to the cubemap and the other for sampling it.
321 	Move<VkRenderPass>				renderPass1				= makeRenderPass (vk, device, m_format, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD,
322 																			  VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
323 																			  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, DE_NULL);
324 
325 	Move<VkFramebuffer>				framebuffer1			= makeFramebuffer(vk, device, *renderPass1, cubemapImageView.get(), renderSize.width, renderSize.height);
326 
327 	const Move<VkShaderModule>		vertexModule1			= createShaderModule (vk, device, m_context.getBinaryCollection().get("vert1"), 0u);
328 	const Move<VkShaderModule>		fragmentModule1			= createShaderModule (vk, device, m_context.getBinaryCollection().get("frag1"), 0u);
329 
330 	const Move<VkPipelineLayout>	pipelineLayout1			= makePipelineLayout (vk, device, 0, DE_NULL, 1, &pushConstantRange);
331 	const Move<VkPipeline>			graphicsPipeline1		= makeGraphicsPipeline(vk, device, pipelineLayout1.get(), vertexModule1.get(),
332 																				   DE_NULL, DE_NULL, DE_NULL, fragmentModule1.get(), renderPass1.get(),
333 																				   viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
334 																				   DE_NULL);
335 
336 	Move<VkRenderPass>				renderPass2				= makeRenderPass(vk, device, m_format, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
337 
338 	Move<VkFramebuffer>				framebuffer2			= makeFramebuffer(vk, device, *renderPass2, targetImageView.get(), renderSize.width, renderSize.height);
339 
340 	Move<VkShaderModule>			vertexModule2			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert2"), 0u);
341 	Move<VkShaderModule>			fragmentModule2			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag2"), 0u);
342 
343 	const Move<VkPipelineLayout>	pipelineLayout2			= makePipelineLayout(vk, device, *descriptorSetLayout);
344 
345 	const auto						vtxBindingDescription	= Vertex::getBindingDescription();
346 	const auto						vtxAttrDescriptions		= Vertex::getAttributeDescriptions();
347 
348 	const VkPipelineVertexInputStateCreateInfo	vertexInputInfo =
349 	{
350 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType
351 		nullptr,													// const void*                                 pNext
352 		0u,															// VkPipelineVertexInputStateCreateFlags       flags
353 		1u,															// deUint32                                    vertexBindingDescriptionCount
354 		&vtxBindingDescription,										// const VkVertexInputBindingDescription*      pVertexBindingDescriptions
355 		static_cast<deUint32>(vtxAttrDescriptions.size()),			// deUint32                                    vertexAttributeDescriptionCount
356 		vtxAttrDescriptions.data(),									// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
357 	};
358 
359 	const Move<VkPipeline>			graphicsPipeline2		= makeGraphicsPipeline(vk, device, pipelineLayout2.get(), vertexModule2.get(),
360 																				   DE_NULL, DE_NULL, DE_NULL, fragmentModule2.get(),
361 																				   renderPass2.get(), viewports, scissors,
362 																				   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &vertexInputInfo);
363 
364 	// The values sampled in the second pipeline will be copied to this buffer.
365 	const VkBufferCreateInfo		resultBufferCreateInfo	= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
366 	Move<VkBuffer>					resultBuffer			= createBuffer(vk, device, &resultBufferCreateInfo);
367 	MovePtr<Allocation>				resultBufferMemory		= allocator.allocate(getBufferMemoryRequirements(vk, device, *resultBuffer), MemoryRequirement::HostVisible);
368 	MovePtr<TextureLevel>			resultImage				(new TextureLevel(mapVkFormat(m_format), renderSize.width, renderSize.height, 1));
369 
370 	VK_CHECK(vk.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
371 
372 	// Clear the cubemap faces and the target image as black.
373 	const Vec4						clearColor				(0.0f, 0.0f, 0.0f, 1.0f);
374 
375 	clearColorImage(vk, device, m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(),
376 					cubemapImage.get(), clearColor, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
377 					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, layerCount);
378 
379 	clearColorImage(vk, device, m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(),
380 					targetImage.get(), clearColor, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
381 					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
382 
383 	// Run the shaders twice.
384 	beginCommandBuffer(vk, *cmdBuffer);
385 
386 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout2, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
387 
388 	for (int pass = 0; pass < 2; pass++)
389 	{
390 		//  Draw on the first cube map face.
391 		vk.cmdPushConstants(*cmdBuffer, *pipelineLayout1, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(deInt32), &pass);
392 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline1);
393 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
394 
395 		beginRenderPass(vk, *cmdBuffer, *renderPass1, *framebuffer1, makeRect2D(0, 0, imageSize.x(), imageSize.y()), 0, DE_NULL);
396 		vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
397 		endRenderPass(vk, *cmdBuffer);
398 
399 		{
400 			const auto barrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
401 														VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
402 														cubemapImage.get(), cubemapSubresourceRange);
403 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier);
404 		}
405 
406 		// Sample the four faces around the first face.
407 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline2);
408 
409 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &uvBuffer.get(), &uvBufferOffset);
410 
411 		beginRenderPass(vk, *cmdBuffer, *renderPass2, *framebuffer2, makeRect2D(0, 0, imageSize.x(), imageSize.y()), 0u, DE_NULL);
412 		vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
413 		endRenderPass(vk, *cmdBuffer);
414 
415 		if (pass == 0)
416 		{
417 			const auto	barrier		= makeImageMemoryBarrier(0u, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
418 															 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, cubemapImage.get(), cubemapSubresourceRange);
419 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier);
420 
421 			const auto	barrier2	= makeImageMemoryBarrier(0u, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
422 															 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
423 															 targetImage.get(), targetSubresourceRange);
424 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier2);
425 		}
426 	}
427 
428 	// Read the result buffer data
429 	copyImageToBuffer(vk, *cmdBuffer, *targetImage, *resultBuffer, IVec2(m_size.x(), m_size.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
430 
431 	endCommandBuffer(vk, *cmdBuffer);
432 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
433 
434 	invalidateAlloc(vk, device, *resultBufferMemory);
435 
436 	tcu::clear(resultImage->getAccess(), IVec4(0));
437 	tcu::copy(resultImage->getAccess(), ConstPixelBufferAccess(resultImage.get()->getFormat(),
438 			  resultImage.get()->getSize(), resultBufferMemory->getHostPtr()));
439 
440 	bool result = true;
441 
442 	// The first run writes pure red and the second pure blue hence the value of the red component
443 	// should be 0.0 and the value in the blue channel > 0.0.
444 	for (deUint32 y = 0; y < renderSize.height; y++)
445 	{
446 		const deUint8* ptr = static_cast<const deUint8 *>(resultImage->getAccess().getPixelPtr(renderSize.width-1, y, 0));
447 		const IVec4 val = IVec4(ptr[0], ptr[1], ptr[2], ptr[3]);
448 		if (!(val[0] == 0 && val[1] > 0))
449 			result = false;
450 	}
451 
452 	// Log attachment contents
453 	m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Attachment ", "")
454 	<< tcu::TestLog::Image("Rendered image", "Rendered image", resultImage->getAccess())
455 	<< tcu::TestLog::EndImageSet;
456 
457 	if (result)
458 		return tcu::TestStatus::pass("pass");
459 	else
460 		return tcu::TestStatus::fail("fail");
461 }
462 
463 class SampleDrawnCubeFaceTest : public TestCase
464 {
465 public:
466 						SampleDrawnCubeFaceTest	(tcu::TestContext&	testCtx,
467 												const std::string&	name,
468 												const std::string&	description,
469 												const tcu::IVec2&	size,
470 												const VkFormat		format);
471 
472 	void				initPrograms			(SourceCollections& programCollection) const;
473 	TestInstance*		createInstance			(Context&			context) const;
474 
475 private:
476 	const tcu::IVec2	m_size;
477 	const VkFormat		m_format;
478 };
479 
SampleDrawnCubeFaceTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const tcu::IVec2 & size,const VkFormat format)480 SampleDrawnCubeFaceTest::SampleDrawnCubeFaceTest (tcu::TestContext&	testCtx,
481 												 const std::string&	name,
482 												 const std::string&	description,
483 												 const tcu::IVec2&	size,
484 												 const VkFormat		format)
485 	: TestCase	(testCtx, name, description)
486 	, m_size	(size)
487 	, m_format	(format)
488 {
489 }
490 
initPrograms(SourceCollections & programCollection) const491 void SampleDrawnCubeFaceTest::initPrograms (SourceCollections& programCollection) const
492 {
493 	std::ostringstream pipeline1VertexSrc;
494 	pipeline1VertexSrc
495 		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
496 		<< "layout(location = 0) in vec4 a_position;\n"
497 		<< "void main (void) {\n"
498 		<< "    gl_Position = a_position;\n"
499 		<< "}\n";
500 
501 	std::ostringstream pipeline1FragmentSrc;
502 	pipeline1FragmentSrc
503 			<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
504 			<< "layout(location = 0) out vec4 outColor;\n"
505 			<< "layout(push_constant) uniform constants {\n"
506 			<< "     int pass;\n"
507 			<< "} pc;\n"
508 			<< "void main() {\n"
509 			<< "   if (pc.pass == 1) {\n"
510 			<< "      outColor = vec4(0., 1., 1., 1.);\n"
511 			<< "    } else {\n"
512 			<< "      outColor = vec4(1., 0., 1., 1.);\n"
513 			<< "    }\n"
514 			<< "}\n";
515 
516 	std::ostringstream pipeline2VertexSrc;
517 	pipeline2VertexSrc
518 		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
519 		<< "layout(location = 0) in highp vec4 a_position;\n"
520 		<< "layout(location = 1) in vec2 inTexCoord;\n"
521 		<< "layout(location = 1) out vec2 fragTexCoord;\n"
522 		<< "void main (void) {\n"
523 		<< "    gl_Position = a_position;\n"
524 		<< "    fragTexCoord = inTexCoord;\n"
525 		<< "}\n";
526 
527 	std::ostringstream pipeline2FragmentSrc;
528 	pipeline2FragmentSrc
529 		<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
530 		<< "layout(location = 0) out vec4 outColor;\n"
531 		<< "layout(location = 1) in vec2 fragTexCoord;\n"
532 		<< "layout(binding = 0) uniform samplerCube texSampler;\n"
533 		<< "void main() {\n"
534 		<< "     outColor = texture(texSampler, vec3(fragTexCoord.x, 1.0, fragTexCoord.y));\n"
535 		<< "     outColor += texture(texSampler, vec3(fragTexCoord.x, -1.0, fragTexCoord.y));\n"
536 		<< "     outColor += texture(texSampler, vec3(fragTexCoord.x, fragTexCoord.y, 1.0));\n"
537 		<< "     outColor += texture(texSampler, vec3(fragTexCoord.x, fragTexCoord.y, -1.0));\n"
538 		<< "     outColor /= 4.;\n"
539 		<< "}\n";
540 
541 	programCollection.glslSources.add("vert1") << glu::VertexSource(pipeline1VertexSrc.str());
542 	programCollection.glslSources.add("vert2") << glu::VertexSource(pipeline2VertexSrc.str());
543 	programCollection.glslSources.add("frag1") << glu::FragmentSource(pipeline1FragmentSrc.str());
544 	programCollection.glslSources.add("frag2") << glu::FragmentSource(pipeline2FragmentSrc.str());
545 }
546 
createInstance(Context & context) const547 TestInstance* SampleDrawnCubeFaceTest::createInstance (Context& context) const
548 {
549 	return new SampleDrawnCubeFaceTestInstance(context, m_size, m_format);
550 }
551 
552 } // anonymous ns
553 
createImageSampleDrawnCubeFaceTests(tcu::TestContext & testCtx)554 tcu::TestCaseGroup* createImageSampleDrawnCubeFaceTests	(tcu::TestContext& testCtx)
555 {
556 	const VkFormat		format	= VK_FORMAT_R8G8B8A8_UNORM;
557 	const tcu::IVec2	size	= tcu::IVec2(8, 8);
558 
559 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "sample_cubemap", "Sample cube map faces that has been rendered to tests"));
560 
561 	testGroup->addChild(new SampleDrawnCubeFaceTest(testCtx, "write_face_0", "", size, format));
562 
563 	return testGroup.release();
564 }
565 
566 } // image
567 } // vkt
568