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