ShaderRenderCase: rebase implementation on sdk-0.9
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrendercase / vktShaderRenderCase.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and/or associated documentation files (the
10  * "Materials"), to deal in the Materials without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sublicense, and/or sell copies of the Materials, and to
13  * permit persons to whom the Materials are furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice(s) and this permission notice shall be included
17  * in all copies or substantial portions of the Materials.
18  *
19  * The Materials are Confidential Information as defined by the
20  * Khronos Membership Agreement until designated non-confidential by Khronos,
21  * at which point this condition clause shall be removed.
22  *
23  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
30  *
31  *//*!
32  * \file
33  * \brief Vulkan ShaderRenderCase
34  *//*--------------------------------------------------------------------*/
35
36 #include "vktShaderRenderCase.hpp"
37
38 #include "tcuImageCompare.hpp"
39 #include "tcuImageIO.hpp"
40 #include "tcuSurface.hpp"
41 #include "tcuVector.hpp"
42 #include "tcuTestLog.hpp"
43 #include "tcuTextureUtil.hpp"
44
45 #include "deMath.h"
46 #include "deFilePath.hpp"
47 #include "deUniquePtr.hpp"
48
49 #include "vkPlatform.hpp"
50 #include "vkStrUtil.hpp"
51 #include "vkRef.hpp"
52 #include "vkRefUtil.hpp"
53 #include "vkQueryUtil.hpp"
54 #include "vkDeviceUtil.hpp"
55
56 #include <vector>
57 #include <string>
58
59 namespace vkt
60 {
61 namespace shaderrendercase
62 {
63
64 using namespace vk;
65
66 static const int                GRID_SIZE                       = 2;
67 static const int                MAX_RENDER_WIDTH        = 128;
68 static const int                MAX_RENDER_HEIGHT       = 112;
69 static const tcu::Vec4  DEFAULT_CLEAR_COLOR     = tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
70
71 // QuadGrid.
72
73 class QuadGrid
74 {
75 public:
76                                                                                 QuadGrid                                (int                                                            gridSize,
77                                                                                                                                  int                                                            screenWidth,
78                                                                                                                                  int                                                            screenHeight,
79                                                                                                                                  const tcu::Vec4&                                       constCoords,
80                                                                                                                                  const std::vector<tcu::Mat4>&          userAttribTransforms,
81                                                                                                                                  const std::vector<TextureBinding>&     textures);
82                                                                                 ~QuadGrid                               (void);
83
84         int                                                                     getGridSize                             (void) const { return m_gridSize; }
85         int                                                                     getNumVertices                  (void) const { return m_numVertices; }
86         int                                                                     getNumTriangles                 (void) const { return m_numTriangles; }
87         const tcu::Vec4&                                        getConstCoords                  (void) const { return m_constCoords; }
88         const std::vector<tcu::Mat4>            getUserAttribTransforms (void) const { return m_userAttribTransforms; }
89         const std::vector<TextureBinding>&      getTextures                             (void) const { return m_textures; }
90
91         const tcu::Vec4*                                        getPositions                    (void) const { return &m_positions[0]; }
92         const float*                                            getAttribOne                    (void) const { return &m_attribOne[0]; }
93         const tcu::Vec4*                                        getCoords                               (void) const { return &m_coords[0]; }
94         const tcu::Vec4*                                        getUnitCoords                   (void) const { return &m_unitCoords[0]; }
95
96         const tcu::Vec4*                                        getUserAttrib                   (int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
97         const deUint16*                                         getIndices                              (void) const { return &m_indices[0]; }
98
99         tcu::Vec4                                                       getCoords                               (float sx, float sy) const;
100         tcu::Vec4                                                       getUnitCoords                   (float sx, float sy) const;
101
102         int                                                                     getNumUserAttribs               (void) const { return (int)m_userAttribTransforms.size(); }
103         tcu::Vec4                                                       getUserAttrib                   (int attribNdx, float sx, float sy) const;
104
105 private:
106         const int                                                       m_gridSize;
107         const int                                                       m_numVertices;
108         const int                                                       m_numTriangles;
109         const tcu::Vec4                                         m_constCoords;
110         const std::vector<tcu::Mat4>            m_userAttribTransforms;
111
112         const std::vector<TextureBinding>       m_textures;
113
114         std::vector<tcu::Vec4>                          m_screenPos;
115         std::vector<tcu::Vec4>                          m_positions;
116         std::vector<tcu::Vec4>                          m_coords;               //!< Near-unit coordinates, roughly [-2.0 .. 2.0].
117         std::vector<tcu::Vec4>                          m_unitCoords;   //!< Positive-only coordinates [0.0 .. 1.5].
118         std::vector<float>                                      m_attribOne;
119         std::vector<tcu::Vec4>                          m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
120         std::vector<deUint16>                           m_indices;
121 };
122
123 QuadGrid::QuadGrid (int                                                                 gridSize,
124                                         int                                                                     width,
125                                         int                                                                     height,
126                                         const tcu::Vec4&                                        constCoords,
127                                         const std::vector<tcu::Mat4>&           userAttribTransforms,
128                                         const std::vector<TextureBinding>&      textures)
129         : m_gridSize                            (gridSize)
130         , m_numVertices                         ((gridSize + 1) * (gridSize + 1))
131         , m_numTriangles                        (gridSize * gridSize * 2)
132         , m_constCoords                         (constCoords)
133         , m_userAttribTransforms        (userAttribTransforms)
134         , m_textures                            (textures)
135 {
136         const tcu::Vec4 viewportScale   ((float)width, (float)height, 0.0f, 0.0f);
137
138         // Compute vertices.
139         m_screenPos.resize(m_numVertices);
140         m_positions.resize(m_numVertices);
141         m_coords.resize(m_numVertices);
142         m_unitCoords.resize(m_numVertices);
143         m_attribOne.resize(m_numVertices);
144
145         // User attributes.
146         for (int attrNdx = 0; attrNdx < DE_LENGTH_OF_ARRAY(m_userAttribs); attrNdx++)
147                 m_userAttribs[attrNdx].resize(m_numVertices);
148
149         for (int y = 0; y < gridSize+1; y++)
150         for (int x = 0; x < gridSize+1; x++)
151         {
152                 float           sx                      = (float)x / (float)gridSize;
153                 float           sy                      = (float)y / (float)gridSize;
154                 float           fx                      = 2.0f * sx - 1.0f;
155                 float           fy                      = 2.0f * sy - 1.0f;
156                 int                     vtxNdx          = ((y * (gridSize+1)) + x);
157
158                 m_positions[vtxNdx]     = tcu::Vec4(fx, fy, 0.0f, 1.0f);
159                 m_coords[vtxNdx]                = getCoords(sx, sy);
160                 m_unitCoords[vtxNdx]    = getUnitCoords(sx, sy);
161                 m_attribOne[vtxNdx]     = 1.0f;
162
163                 m_screenPos[vtxNdx]             = tcu::Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
164
165                 for (int attribNdx = 0; attribNdx < getNumUserAttribs(); attribNdx++)
166                         m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
167         }
168
169         // Compute indices.
170         m_indices.resize(3 * m_numTriangles);
171         for (int y = 0; y < gridSize; y++)
172         for (int x = 0; x < gridSize; x++)
173         {
174                 int stride                              = gridSize + 1;
175                 int v00                                 = (y * stride) + x;
176                 int v01                                 = (y * stride) + x + 1;
177                 int v10                                 = ((y+1) * stride) + x;
178                 int v11                                 = ((y+1) * stride) + x + 1;
179
180                 int baseNdx                     = ((y * gridSize) + x) * 6;
181                 m_indices[baseNdx + 0]  = (deUint16)v10;
182                 m_indices[baseNdx + 1]  = (deUint16)v00;
183                 m_indices[baseNdx + 2]  = (deUint16)v01;
184
185                 m_indices[baseNdx + 3]  = (deUint16)v10;
186                 m_indices[baseNdx + 4]  = (deUint16)v01;
187                 m_indices[baseNdx + 5]  = (deUint16)v11;
188         }
189 }
190
191 QuadGrid::~QuadGrid (void)
192 {
193 }
194
195 inline tcu::Vec4 QuadGrid::getCoords (float sx, float sy) const
196 {
197         const float fx = 2.0f * sx - 1.0f;
198         const float fy = 2.0f * sy - 1.0f;
199         return tcu::Vec4(fx, fy, -fx + 0.33f*fy, -0.275f*fx - fy);
200 }
201
202 inline tcu::Vec4 QuadGrid::getUnitCoords (float sx, float sy) const
203 {
204         return tcu::Vec4(sx, sy, 0.33f*sx + 0.5f*sy, 0.5f*sx + 0.25f*sy);
205 }
206
207 inline tcu::Vec4 QuadGrid::getUserAttrib (int attribNdx, float sx, float sy) const
208 {
209         // homogeneous normalized screen-space coordinates
210         return m_userAttribTransforms[attribNdx] * tcu::Vec4(sx, sy, 0.0f, 1.0f);
211 }
212
213 // TextureBinding
214
215 TextureBinding::TextureBinding (const tcu::Archive&     archive,
216                                                                 const char*                     filename,
217                                                                 const Type                      type,
218                                                                 const tcu::Sampler&     sampler)
219         : m_type        (type)
220         , m_sampler     (sampler)
221 {
222         switch(m_type)
223         {
224                 case TYPE_2D: m_binding.tex2D = loadTexture2D(archive, filename); break;
225                 default:
226                         TCU_FAIL("Unsupported texture type");
227         }
228 }
229
230 tcu::Texture2D* TextureBinding::loadTexture2D (const tcu::Archive& archive, const char* filename)
231 {
232         std::string ext = de::FilePath(filename).getFileExtension();
233
234         if (ext == "png")
235         {
236                 // Uncompressed texture.
237                 tcu::TextureLevel level;
238                 tcu::ImageIO::loadPNG(level, archive, filename);
239
240                 TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
241                                                         level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
242
243                 // \todo [2015-10-08 elecro] for some reason we get better when using RGBA texture even in RGB case, this needs to be investigated
244                 tcu::Texture2D* texture = new tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight());
245
246                 try
247                 {
248                         // Fill level 0.
249                         texture->allocLevel(0);
250
251                         tcu::copy(texture->getLevel(0), level.getAccess());
252                 }
253                 catch (const std::exception&)
254                 {
255                         delete texture;
256                         throw;
257                 }
258
259                 return texture;
260         }
261         else
262                 TCU_FAIL("Unsupported file format"); // TODO: maybe support pkm?
263 }
264
265 // ShaderEvalContext.
266
267 ShaderEvalContext::ShaderEvalContext (const QuadGrid& quadGrid)
268         : constCoords   (quadGrid.getConstCoords())
269         , isDiscarded   (false)
270         , m_quadGrid    (quadGrid)
271 {
272         const std::vector<TextureBinding>& bindings = m_quadGrid.getTextures();
273         DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);
274
275         // Fill in texture array.
276         for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
277         {
278                 const TextureBinding& binding = bindings[ndx];
279
280                 if (binding.getType() == TextureBinding::TYPE_NONE)
281                         continue;
282
283                 textures[ndx].sampler = binding.getSampler();
284
285                 switch (binding.getType())
286                 {
287                         case TextureBinding::TYPE_2D:           textures[ndx].tex2D                     = binding.get2D();              break;
288                         // \todo [2015-09-07 elecro] Add support for the other binding types
289                         /*
290                         case TextureBinding::TYPE_CUBE_MAP:     textures[ndx].texCube           = &binding.getCube()->getRefTexture();          break;
291                         case TextureBinding::TYPE_2D_ARRAY:     textures[ndx].tex2DArray        = &binding.get2DArray()->getRefTexture();       break;
292                         case TextureBinding::TYPE_3D:           textures[ndx].tex3D                     = &binding.get3D()->getRefTexture();            break;
293                         */
294                         default:
295                                 TCU_THROW(InternalError, "Handling of texture binding type not implemented");
296                 }
297         }
298 }
299
300 ShaderEvalContext::~ShaderEvalContext (void)
301 {
302 }
303
304 void ShaderEvalContext::reset (float sx, float sy)
305 {
306         // Clear old values
307         color           = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
308         isDiscarded     = false;
309
310         // Compute coords
311         coords          = m_quadGrid.getCoords(sx, sy);
312         unitCoords      = m_quadGrid.getUnitCoords(sx, sy);
313
314         // Compute user attributes.
315         const int numAttribs = m_quadGrid.getNumUserAttribs();
316         DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
317         for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
318                 in[attribNdx] = m_quadGrid.getUserAttrib(attribNdx, sx, sy);
319 }
320
321 tcu::Vec4 ShaderEvalContext::texture2D (int unitNdx, const tcu::Vec2& texCoords)
322 {
323         if (textures[unitNdx].tex2D)
324                 return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
325         else
326         return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
327 }
328
329 // ShaderEvaluator.
330
331 ShaderEvaluator::ShaderEvaluator (void)
332         : m_evalFunc(DE_NULL)
333 {
334 }
335
336 ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
337         : m_evalFunc(evalFunc)
338 {
339 }
340
341 ShaderEvaluator::~ShaderEvaluator (void)
342 {
343 }
344
345 void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
346 {
347         DE_ASSERT(m_evalFunc);
348         m_evalFunc(ctx);
349 }
350
351 // UniformSetup.
352
353 UniformSetup::UniformSetup (void)
354         : m_setupFunc(DE_NULL)
355 {
356 }
357
358 UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
359         : m_setupFunc(setupFunc)
360 {
361 }
362
363 UniformSetup::~UniformSetup (void)
364 {
365 }
366
367 void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
368 {
369         if (m_setupFunc)
370                 m_setupFunc(instance, constCoords);
371 }
372
373 // ShaderRenderCase.
374
375 ShaderRenderCase::ShaderRenderCase (tcu::TestContext&                   testCtx,
376                                                                         const std::string&                      name,
377                                                                         const std::string&                      description,
378                                                                         const bool                                      isVertexCase,
379                                                                         const ShaderEvalFunc            evalFunc,
380                                                                         const UniformSetup*                     uniformSetup,
381                                                                         const AttributeSetupFunc        attribFunc)
382         : vkt::TestCase         (testCtx, name, description)
383         , m_isVertexCase        (isVertexCase)
384         , m_evaluator           (new ShaderEvaluator(evalFunc))
385         , m_uniformSetup        (uniformSetup ? uniformSetup : new UniformSetup())
386         , m_attribFunc          (attribFunc)
387 {}
388
389 ShaderRenderCase::ShaderRenderCase (tcu::TestContext&                   testCtx,
390                                                                         const std::string&                      name,
391                                                                         const std::string&                      description,
392                                                                         const bool                                      isVertexCase,
393                                                                         const ShaderEvaluator*          evaluator,
394                                                                         const UniformSetup*                     uniformSetup,
395                                                                         const AttributeSetupFunc        attribFunc)
396         : vkt::TestCase         (testCtx, name, description)
397         , m_isVertexCase        (isVertexCase)
398         , m_evaluator           (evaluator)
399         , m_uniformSetup        (uniformSetup ? uniformSetup : new UniformSetup())
400         , m_attribFunc          (attribFunc)
401 {}
402
403 ShaderRenderCase::~ShaderRenderCase (void)
404 {
405         delete m_evaluator;
406         m_evaluator = DE_NULL;
407         delete m_uniformSetup;
408         m_uniformSetup = DE_NULL;
409 }
410
411 void ShaderRenderCase::initPrograms (vk::SourceCollections& programCollection) const
412 {
413         programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
414         programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
415 }
416
417 TestInstance* ShaderRenderCase::createInstance (Context& context) const
418 {
419         DE_ASSERT(m_evaluator != DE_NULL);
420         DE_ASSERT(m_uniformSetup != DE_NULL);
421         return new ShaderRenderCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_attribFunc);
422 }
423
424 // ShaderRenderCaseInstance.
425
426 ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&                                    context,
427                                                                                                         const bool                                      isVertexCase,
428                                                                                                         const ShaderEvaluator&          evaluator,
429                                                                                                         const UniformSetup&                     uniformSetup,
430                                                                                                         const AttributeSetupFunc        attribFunc)
431         : vkt::TestInstance     (context)
432         , m_clearColor          (DEFAULT_CLEAR_COLOR)
433         , m_memAlloc            (m_context.getDeviceInterface(), m_context.getDevice(), getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()))
434         , m_isVertexCase        (isVertexCase)
435         , m_evaluator           (evaluator)
436         , m_uniformSetup        (uniformSetup)
437         , m_attribFunc          (attribFunc)
438         , m_renderSize          (100, 100)
439         , m_colorFormat         (VK_FORMAT_R8G8B8A8_UNORM)
440 {
441 }
442
443 ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
444 {
445 }
446
447 tcu::TestStatus ShaderRenderCaseInstance::iterate (void)
448 {
449         setup();
450
451         // Create quad grid.
452         const tcu::IVec2        viewportSize    = getViewportSize();
453         const int                       width                   = viewportSize.x();
454         const int                       height                  = viewportSize.y();
455
456         QuadGrid                        quadGrid                (m_isVertexCase ? GRID_SIZE : 4, width, height, tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f), m_userAttribTransforms, m_textures);
457
458         // Render result.
459         tcu::Surface            resImage                (width, height);
460         render(resImage, quadGrid);
461
462         // Compute reference.
463         tcu::Surface            refImage                (width, height);
464         if (m_isVertexCase)
465                 computeVertexReference(refImage, quadGrid);
466         else
467                 computeFragmentReference(refImage, quadGrid);
468
469         // Compare.
470         const bool                      compareOk               = compareImages(resImage, refImage, 0.05f);
471
472         if (compareOk)
473                 return tcu::TestStatus::pass("Result image matches reference");
474         else
475                 return tcu::TestStatus::fail("Image mismatch");
476 }
477
478 void ShaderRenderCaseInstance::setupUniformData (deUint32 bindingLocation, deUint32 size, const void* dataPtr)
479 {
480         const VkDevice                                  vkDevice                        = m_context.getDevice();
481         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
482         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
483
484         const VkBufferCreateInfo                uniformBufferParams     =
485         {
486                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
487                 DE_NULL,                                                                        // const void*                  pNext;
488                 size,                                                                           // VkDeviceSize                 size;
489                 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                     // VkBufferUsageFlags   usage;
490                 0u,                                                                                     // VkBufferCreateFlags  flags;
491                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
492                 1u,                                                                                     // deUint32                             queueFamilyCount;
493                 &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
494         };
495
496         Move<VkBuffer>                                  buffer                          = createBuffer(vk, vkDevice, &uniformBufferParams);
497         de::MovePtr<Allocation>                 alloc                           = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::Any);
498         VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), 0));
499
500         void* bufferPtr;
501         VK_CHECK(vk.mapMemory(vkDevice, alloc->getMemory(), 0, size, 0, &bufferPtr));
502         deMemcpy(bufferPtr, dataPtr, size);
503         vk.unmapMemory(vkDevice, alloc->getMemory());
504
505         const VkBufferViewCreateInfo    viewInfo        =
506         {
507                 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,      // VkStructureType      sType;
508                 DE_NULL,                                                                        // void*                        pNext;
509                 *buffer,                                                                        // VkBuffer                     buffer;
510                 VK_FORMAT_R32_SFLOAT,                                           // VkFormat     format;
511                 0u,                                                                                     // VkDeviceSize offset;
512                 size,                                                                           // VkDeviceSize range;
513         };
514
515         Move<VkBufferView>                              bufferView                      = createBufferView(vk, vkDevice, &viewInfo);
516
517         // \todo [2015-10-09 elecro] remove the '_hack_padding' variable if the driver support small uniforms,
518         // that is for example one float big uniforms.
519         const deUint32 _hack_padding = size < 4 * sizeof(float) ? (deUint32)(3u * sizeof(float)) : 0u;
520
521         const VkDescriptorInfo                  descriptor                      =
522         {
523                 bufferView.get(),                                                       // VkBufferView                         bufferView;
524                 0,                                                                                      // VkSampler                            sampler;
525                 0,                                                                                      // VkImageView                          imageView;
526                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        imageLayout;
527                 {
528                         *buffer,                                                // VkBuffer             buffer;
529                         0u,                                                             // VkDeviceSize offset;
530                         size + _hack_padding,                   // VkDeviceSize range;
531                 },                                                                                      // VkDescriptorBufferInfo       bufferInfo;
532         };
533
534         de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
535         uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
536         uniformInfo->descriptor = descriptor;
537         uniformInfo->location = bindingLocation;
538         uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
539         uniformInfo->bufferView = VkBufferViewSp(new vk::Unique<VkBufferView>(bufferView));
540         uniformInfo->alloc = AllocationSp(new de::UniquePtr<vk::Allocation>(alloc));
541
542         m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
543 }
544
545 void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, deUint32 dataSize, const void* data)
546 {
547         m_descriptorSetLayoutBuilder.addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT);
548         m_descriptorPoolBuilder.addType(descriptorType);
549
550         setupUniformData(bindingLocation, dataSize, data);
551 }
552
553 void ShaderRenderCaseInstance::addAttribute (deUint32 bindingLocation, vk::VkFormat format, deUint32 sizePerElement, deUint32 count, const void* dataPtr)
554 {
555         // Add binding specification
556         const deUint32                                                  binding                                 = (deUint32)m_vertexBindingDescription.size();
557         const VkVertexInputBindingDescription   bindingDescription              =
558         {
559                 binding,
560                 sizePerElement,
561                 VK_VERTEX_INPUT_STEP_RATE_VERTEX
562         };
563
564         m_vertexBindingDescription.push_back(bindingDescription);
565
566         // Add location and format specification
567         const VkVertexInputAttributeDescription attributeDescription    =
568         {
569                 bindingLocation,                        // deUint32     location;
570                 binding,                                        // deUint32     binding;
571                 format,                                         // VkFormat     format;
572                 0u,                                                     // deUint32     offsetInBytes;
573         };
574
575         m_vertexattributeDescription.push_back(attributeDescription);
576
577         // Upload data to buffer
578         const VkDevice                                                  vkDevice                                = m_context.getDevice();
579         const DeviceInterface&                                  vk                                              = m_context.getDeviceInterface();
580         const deUint32                                                  queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
581
582         const VkDeviceSize                                              inputSize                               = sizePerElement * count;
583         const VkBufferCreateInfo                                vertexBufferParams              =
584         {
585                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
586                 DE_NULL,                                                                        // const void*                  pNext;
587                 inputSize,                                                                      // VkDeviceSize                 size;
588                 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
589                 0u,                                                                                     // VkBufferCreateFlags  flags;
590                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
591                 1u,                                                                                     // deUint32                             queueFamilyCount;
592                 &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
593         };
594
595         Move<VkBuffer>                                                  buffer                                  = createBuffer(vk, vkDevice, &vertexBufferParams);
596         de::MovePtr<vk::Allocation>                             alloc                                   = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::Any);
597
598         VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), 0));
599
600         void* bufferPtr;
601         VK_CHECK(vk.mapMemory(vkDevice, alloc->getMemory(), 0, inputSize, 0, &bufferPtr));
602         deMemcpy(bufferPtr, dataPtr, inputSize);
603         vk.unmapMemory(vkDevice, alloc->getMemory());
604
605         m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
606         m_vertexBufferAllocs.push_back(AllocationSp(new de::UniquePtr<vk::Allocation>(alloc)));
607 }
608
609 void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
610 {
611         const EnabledBaseAttribute attribute =
612         {
613                 bindingLocation,
614                 type
615         };
616         m_enabledBaseAttributes.push_back(attribute);
617 }
618
619 void ShaderRenderCaseInstance::setup (void)
620 {
621 }
622
623 void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
624 {
625         m_uniformSetup.setup(*this, constCoords);
626 }
627
628 void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
629 {
630         #define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
631
632         switch(type)
633         {
634                 // Bool
635                 UNIFORM_CASE(UB_FALSE,  0);
636                 UNIFORM_CASE(UB_TRUE,   1);
637
638                 // BVec4
639                 UNIFORM_CASE(UB4_FALSE, tcu::Vec4(0));
640                 UNIFORM_CASE(UB4_TRUE,  tcu::Vec4(1));
641
642                 // Integer
643                 UNIFORM_CASE(UI_ZERO,   0);
644                 UNIFORM_CASE(UI_ONE,    1);
645                 UNIFORM_CASE(UI_TWO,    2);
646                 UNIFORM_CASE(UI_THREE,  3);
647                 UNIFORM_CASE(UI_FOUR,   4);
648                 UNIFORM_CASE(UI_FIVE,   5);
649                 UNIFORM_CASE(UI_SIX,    6);
650                 UNIFORM_CASE(UI_SEVEN,  7);
651                 UNIFORM_CASE(UI_EIGHT,  8);
652                 UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
653
654                 // IVec2
655                 UNIFORM_CASE(UI2_MINUS_ONE, tcu::IVec2(-1));
656                 UNIFORM_CASE(UI2_ZERO,          tcu::IVec2(0));
657                 UNIFORM_CASE(UI2_ONE,           tcu::IVec2(1));
658                 UNIFORM_CASE(UI2_TWO,           tcu::IVec2(2));
659                 UNIFORM_CASE(UI2_THREE,         tcu::IVec2(3));
660                 UNIFORM_CASE(UI2_FOUR,          tcu::IVec2(4));
661                 UNIFORM_CASE(UI2_FIVE,          tcu::IVec2(5));
662
663                 // IVec3
664                 UNIFORM_CASE(UI3_MINUS_ONE,     tcu::IVec3(-1));
665                 UNIFORM_CASE(UI3_ZERO,          tcu::IVec3(0));
666                 UNIFORM_CASE(UI3_ONE,           tcu::IVec3(1));
667                 UNIFORM_CASE(UI3_TWO,           tcu::IVec3(2));
668                 UNIFORM_CASE(UI3_THREE,         tcu::IVec3(3));
669                 UNIFORM_CASE(UI3_FOUR,          tcu::IVec3(4));
670                 UNIFORM_CASE(UI3_FIVE,          tcu::IVec3(5));
671
672                 // IVec4
673                 UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
674                 UNIFORM_CASE(UI4_ZERO,          tcu::IVec4(0));
675                 UNIFORM_CASE(UI4_ONE,           tcu::IVec4(1));
676                 UNIFORM_CASE(UI4_TWO,           tcu::IVec4(2));
677                 UNIFORM_CASE(UI4_THREE,         tcu::IVec4(3));
678                 UNIFORM_CASE(UI4_FOUR,          tcu::IVec4(4));
679                 UNIFORM_CASE(UI4_FIVE,          tcu::IVec4(5));
680
681                 // Float
682                 UNIFORM_CASE(UF_ZERO,           0.0f);
683                 UNIFORM_CASE(UF_ONE,            1.0f);
684                 UNIFORM_CASE(UF_TWO,            2.0f);
685                 UNIFORM_CASE(UF_THREE,          3.0f);
686                 UNIFORM_CASE(UF_FOUR,           4.0f);
687                 UNIFORM_CASE(UF_FIVE,           5.0f);
688                 UNIFORM_CASE(UF_SIX,            6.0f);
689                 UNIFORM_CASE(UF_SEVEN,          7.0f);
690                 UNIFORM_CASE(UF_EIGHT,          8.0f);
691
692                 UNIFORM_CASE(UF_HALF,           1.0f / 2.0f);
693                 UNIFORM_CASE(UF_THIRD,          1.0f / 3.0f);
694                 UNIFORM_CASE(UF_FOURTH,         1.0f / 4.0f);
695                 UNIFORM_CASE(UF_FIFTH,          1.0f / 5.0f);
696                 UNIFORM_CASE(UF_SIXTH,          1.0f / 6.0f);
697                 UNIFORM_CASE(UF_SEVENTH,        1.0f / 7.0f);
698                 UNIFORM_CASE(UF_EIGHTH,         1.0f / 8.0f);
699
700                 // Vec2
701                 UNIFORM_CASE(UV2_MINUS_ONE,     tcu::Vec2(-1.0f));
702                 UNIFORM_CASE(UV2_ZERO,          tcu::Vec2(0.0f));
703                 UNIFORM_CASE(UV2_ONE,           tcu::Vec2(1.0f));
704                 UNIFORM_CASE(UV2_TWO,           tcu::Vec2(2.0f));
705                 UNIFORM_CASE(UV2_THREE,         tcu::Vec2(3.0f));
706
707                 UNIFORM_CASE(UV2_HALF,          tcu::Vec2(1.0f / 2.0f));
708
709                 // Vec3
710                 UNIFORM_CASE(UV3_MINUS_ONE,     tcu::Vec3(-1.0f));
711                 UNIFORM_CASE(UV3_ZERO,          tcu::Vec3(0.0f));
712                 UNIFORM_CASE(UV3_ONE,           tcu::Vec3(1.0f));
713                 UNIFORM_CASE(UV3_TWO,           tcu::Vec3(2.0f));
714                 UNIFORM_CASE(UV3_THREE,         tcu::Vec3(3.0f));
715
716                 UNIFORM_CASE(UV3_HALF,          tcu::Vec3(1.0f / 2.0f));
717
718                 // Vec4
719                 UNIFORM_CASE(UV4_MINUS_ONE,     tcu::Vec4(-1.0f));
720                 UNIFORM_CASE(UV4_ZERO,          tcu::Vec4(0.0f));
721                 UNIFORM_CASE(UV4_ONE,           tcu::Vec4(1.0f));
722                 UNIFORM_CASE(UV4_TWO,           tcu::Vec4(2.0f));
723                 UNIFORM_CASE(UV4_THREE,         tcu::Vec4(3.0f));
724
725                 UNIFORM_CASE(UV4_HALF,          tcu::Vec4(1.0f / 2.0f));
726
727                 UNIFORM_CASE(UV4_BLACK,         tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
728                 UNIFORM_CASE(UV4_GRAY,          tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
729                 UNIFORM_CASE(UV4_WHITE,         tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
730
731                 default:
732                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
733                         break;
734         }
735
736         #undef UNIFORM_CASE
737 }
738
739 const tcu::IVec2 ShaderRenderCaseInstance::getViewportSize (void) const
740 {
741         return tcu::IVec2(de::min(m_renderSize.x(), MAX_RENDER_WIDTH),
742                                           de::min(m_renderSize.y(), MAX_RENDER_HEIGHT));
743 }
744
745 Move<VkImage> ShaderRenderCaseInstance::createImage2D (const tcu::Texture2D& texture, const VkFormat format)
746 {
747         const VkDevice                  vkDevice                        = m_context.getDevice();
748         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
749         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
750
751         const VkImageCreateInfo imageCreateInfo =
752         {
753                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                            // VkStructureType                      sType;
754                 DE_NULL,                                                                                                        // const void*                          pnext;
755                 VK_IMAGE_TYPE_2D,                                                                                       // VkImageType                          imageType;
756                 format,                                                                                                         // VkFormat                                     format;
757                 { texture.getWidth(), texture.getHeight(), 1 },                         // VkExtend3D                           extent;
758                 1u,                                                                                                                     // deUint32                                     mipLevels;
759                 1u,                                                                                                                     // deUint32                                     arraySize;
760                 1u,                                                                                                                     // deUint32                                     samples;
761                 VK_IMAGE_TILING_LINEAR,                                                                         // VkImageTiling                        tiling;
762                 VK_IMAGE_USAGE_SAMPLED_BIT,                                                                     // VkImageUsageFlags            usage;
763                 0,                                                                                                                      // VkImageCreateFlags           flags;
764                 VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                        sharingMode;
765                 1,                                                                                                                      // deuint32                                     queueFamilyCount;
766                 &queueFamilyIndex,                                                                                      // const deUint32*                      pQueueFamilyIndices;
767                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                initialLayout;
768         };
769
770         Move<VkImage> vkTexture = createImage(vk, vkDevice, &imageCreateInfo);
771         return vkTexture;
772 }
773
774 void ShaderRenderCaseInstance::useSampler2D (deUint32 bindingLocation, deUint32 textureID)
775 {
776         const VkDevice                          vkDevice                        = m_context.getDevice();
777         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
778
779         DE_ASSERT(textureID < m_textures.size());
780
781         const TextureBinding&           textureBinding          = m_textures[textureID];
782         const tcu::Texture2D*           refTexture                      = textureBinding.get2D();
783         const tcu::Sampler&                     refSampler                      = textureBinding.getSampler();
784         const VkFormat                          format                          = refTexture->getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
785                                                                                                                 ? VK_FORMAT_R8G8B8A8_UNORM
786                                                                                                                 : VK_FORMAT_R8G8B8_UNORM;
787
788         DE_ASSERT(refTexture != DE_NULL);
789         // Create & alloc the image
790         Move<VkImage> vkTexture(createImage2D(*refTexture, format));
791
792         // Allocate and bind color image memory
793         de::MovePtr<Allocation> allocation                              = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
794         VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
795
796         const VkImageSubresource subres =
797         {
798                 VK_IMAGE_ASPECT_COLOR,                                                  // VkImageAspect                aspect;
799                 0u,                                                                                             // deUint32                             mipLevel;
800                 0u                                                                                              // deUint32                             arraySlice
801         };
802
803         VkSubresourceLayout layout;
804         VK_CHECK(vk.getImageSubresourceLayout(vkDevice, *vkTexture, &subres, &layout));
805
806         void *imagePtr;
807         VK_CHECK(vk.mapMemory(vkDevice, allocation->getMemory(), allocation->getOffset(), layout.size, 0u, &imagePtr));
808
809         tcu::ConstPixelBufferAccess access = refTexture->getLevel(0);
810         tcu::PixelBufferAccess destAccess(refTexture->getFormat(), refTexture->getWidth(), refTexture->getHeight(), 1, imagePtr);
811
812         tcu::copy(destAccess, access);
813
814         const vk::VkMappedMemoryRange range =
815         {
816                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,                  // VkStructureType      sType;
817                 DE_NULL,                                                                                // const void*          pNext;
818                 allocation->getMemory(),                                                // VkDeviceMemory       mem;
819                 0,                                                                                              // VkDeviceSize         offset;
820                 layout.size,                                                                    // VkDeviceSize         size;
821         };
822
823         VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range));
824         vk.unmapMemory(vkDevice, allocation->getMemory());
825
826
827         // Create sampler
828         const VkSamplerCreateInfo       samplerParams           =
829         {
830                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
831                 DE_NULL,
832                 getVkTexFilter(refSampler.magFilter),
833                 getVkTexFilter(refSampler.minFilter),
834                 getVkTexMipmapMode(refSampler.minFilter),
835                 getVkWrapMode(refSampler.wrapS),
836                 getVkWrapMode(refSampler.wrapT),
837                 getVkWrapMode(refSampler.wrapR),
838                 refSampler.lodThreshold,
839                 1,
840                 (refSampler.compare != tcu::Sampler::COMPAREMODE_NONE),
841                 getVkCompareMode(refSampler.compare),
842                 0.0f,
843                 0.0f,
844                 VK_BORDER_COLOR_INT_OPAQUE_WHITE,
845                 VK_FALSE,
846         };
847
848         Move<VkSampler>                         sampler                         = createSampler(vk, vkDevice, &samplerParams);
849
850         const VkImageViewCreateInfo     viewParams                      =
851         {
852                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                      sType;
853                 NULL,                                                                           // const voide*                         pNexŧ;
854                 *vkTexture,                                                                     // VkImage                                      image;
855                 VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                      viewType;
856                 format,                                                                         // VkFormat                                     format;
857                 {
858                         VK_CHANNEL_SWIZZLE_R,                   // VkChannelSwizzle             r;
859                         VK_CHANNEL_SWIZZLE_G,                   // VkChannelSwizzle             g;
860                         VK_CHANNEL_SWIZZLE_B,                   // VkChannelSwizzle             b;
861                         VK_CHANNEL_SWIZZLE_A                    // VkChannelSwizzle             a;
862                 },                                                                                      // VkChannelMapping                     channels;
863                 {
864                         VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
865                         0,                                                              // deUint32                             baseMipLevel;
866                         1,                                                              // deUint32                             mipLevels;
867                         0,                                                              // deUint32                             baseArraySlice;
868                         1                                                               // deUint32                             arraySize;
869                 },                                                                                      // VkImageSubresourceRange      subresourceRange;
870                 0u                                                                                                      // VkImageViewCreateFlags       flags;
871         };
872
873         Move<VkImageView>                       imageView                       = createImageView(vk, vkDevice, &viewParams);
874
875         const vk::VkDescriptorInfo      descriptor                      =
876         {
877                 0,                                                                                      // VkBufferView                         bufferView;
878                 sampler.get(),                                                          // VkSampler                            sampler;
879                 imageView.get(),                                                        // VkImageView                          imageView;
880                 VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        imageLayout;
881                 {0, 0, 0},                                                                                      // VkDescriptorBufferInfo       bufferInfo;
882         };
883
884         de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
885         uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
886         uniform->descriptor = descriptor;
887         uniform->location = bindingLocation;
888         uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
889         uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
890         uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
891         uniform->alloc = AllocationSp(new de::UniquePtr<vk::Allocation>(allocation));
892
893         m_descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_FRAGMENT_BIT, &uniform->descriptor.sampler);
894         m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
895
896         m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
897 }
898
899 void ShaderRenderCaseInstance::setupDefaultInputs (const QuadGrid& quadGrid)
900 {
901         /* Configuration of the vertex input attributes:
902                 a_position   is at location 0
903                 a_coords     is at location 1
904                 a_unitCoords is at location 2
905                 a_one        is at location 3
906
907           User attributes starts from at the location 4.
908         */
909         addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
910         addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
911         addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
912         addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
913
914         static const struct
915         {
916                 BaseAttributeType       type;
917                 int                                     userNdx;
918         } userAttributes[] =
919         {
920                 { A_IN0, 0 },
921                 { A_IN1, 1 },
922                 { A_IN2, 2 },
923                 { A_IN3, 3 }
924         };
925
926         static const struct
927         {
928                 BaseAttributeType       matrixType;
929                 int                                     numCols;
930                 int                                     numRows;
931         } matrices[] =
932         {
933                 { MAT2,         2, 2 },
934                 { MAT2x3,       2, 3 },
935                 { MAT2x4,       2, 4 },
936                 { MAT3x2,       3, 2 },
937                 { MAT3,         3, 3 },
938                 { MAT3x4,       3, 4 },
939                 { MAT4x2,       4, 2 },
940                 { MAT4x3,       4, 3 },
941                 { MAT4,         4, 4 }
942         };
943
944         for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
945         {
946                 for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
947                 {
948                         if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
949                                 continue;
950
951                         addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
952                 }
953
954                 for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
955                 {
956
957                         if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
958                                 continue;
959
960                         const int numCols = matrices[matNdx].numCols;
961
962                         for (int colNdx = 0; colNdx < numCols; colNdx++)
963                         {
964                                 addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, 4 * sizeof(float), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
965                         }
966                 }
967         }
968 }
969
970 void ShaderRenderCaseInstance::render (tcu::Surface& result, const QuadGrid& quadGrid)
971 {
972         const VkDevice                          vkDevice                        = m_context.getDevice();
973         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
974         const VkQueue                           queue                           = m_context.getUniversalQueue();
975         const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
976
977         // Create color image
978         {
979                 const VkImageCreateInfo colorImageParams =
980                 {
981                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType              sType;
982                         DE_NULL,                                                                                                                                        // const void*                  pNext;
983                         VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                  imageType;
984                         m_colorFormat,                                                                                                                          // VkFormat                             format;
985                         { m_renderSize.x(), m_renderSize.y(), 1u },                                                                     // VkExtent3D                   extent;
986                         1u,                                                                                                                                                     // deUint32                             mipLevels;
987                         1u,                                                                                                                                                     // deUint32                             arraySize;
988                         1u,                                                                                                                                                     // deUint32                             samples;
989                         VK_IMAGE_TILING_OPTIMAL,                                                                                                        // VkImageTiling                tiling;
990                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT,       // VkImageUsageFlags    usage;
991                         0u,                                                                                                                                                     // VkImageCreateFlags   flags;
992                         VK_SHARING_MODE_EXCLUSIVE,                                                                                                      // VkSharingMode                sharingMode;
993                         1u,                                                                                                                                                     // deUint32                             queueFamilyCount;
994                         &queueFamilyIndex,                                                                                                                      // const deUint32*              pQueueFamilyIndices;
995                         VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                initialLayout;
996                 };
997
998                 m_colorImage = createImage(vk, vkDevice, &colorImageParams);
999
1000                 // Allocate and bind color image memory
1001                 m_colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::HostVisible);
1002                 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), 0));
1003         }
1004
1005         // Create color attachment view
1006         {
1007                 const VkImageViewCreateInfo colorImageViewParams =
1008                 {
1009                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                       // VkStructureType                      sType;
1010                         DE_NULL,                                                                                        // const void*                          pNext;
1011                         *m_colorImage,                                                                          // VkImage                                      image;
1012                         VK_IMAGE_VIEW_TYPE_2D,                                                          // VkImageViewType                      viewType;
1013                         m_colorFormat,                                                                          // VkFormat                                     format;
1014                         {
1015                                 VK_CHANNEL_SWIZZLE_R,                   // VkChannelSwizzle             r;
1016                                 VK_CHANNEL_SWIZZLE_G,                   // VkChannelSwizzle             g;
1017                                 VK_CHANNEL_SWIZZLE_B,                   // VkChannelSwizzle             b;
1018                                 VK_CHANNEL_SWIZZLE_A                    // VkChannelSwizzle             a;
1019                         },                                                                                                      // VkChannelMapping                     channels;
1020                         {
1021                                 VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
1022                                 0,                                                              // deUint32                             baseMipLevel;
1023                                 1,                                                              // deUint32                             mipLevels;
1024                                 0,                                                              // deUint32                             baseArraySlice;
1025                                 1                                                               // deUint32                             arraySize;
1026                         },                                                                                                      // VkImageSubresourceRange      subresourceRange;
1027                         0u                                                                                                      // VkImageViewCreateFlags       flags;
1028                 };
1029
1030                 m_colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
1031         }
1032
1033         // Create render pass
1034         {
1035                 const VkAttachmentDescription colorAttachmentDescription =
1036                 {
1037                         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,                       // VkStructureType                              sType;
1038                         DE_NULL,                                                                                        // const void*                                  pNext;
1039                         m_colorFormat,                                                                          // VkFormat                                             format;
1040                         1u,                                                                                                     // deUint32                                             samples;
1041                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                   loadOp;
1042                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                  storeOp;
1043                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                   stencilLoadOp;
1044                         VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                  stencilStoreOp;
1045                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                initialLayout;
1046                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                finalLayout;
1047                         0u,                                                                                                     // VkAttachmentDescriptorFlags  flags;
1048                 };
1049
1050                 const VkAttachmentDescription attachments[1] =
1051                 {
1052                         colorAttachmentDescription
1053                 };
1054
1055                 const VkAttachmentReference colorAttachmentReference =
1056                 {
1057                         0u,                                                                                                     // deUint32                     attachment;
1058                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
1059                 };
1060
1061                 const VkSubpassDescription subpassDescription =
1062                 {
1063                         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,                          // VkStructureType                              sType;
1064                         DE_NULL,                                                                                        // constvoid*                                   pNext;
1065                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                  pipelineBindPoint;
1066                         0u,                                                                                                     // VkSubpassDescriptionFlags    flags;
1067                         0u,                                                                                                     // deUint32                                             inputCount;
1068                         DE_NULL,                                                                                        // constVkAttachmentReference*  pInputAttachments;
1069                         1u,                                                                                                     // deUint32                                             colorCount;
1070                         &colorAttachmentReference,                                                      // constVkAttachmentReference*  pColorAttachments;
1071                         DE_NULL,                                                                                        // constVkAttachmentReference*  pResolveAttachments;
1072                         { ~0u, VK_IMAGE_LAYOUT_GENERAL },                                       // VkAttachmentReference                depthStencilAttachment;
1073                         0u,                                                                                                     // deUint32                                             preserveCount;
1074                         DE_NULL                                                                                         // constVkAttachmentReference*  pPreserveAttachments;
1075                 };
1076
1077                 const VkRenderPassCreateInfo renderPassParams =
1078                 {
1079                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
1080                         DE_NULL,                                                                                        // const void*                                          pNext;
1081                         1u,                                                                                                     // deUint32                                                     attachmentCount;
1082                         attachments,                                                                            // const VkAttachmentDescription*       pAttachments;
1083                         1u,                                                                                                     // deUint32                                                     subpassCount;
1084                         &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
1085                         0u,                                                                                                     // deUint32                                                     dependencyCount;
1086                         DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
1087                 };
1088
1089                 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
1090         }
1091
1092         // Create framebuffer
1093         {
1094                 const VkFramebufferCreateInfo framebufferParams =
1095                 {
1096                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                              sType;
1097                         DE_NULL,                                                                                        // const void*                                  pNext;
1098                         *m_renderPass,                                                                          // VkRenderPass                                 renderPass;
1099                         1u,                                                                                                     // deUint32                                             attachmentCount;
1100                         &*m_colorImageView,                                                                     // const VkImageView*                   pAttachments;
1101                         (deUint32)m_renderSize.x(),                                                     // deUint32                                             width;
1102                         (deUint32)m_renderSize.y(),                                                     // deUint32                                             height;
1103                         1u                                                                                                      // deUint32                                             layers;
1104                 };
1105
1106                 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1107         }
1108
1109         // Create descriptors
1110         {
1111                 setupUniforms(quadGrid.getConstCoords());
1112
1113                 m_descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
1114                 m_descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1u);
1115                 m_descriptorSet = allocDescriptorSet(vk, vkDevice, *m_descriptorPool, VK_DESCRIPTOR_SET_USAGE_STATIC, *m_descriptorSetLayout);
1116
1117                 for(deUint32 i = 0; i < m_uniformInfos.size(); i++)
1118                 {
1119                         const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1120                         deUint32 location = uniformInfo->location;
1121                         m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &uniformInfo->descriptor);
1122                 }
1123
1124                 m_descriptorSetUpdateBuilder.update(vk, vkDevice);
1125         }
1126
1127         // Create pipeline layout
1128         {
1129                 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1130                 {
1131                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
1132                         DE_NULL,                                                                                        // const void*                                  pNext;
1133                         1u,                                                                                                     // deUint32                                             descriptorSetCount;
1134                         &*m_descriptorSetLayout,                                                        // const VkDescriptorSetLayout* pSetLayouts;
1135                         0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
1136                         DE_NULL                                                                                         // const VkPushConstantRange*   pPushConstantRanges;
1137                 };
1138
1139                 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1140         }
1141
1142         // Create shaders
1143         {
1144                 m_vertexShaderModule    = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
1145                 m_fragmentShaderModule  = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
1146
1147                 const VkShaderCreateInfo vertexShaderParams =
1148                 {
1149                         VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,                   // VkStructureType              sType;
1150                         DE_NULL,                                                                                // const void*                  pNext;
1151                         *m_vertexShaderModule,                                                  // VkShaderModule               module;
1152                         "main",                                                                                 // const char*                  pName;
1153                         0u,                                                                                             // VkShaderCreateFlags  flags;
1154                         VK_SHADER_STAGE_VERTEX,                                                 // VkShaderStage                stage;
1155                 };
1156
1157                 const VkShaderCreateInfo fragmentShaderParams =
1158                 {
1159                         VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,                   // VkStructureType              sType;
1160                         DE_NULL,                                                                                // const void*                  pNext;
1161                         *m_fragmentShaderModule,                                                // VkShaderModule               module;
1162                         "main",                                                                                 // const char*                  pName;
1163                         0u,                                                                                             // VkShaderCreateFlags  flags;
1164                         VK_SHADER_STAGE_FRAGMENT,                                               // VkShaderStage                stage;
1165                 };
1166
1167                 m_vertexShader  = createShader(vk, vkDevice, &vertexShaderParams);
1168                 m_fragmentShader= createShader(vk, vkDevice, &fragmentShaderParams);
1169         }
1170
1171         // Create pipeline
1172         {
1173                 const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
1174                 {
1175                         {
1176                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                              sType;
1177                                 DE_NULL,                                                                                                        // const void*                                  pNext;
1178                                 VK_SHADER_STAGE_VERTEX,                                                                         // VkShaderStage                                stage;
1179                                 *m_vertexShader,                                                                                        // VkShader                                             shader;
1180                                 DE_NULL                                                                                                         // const VkSpecializationInfo*  pSpecializationInfo;
1181                         },
1182                         {
1183                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                              sType;
1184                                 DE_NULL,                                                                                                        // const void*                                  pNext;
1185                                 VK_SHADER_STAGE_FRAGMENT,                                                                       // VkShaderStage                                stage;
1186                                 *m_fragmentShader,                                                                                      // VkShader                                             shader;
1187                                 DE_NULL                                                                                                         // const VkSpecializationInfo*  pSpecializationInfo;
1188                         }
1189                 };
1190
1191                 // Add base attributes
1192
1193                 // Add test case specific attributes
1194                 if (m_attribFunc)
1195                         m_attribFunc(*this, quadGrid.getNumVertices());
1196
1197                 setupDefaultInputs(quadGrid);
1198
1199                 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1200                 {
1201                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
1202                         DE_NULL,                                                                                                                // const void*                                                          pNext;
1203                         (deUint32)m_vertexBindingDescription.size(),                                    // deUint32                                                                     bindingCount;
1204                         &m_vertexBindingDescription[0],                                                                 // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
1205                         (deUint32)m_vertexattributeDescription.size(),                                  // deUint32                                                                     attributeCount;
1206                         &m_vertexattributeDescription[0],                                                               // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
1207                 };
1208
1209                 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1210                 {
1211                         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType              sType;
1212                         DE_NULL,                                                                                                                // const void*                  pNext;
1213                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                                    // VkPrimitiveTopology  topology;
1214                         false                                                                                                                   // VkBool32                             primitiveRestartEnable;
1215                 };
1216
1217                 const VkViewport viewport =
1218                 {
1219                         0.0f,                                           // float        originX;
1220                         0.0f,                                           // float        originY;
1221                         (float)m_renderSize.x(),        // float        width;
1222                         (float)m_renderSize.y(),        // float        height;
1223                         0.0f,                                           // float        minDepth;
1224                         1.0f                                            // float        maxDepth;
1225                 };
1226
1227                 const VkRect2D scissor =
1228                 {
1229                         {
1230                                 0u,                                     // deUint32     x;
1231                                 0u,                                     // deUint32     y;
1232                         },                                                      // VkOffset2D   offset;
1233                         {
1234                                 m_renderSize.x(),       // deUint32     width;
1235                                 m_renderSize.y(),       // deUint32     height;
1236                         },                                                      // VkExtent2D   extent;
1237                 };
1238
1239                 const VkPipelineViewportStateCreateInfo viewportStateParams =
1240                 {
1241                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType              sType;
1242                         DE_NULL,                                                                                                                // const void*                  pNext;
1243                         1u,                                                                                                                             // deUint32                             viewportCount;
1244                         &viewport,                                                                                                              // const VkViewport*    pViewports;
1245                         1u,                                                                                                                             // deUint32                             scissorsCount;
1246                         &scissor,                                                                                                               // const VkRect2D*              pScissors;
1247                 };
1248
1249                 const VkPipelineRasterStateCreateInfo rasterStateParams =
1250                 {
1251                         VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO,                    // VkStructureType      sType;
1252                         DE_NULL,                                                                                                                // const void*          pNext;
1253                         false,                                                                                                                  // VkBool32                     depthClipEnable;
1254                         false,                                                                                                                  // VkBool32                     rasterizerDiscardEnable;
1255                         VK_FILL_MODE_SOLID,                                                                                             // VkFillMode           fillMode;
1256                         VK_CULL_MODE_NONE,                                                                                              // VkCullMode           cullMode;
1257                         VK_FRONT_FACE_CCW,                                                                                              // VkFrontFace          frontFace;
1258                         false,                                                                                                                  // VkBool32                     depthBiasEnable;
1259                         0.0f,                                                                                                                   // float                        depthBias;
1260                         0.0f,                                                                                                                   // float                        depthBiasClamp;
1261                         0.0f,                                                                                                                   // float                        slopeScaledDepthBias;
1262                         1.0f,                                                                                                                   // float                        lineWidth;
1263                 };
1264
1265                 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1266                 {
1267                         false,                                                                                                                                          // VkBool32                     blendEnable;
1268                         VK_BLEND_ONE,                                                                                                                           // VkBlend                      srcBlendColor;
1269                         VK_BLEND_ZERO,                                                                                                                          // VkBlend                      destBlendColor;
1270                         VK_BLEND_OP_ADD,                                                                                                                        // VkBlendOp            blendOpColor;
1271                         VK_BLEND_ONE,                                                                                                                           // VkBlend                      srcBlendAlpha;
1272                         VK_BLEND_ZERO,                                                                                                                          // VkBlend                      destBlendAlpha;
1273                         VK_BLEND_OP_ADD,                                                                                                                        // VkBlendOp            blendOpAlpha;
1274                         VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT | VK_CHANNEL_A_BIT       // VkChannelFlags       channelWriteMask;
1275                 };
1276
1277                 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1278                 {
1279                         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
1280                         DE_NULL,                                                                                                        // const void*                                                                  pNext;
1281                         false,                                                                                                          // VkBool32                                                                             alphaToCoverageEnable;
1282                         false,                                                                                                          // VkBool32                                                                             alphaToOneEnable;
1283                         false,                                                                                                          // VkBool32                                                                             logicOpEnable;
1284                         VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
1285                         1u,                                                                                                                     // deUint32                                                                             attachmentCount;
1286                         &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
1287                         { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConst[4];
1288                 };
1289
1290                 const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
1291                 {
1292                         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,           // VkStructureType                              sType;
1293                         DE_NULL,                                                                                                        // const void*                                  pNext;
1294                         0u,                                                                                                                     // deUint32                                             dynamicStateCount;
1295                         DE_NULL                                                                                                         // const VkDynamicState*                pDynamicStates;
1296                 };
1297
1298                 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1299                 {
1300                         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
1301                         DE_NULL,                                                                                        // const void*                                                                          pNext;
1302                         2u,                                                                                                     // deUint32                                                                                     stageCount;
1303                         shaderStageParams,                                                                      // const VkPipelineShaderStageCreateInfo*                       pStages;
1304                         &vertexInputStateParams,                                                        // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
1305                         &inputAssemblyStateParams,                                                      // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
1306                         DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
1307                         &viewportStateParams,                                                           // const VkPipelineViewportStateCreateInfo*                     pViewportState;
1308                         &rasterStateParams,                                                                     // const VkPipelineRasterStateCreateInfo*                       pRasterState;
1309                         DE_NULL,                                                                                        // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
1310                         DE_NULL,                                                                                        // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
1311                         &colorBlendStateParams,                                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
1312                         &dynamicStateInfo,                                                                      // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
1313                         0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
1314                         *m_pipelineLayout,                                                                      // VkPipelineLayout                                                                     layout;
1315                         *m_renderPass,                                                                          // VkRenderPass                                                                         renderPass;
1316                         0u,                                                                                                     // deUint32                                                                                     subpass;
1317                         0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
1318                         0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
1319                 };
1320
1321                 m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1322         }
1323
1324         // Create vertex indices buffer
1325         {
1326                 const VkDeviceSize indiceBufferSize = quadGrid.getNumTriangles() * 3 * sizeof(deUint16);
1327                 const VkBufferCreateInfo indiceBufferParams =
1328                 {
1329                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
1330                         DE_NULL,                                                                        // const void*                  pNext;
1331                         indiceBufferSize,                                                       // VkDeviceSize                 size;
1332                         VK_BUFFER_USAGE_INDEX_BUFFER_BIT,                       // VkBufferUsageFlags   usage;
1333                         0u,                                                                                     // VkBufferCreateFlags  flags;
1334                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
1335                         1u,                                                                                     // deUint32                             queueFamilyCount;
1336                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
1337                 };
1338
1339                 m_indiceBuffer          = createBuffer(vk, vkDevice, &indiceBufferParams);
1340                 m_indiceBufferAlloc     = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indiceBuffer), MemoryRequirement::HostVisible);
1341
1342                 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indiceBuffer, m_indiceBufferAlloc->getMemory(), 0));
1343
1344                 // Load vertice indices into buffer
1345                 void* bufferPtr;
1346                 VK_CHECK(vk.mapMemory(vkDevice, m_indiceBufferAlloc->getMemory(), 0, indiceBufferSize, 0, &bufferPtr));
1347                 deMemcpy(bufferPtr, quadGrid.getIndices(), indiceBufferSize);
1348                 vk.unmapMemory(vkDevice, m_indiceBufferAlloc->getMemory());
1349         }
1350
1351         // Create command pool
1352         {
1353                 const VkCmdPoolCreateInfo cmdPoolParams =
1354                 {
1355                         VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,         // VkStructureType              sType;
1356                         DE_NULL,                                                                        // const void*                  pNext;
1357                         queueFamilyIndex,                                                       // deUint32                             queueFamilyIndex;
1358                         VK_CMD_POOL_CREATE_TRANSIENT_BIT                        // VkCmdPoolCreateFlags flags;
1359                 };
1360
1361                 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1362         }
1363
1364         // Create command buffer
1365         {
1366                 const VkCmdBufferCreateInfo cmdBufferParams =
1367                 {
1368                         VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,       // VkStructureType                      sType;
1369                         DE_NULL,                                                                        // const void*                          pNext;
1370                         *m_cmdPool,                                                                     // VkCmdPool                            cmdPool;
1371                         VK_CMD_BUFFER_LEVEL_PRIMARY,                            // VkCmdBufferLevel                     level;
1372                         0u                                                                                      // VkCmdBufferCreateFlags       flags;
1373                 };
1374
1375                 const VkCmdBufferBeginInfo cmdBufferBeginInfo =
1376                 {
1377                         VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,        // VkStructureType                      sType;
1378                         DE_NULL,                                                                        // const void*                          pNext;
1379                         0u,                                                                                     // VkCmdBufferOptimizeFlags     flags;
1380                         DE_NULL,                                                                        // VkRenderPass                         renderPass;
1381                         0u,                                                                                     // deUint32                                     subpass;
1382                         DE_NULL                                                                         // VkFramebuffer                        framebuffer;
1383                 };
1384
1385                 const VkClearValue clearValues =
1386                 {
1387                         m_clearColor.x(),
1388                         m_clearColor.y(),
1389                         m_clearColor.z(),
1390                         m_clearColor.w(),
1391                 };
1392
1393                 const VkRenderPassBeginInfo renderPassBeginInfo =
1394                 {
1395                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO        ,       // VkStructureType              sType;
1396                         DE_NULL,                                                                                // const void*                  pNext;
1397                         *m_renderPass,                                                                  // VkRenderPass                 renderPass;
1398                         *m_framebuffer,                                                                 // VkFramebuffer                framebuffer;
1399                         { 0, 0, m_renderSize.x(), m_renderSize.y() },   // VkRect2D                             renderArea;
1400                         1,                                                                                              // deUint32                             clearValueCount;
1401                         &clearValues,                                                                   // const VkClearValue*  pClearValues;
1402                 };
1403
1404                 m_cmdBuffer = createCommandBuffer(vk, vkDevice, &cmdBufferParams);
1405
1406                 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1407
1408                 // Add texture barriers
1409                 std::vector<VkImageMemoryBarrier> barriers;
1410                 std::vector<void*> barrierPtrs;
1411
1412                 for(deUint32 i = 0; i < m_uniformInfos.size(); i++)
1413                 {
1414                         const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1415
1416                         if (uniformInfo->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1417                         {
1418                                 continue;
1419                         }
1420
1421                         const SamplerUniform* sampler = static_cast<const SamplerUniform*>(uniformInfo);
1422
1423                         VkImageMemoryBarrier textureBarrier =
1424                         {
1425                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1426                                 DE_NULL,
1427                                 VK_MEMORY_OUTPUT_HOST_WRITE_BIT | VK_MEMORY_OUTPUT_TRANSFER_BIT,
1428                                 0,
1429                                 VK_IMAGE_LAYOUT_UNDEFINED,
1430                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1431                                 queueFamilyIndex,
1432                                 queueFamilyIndex,
1433                                 sampler->image->get(),
1434                                 {
1435                                         VK_IMAGE_ASPECT_COLOR_BIT,
1436                                         0,
1437                                         1,
1438                                         0,
1439                                         0
1440                                 }
1441                         };
1442
1443                         barriers.push_back(textureBarrier);
1444                         barrierPtrs.push_back((void*)&barriers.back());
1445                 }
1446
1447                 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, (deUint32)barrierPtrs.size(), (const void * const*)&barrierPtrs[0]);
1448
1449                 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_RENDER_PASS_CONTENTS_INLINE);
1450
1451                 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1452                 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
1453                 vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
1454
1455
1456                 const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
1457                 const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
1458
1459                 std::vector<VkBuffer> buffers(numberOfVertexAttributes);
1460                 for (size_t i = 0; i < numberOfVertexAttributes; i++)
1461                 {
1462                         buffers[i] = m_vertexBuffers[i].get()->get();
1463                 }
1464
1465                 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
1466                 vk.cmdDrawIndexed(*m_cmdBuffer, quadGrid.getNumTriangles() * 3, 1, 0, 0, 0);
1467
1468                 vk.cmdEndRenderPass(*m_cmdBuffer);
1469                 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1470         }
1471
1472         // Create fence
1473         {
1474                 const VkFenceCreateInfo fenceParams =
1475                 {
1476                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
1477                         DE_NULL,                                                                // const void*                  pNext;
1478                         0u                                                                              // VkFenceCreateFlags   flags;
1479                 };
1480                 m_fence = createFence(vk, vkDevice, &fenceParams);
1481         }
1482
1483         // Execute Draw
1484         {
1485                 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1486                 VK_CHECK(vk.queueSubmit(queue, 1, &m_cmdBuffer.get(), *m_fence));
1487                 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1488         }
1489
1490         // Read back the result
1491         {
1492                 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32) * m_renderSize.x() * m_renderSize.y());
1493                 const VkBufferCreateInfo readImageBufferParams   =
1494                 {
1495                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           //  VkStructureType             sType;
1496                         DE_NULL,                                                                        //  const void*                 pNext;
1497                         imageSizeBytes,                                                         //  VkDeviceSize                size;
1498                         VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT,       //  VkBufferUsageFlags  usage;
1499                         0u,                                                                                     //  VkBufferCreateFlags flags;
1500                         VK_SHARING_MODE_EXCLUSIVE,                                      //  VkSharingMode               sharingMode;
1501                         1u,                                                                                     //  deUint32                    queueFamilyCount;
1502                         &queueFamilyIndex,                                                      //  const deUint32*             pQueueFamilyIndices;
1503                 };
1504                 const Unique<VkBuffer> readImageBuffer(createBuffer(vk, vkDevice, &readImageBufferParams));
1505                 const de::UniquePtr<Allocation> readImageBufferMemory(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
1506
1507                 VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
1508
1509
1510                 // Copy image to buffer
1511                 const VkCmdBufferCreateInfo cmdBufferParams =
1512                 {
1513                         VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,       // VkStructureType                      sType;
1514                         DE_NULL,                                                                        // const void*                          pNext;
1515                         *m_cmdPool,                                                                     // VkCmdPool                            cmdPool;
1516                         VK_CMD_BUFFER_LEVEL_PRIMARY,                            // VkCmdBufferLevel                     level;
1517                         0u                                                                                      // VkCmdBufferCreateFlags       flags;
1518                 };
1519
1520                 const VkCmdBufferBeginInfo cmdBufferBeginInfo =
1521                 {
1522                         VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,        // VkStructureType                      sType;
1523                         DE_NULL,                                                                        // const void*                          pNext;
1524                         0u,                                                                                     // VkCmdBufferOptimizeFlags     flags;
1525                         DE_NULL,                                                                        // VkRenderPass                         renderPass;
1526                         0u,                                                                                     // deUint32                                     subpass;
1527                         DE_NULL                                                                         // VkFramebuffer                        framebuffer;
1528                 };
1529
1530                 const Move<VkCmdBuffer> cmdBuffer = createCommandBuffer(vk, vkDevice, &cmdBufferParams);
1531
1532                 const VkBufferImageCopy copyParams =
1533                 {
1534                         0u,                                                                                     // VkDeviceSize                 bufferOffset;
1535                         m_renderSize.x() * 4u,                                          // deUint32                             bufferRowLength;
1536                         0u,                                                                                     // deUint32                             bufferImageHeight;
1537                         {
1538                                 VK_IMAGE_ASPECT_COLOR,                          // VkImageAspect                aspect;
1539                                 0u,                                                                     // deUint32                             mipLevel;
1540                                 0u,                                                                     // deUint32                             arraySlice;
1541                                 1u,                                                                     // deUint32                             arraySize;
1542                         },                                                                                      // VkImageSubresourceCopy       imageSubresource;
1543                         { 0u, 0u, 0u },                                                         // VkOffset3D                   imageOffset;
1544                         { m_renderSize.x(), m_renderSize.y(), 1u }      // VkExtent3D                   imageExtent;
1545                 };
1546
1547                 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1548                 vk.cmdCopyImageToBuffer(*cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL, *readImageBuffer, 1u, &copyParams);
1549                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1550
1551                 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1552                 VK_CHECK(vk.queueSubmit(queue, 1, &cmdBuffer.get(), *m_fence));
1553                 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1554
1555                 void *imagePtr;
1556                 VK_CHECK(vk.mapMemory(vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes, 0u, &imagePtr));
1557
1558                 const VkMappedMemoryRange range =
1559                 {
1560                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,          // VkStructureType              sType;
1561                         DE_NULL,                                                                        // const void*                  pNext;
1562                         readImageBufferMemory->getMemory(),                     // VkDeviceMemory               mem;
1563                         0,                                                                                      // VkDeviceSize                 offset;
1564                         imageSizeBytes,                                                         // VkDeviceSize                 size;
1565                 };
1566
1567                 VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
1568
1569                 const tcu::TextureFormat resultFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1570                 const tcu::ConstPixelBufferAccess resultAccess(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, imagePtr);
1571
1572                 tcu::copy(result.getAccess(), resultAccess);
1573
1574                 vk.unmapMemory(vkDevice, readImageBufferMemory->getMemory());
1575         }
1576 }
1577
1578 void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
1579 {
1580         // Buffer info.
1581         const int                               width           = result.getWidth();
1582         const int                               height          = result.getHeight();
1583         const int                               gridSize        = quadGrid.getGridSize();
1584         const int                               stride          = gridSize + 1;
1585         const bool                              hasAlpha        = true; // \todo [2015-09-07 elecro] add correct alpha check
1586         ShaderEvalContext               evalCtx         (quadGrid);
1587
1588         // Evaluate color for each vertex.
1589         std::vector<tcu::Vec4>  colors          ((gridSize + 1) * (gridSize + 1));
1590         for (int y = 0; y < gridSize+1; y++)
1591         for (int x = 0; x < gridSize+1; x++)
1592         {
1593                 const float     sx                      = (float)x / (float)gridSize;
1594                 const float     sy                      = (float)y / (float)gridSize;
1595                 const int       vtxNdx          = ((y * (gridSize+1)) + x);
1596
1597                 evalCtx.reset(sx, sy);
1598                 m_evaluator.evaluate(evalCtx);
1599                 DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
1600                 tcu::Vec4 color = evalCtx.color;
1601
1602                 if (!hasAlpha)
1603                         color.w() = 1.0f;
1604
1605                 colors[vtxNdx] = color;
1606         }
1607
1608         // Render quads.
1609         for (int y = 0; y < gridSize; y++)
1610         for (int x = 0; x < gridSize; x++)
1611         {
1612                 const float             x0              = (float)x       / (float)gridSize;
1613                 const float             x1              = (float)(x + 1) / (float)gridSize;
1614                 const float             y0              = (float)y       / (float)gridSize;
1615                 const float             y1              = (float)(y + 1) / (float)gridSize;
1616
1617                 const float             sx0             = x0 * (float)width;
1618                 const float             sx1             = x1 * (float)width;
1619                 const float             sy0             = y0 * (float)height;
1620                 const float             sy1             = y1 * (float)height;
1621                 const float             oosx    = 1.0f / (sx1 - sx0);
1622                 const float             oosy    = 1.0f / (sy1 - sy0);
1623
1624                 const int               ix0             = deCeilFloatToInt32(sx0 - 0.5f);
1625                 const int               ix1             = deCeilFloatToInt32(sx1 - 0.5f);
1626                 const int               iy0             = deCeilFloatToInt32(sy0 - 0.5f);
1627                 const int               iy1             = deCeilFloatToInt32(sy1 - 0.5f);
1628
1629                 const int               v00             = (y * stride) + x;
1630                 const int               v01             = (y * stride) + x + 1;
1631                 const int               v10             = ((y + 1) * stride) + x;
1632                 const int               v11             = ((y + 1) * stride) + x + 1;
1633                 const tcu::Vec4 c00             = colors[v00];
1634                 const tcu::Vec4 c01             = colors[v01];
1635                 const tcu::Vec4 c10             = colors[v10];
1636                 const tcu::Vec4 c11             = colors[v11];
1637
1638                 //printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
1639
1640                 for (int iy = iy0; iy < iy1; iy++)
1641                 for (int ix = ix0; ix < ix1; ix++)
1642                 {
1643                         DE_ASSERT(deInBounds32(ix, 0, width));
1644                         DE_ASSERT(deInBounds32(iy, 0, height));
1645
1646                         const float                     sfx             = (float)ix + 0.5f;
1647                         const float                     sfy             = (float)iy + 0.5f;
1648                         const float                     fx1             = deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
1649                         const float                     fy1             = deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
1650
1651                         // Triangle quad interpolation.
1652                         const bool                      tri             = fx1 + fy1 <= 1.0f;
1653                         const float                     tx              = tri ? fx1 : (1.0f-fx1);
1654                         const float                     ty              = tri ? fy1 : (1.0f-fy1);
1655                         const tcu::Vec4&        t0              = tri ? c00 : c11;
1656                         const tcu::Vec4&        t1              = tri ? c01 : c10;
1657                         const tcu::Vec4&        t2              = tri ? c10 : c01;
1658                         const tcu::Vec4         color   = t0 + (t1-t0)*tx + (t2-t0)*ty;
1659
1660                         result.setPixel(ix, iy, tcu::RGBA(color));
1661                 }
1662         }
1663 }
1664
1665 void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
1666 {
1667         // Buffer info.
1668         const int                       width           = result.getWidth();
1669         const int                       height          = result.getHeight();
1670         const bool                      hasAlpha        = true;  // \todo [2015-09-07 elecro] add correct alpha check
1671         ShaderEvalContext       evalCtx         (quadGrid);
1672
1673         // Render.
1674         for (int y = 0; y < height; y++)
1675         for (int x = 0; x < width; x++)
1676         {
1677                 const float sx = ((float)x + 0.5f) / (float)width;
1678                 const float sy = ((float)y + 0.5f) / (float)height;
1679
1680                 evalCtx.reset(sx, sy);
1681                 m_evaluator.evaluate(evalCtx);
1682                 // Select either clear color or computed color based on discarded bit.
1683                 tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
1684
1685                 if (!hasAlpha)
1686                         color.w() = 1.0f;
1687
1688                 result.setPixel(x, y, tcu::RGBA(color));
1689         }
1690 }
1691
1692 bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
1693 {
1694         return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
1695 }
1696
1697 } // shaderrendercase
1698 } // vkt