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