es31fShaderImageLoadStoreTests.cpp revision 8852c82a1ffa4760985c17cc6875d5d521daf343
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Shader Image Load & Store Tests. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fShaderImageLoadStoreTests.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsTextureTestUtil.hpp" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp" 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp" 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp" 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp" 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluStrUtil.hpp" 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluCallLogWrapper.hpp" 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluProgramInterfaceQuery.hpp" 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp" 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp" 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp" 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp" 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp" 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp" 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp" 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp" 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSharedPtr.hpp" 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp" 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp" 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h" 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp" 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwDefs.hpp" 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp" 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector> 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string> 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm> 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map> 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::RenderContext; 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog; 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2; 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3; 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4; 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2; 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3; 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4; 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec2; 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec3; 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec4; 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TextureFormat; 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::ConstPixelBufferAccess; 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::PixelBufferAccess; 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::toString; 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::SharedPtr; 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::UniquePtr; 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector; 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string; 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::TextureTestUtil; 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Default image sizes used in most test cases. 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline IVec3 defaultImageSize (TextureType type) 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (type) 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_BUFFER: return IVec3(64, 1, 1); 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D: return IVec3(64, 64, 1); 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_CUBE: return IVec3(64, 64, 1); 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_3D: return IVec3(64, 64, 8); 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D_ARRAY: return IVec3(64, 64, 8); 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return IVec3(-1); 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size> 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string arrayStr (const T (&arr)[Size]) 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry string result = "{ "; 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < Size; i++) 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result += (i > 0 ? ", " : "") + toString(arr[i]); 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result += " }"; 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return result; 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrytemplate <typename T, int N> 1148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrystatic int arrayIndexOf (const T (&arr)[N], const T& e) 1158852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{ 1168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry return (int)(std::find(DE_ARRAY_BEGIN(arr), DE_ARRAY_END(arr), e) - DE_ARRAY_BEGIN(arr)); 1178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry} 1188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getTextureTypeName (TextureType type) 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (type) 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_BUFFER: return "buffer"; 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D: return "2d"; 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_CUBE: return "cube"; 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_3D: return "3d"; 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D_ARRAY: return "2d_array"; 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_NULL; 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isFormatTypeUnsignedInteger (TextureFormat::ChannelType type) 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return type == TextureFormat::UNSIGNED_INT8 || 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::UNSIGNED_INT16 || 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::UNSIGNED_INT32; 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isFormatTypeSignedInteger (TextureFormat::ChannelType type) 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return type == TextureFormat::SIGNED_INT8 || 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::SIGNED_INT16 || 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::SIGNED_INT32; 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isFormatTypeInteger (TextureFormat::ChannelType type) 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return isFormatTypeUnsignedInteger(type) || isFormatTypeSignedInteger(type); 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isFormatTypeUnorm (TextureFormat::ChannelType type) 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return type == TextureFormat::UNORM_INT8 || 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::UNORM_INT16 || 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::UNORM_INT32; 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isFormatTypeSnorm (TextureFormat::ChannelType type) 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return type == TextureFormat::SNORM_INT8 || 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::SNORM_INT16 || 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry type == TextureFormat::SNORM_INT32; 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isFormatSupportedForTextureBuffer (const TextureFormat& format) 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (format.order) 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::RGB: 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return format.type == TextureFormat::FLOAT || 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::SIGNED_INT32 || 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::UNSIGNED_INT32; 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Fallthroughs. 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::R: 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::RG: 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::RGBA: 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return format.type == TextureFormat::UNORM_INT8 || 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::HALF_FLOAT || 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::FLOAT || 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::SIGNED_INT8 || 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::SIGNED_INT16 || 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::SIGNED_INT32 || 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::UNSIGNED_INT8 || 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::UNSIGNED_INT16 || 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format.type == TextureFormat::UNSIGNED_INT32; 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getShaderImageFormatQualifier (const TextureFormat& format) 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* orderPart; 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* typePart; 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (format.order) 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::R: orderPart = "r"; break; 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::RGBA: orderPart = "rgba"; break; 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry orderPart = DE_NULL; 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (format.type) 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::FLOAT: typePart = "32f"; break; 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::HALF_FLOAT: typePart = "16f"; break; 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break; 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break; 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break; 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::SIGNED_INT32: typePart = "32i"; break; 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::SIGNED_INT16: typePart = "16i"; break; 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::SIGNED_INT8: typePart = "8i"; break; 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::UNORM_INT16: typePart = "16"; break; 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::UNORM_INT8: typePart = "8"; break; 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::SNORM_INT16: typePart = "16_snorm"; break; 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::SNORM_INT8: typePart = "8_snorm"; break; 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typePart = DE_NULL; 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return string() + orderPart + typePart; 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getShaderSamplerOrImageType (TextureFormat::ChannelType formatType, TextureType textureType, bool isSampler) 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const formatPart = isFormatTypeUnsignedInteger(formatType) ? "u" 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : isFormatTypeSignedInteger(formatType) ? "i" 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ""; 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const imageTypePart = textureType == TEXTURETYPE_BUFFER ? "Buffer" 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : textureType == TEXTURETYPE_2D ? "2D" 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : textureType == TEXTURETYPE_3D ? "3D" 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : textureType == TEXTURETYPE_CUBE ? "Cube" 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : textureType == TEXTURETYPE_2D_ARRAY ? "2DArray" 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return string() + formatPart + (isSampler ? "sampler" : "image") + imageTypePart; 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getShaderImageType (TextureFormat::ChannelType formatType, TextureType imageType) 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getShaderSamplerOrImageType(formatType, imageType, false); 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string getShaderSamplerType (TextureFormat::ChannelType formatType, TextureType imageType) 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getShaderSamplerOrImageType(formatType, imageType, true); 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint32 getGLTextureTarget (TextureType texType) 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (texType) 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_BUFFER: return GL_TEXTURE_BUFFER; 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D: return GL_TEXTURE_2D; 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_3D: return GL_TEXTURE_3D; 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_CUBE: return GL_TEXTURE_CUBE_MAP; 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D_ARRAY: return GL_TEXTURE_2D_ARRAY; 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (deUint32)-1; 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 cubeFaceToGLFace (tcu::CubeFace face) 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (face) 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case tcu::CUBEFACE_NEGATIVE_X: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X; 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case tcu::CUBEFACE_POSITIVE_X: return GL_TEXTURE_CUBE_MAP_POSITIVE_X; 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case tcu::CUBEFACE_NEGATIVE_Y: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case tcu::CUBEFACE_POSITIVE_Y: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y; 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case tcu::CUBEFACE_NEGATIVE_Z: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case tcu::CUBEFACE_POSITIVE_Z: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z; 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return GL_NONE; 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Texture1D* newOneLevelTexture1D (const tcu::TextureFormat& format, int w) 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Texture1D* const res = new tcu::Texture1D(format, w); 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res->allocLevel(0); 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Texture2D* newOneLevelTexture2D (const tcu::TextureFormat& format, int w, int h) 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Texture2D* const res = new tcu::Texture2D(format, w, h); 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res->allocLevel(0); 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::TextureCube* newOneLevelTextureCube (const tcu::TextureFormat& format, int size) 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureCube* const res = new tcu::TextureCube(format, size); 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < tcu::CUBEFACE_LAST; i++) 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res->allocLevel((tcu::CubeFace)i, 0); 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Texture3D* newOneLevelTexture3D (const tcu::TextureFormat& format, int w, int h, int d) 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Texture3D* const res = new tcu::Texture3D(format, w, h, d); 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res->allocLevel(0); 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Texture2DArray* newOneLevelTexture2DArray (const tcu::TextureFormat& format, int w, int h, int d) 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Texture2DArray* const res = new tcu::Texture2DArray(format, w, h, d); 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res->allocLevel(0); 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline TextureType textureLayerType (TextureType entireTextureType) 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (entireTextureType) 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Single-layer types. 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Fallthrough. 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_BUFFER: 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D: 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return entireTextureType; 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Multi-layer types with 2d layers. 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_3D: 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_CUBE: 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D_ARRAY: 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return TEXTURETYPE_2D; 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return TEXTURETYPE_LAST; 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* const s_texBufExtString = "GL_EXT_texture_buffer"; 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void checkTextureTypeExtensions (const glu::ContextInfo& contextInfo, TextureType type) 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (type == TEXTURETYPE_BUFFER && !contextInfo.isExtensionSupported(s_texBufExtString)) 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("Test requires " + string(s_texBufExtString) + " extension"); 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline string textureTypeExtensionShaderRequires (TextureType type) 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (type == TEXTURETYPE_BUFFER) 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "#extension " + string(s_texBufExtString) + " : require\n"; 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return ""; 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum AtomicOperation 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_ADD = 0, 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_MIN, 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_MAX, 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_AND, 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_OR, 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_XOR, 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_EXCHANGE, 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_COMP_SWAP, 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_LAST 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! An order-independent operation is one for which the end result doesn't depend on the order in which the operations are carried (i.e. is both commutative and associative). 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isOrderIndependentAtomicOperation (AtomicOperation op) 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return op == ATOMIC_OPERATION_ADD || 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry op == ATOMIC_OPERATION_MIN || 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry op == ATOMIC_OPERATION_MAX || 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry op == ATOMIC_OPERATION_AND || 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry op == ATOMIC_OPERATION_OR || 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry op == ATOMIC_OPERATION_XOR; 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Computes the result of an atomic operation where "a" is the data operated on and "b" is the parameter to the atomic function. 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeBinaryAtomicOperationResult (AtomicOperation op, int a, int b) 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (op) 3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_ADD: return a + b; 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MIN: return de::min(a, b); 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MAX: return de::max(a, b); 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_AND: return a & b; 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_OR: return a | b; 4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_XOR: return a ^ b; 4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_EXCHANGE: return b; 4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return -1; 4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! \note For floats, only the exchange operation is supported. 4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat computeBinaryAtomicOperationResult (AtomicOperation op, float /*a*/, float b) 4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (op) 4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_EXCHANGE: return b; 4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return -1; 4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getAtomicOperationCaseName (AtomicOperation op) 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (op) 4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_ADD: return "add"; 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MIN: return "min"; 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MAX: return "max"; 4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_AND: return "and"; 4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_OR: return "or"; 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_XOR: return "xor"; 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_EXCHANGE: return "exchange"; 4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_COMP_SWAP: return "comp_swap"; 4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_NULL; 4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getAtomicOperationShaderFuncName (AtomicOperation op) 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (op) 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_ADD: return "imageAtomicAdd"; 4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MIN: return "imageAtomicMin"; 4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MAX: return "imageAtomicMax"; 4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_AND: return "imageAtomicAnd"; 4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_OR: return "imageAtomicOr"; 4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_XOR: return "imageAtomicXor"; 4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_EXCHANGE: return "imageAtomicExchange"; 4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_COMP_SWAP: return "imageAtomicCompSwap"; 4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_NULL; 4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! In GLSL, when accessing cube images, the z coordinate is mapped to a cube face. 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! \note This is _not_ the same as casting the z to a tcu::CubeFace. 4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::CubeFace glslImageFuncZToCubeFace (int z) 4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const tcu::CubeFace faces[6] = 4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::CUBEFACE_POSITIVE_X, 4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::CUBEFACE_NEGATIVE_X, 4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::CUBEFACE_POSITIVE_Y, 4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::CUBEFACE_NEGATIVE_Y, 4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::CUBEFACE_POSITIVE_Z, 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::CUBEFACE_NEGATIVE_Z 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inBounds(z, 0, DE_LENGTH_OF_ARRAY(faces))); 4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return faces[z]; 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BufferMemMap 4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BufferMemMap (const glw::Functions& gl, deUint32 target, int offset, int size, deUint32 access) 4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_gl (gl) 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_target (target) 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_ptr (DE_NULL) 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_ptr = gl.mapBufferRange(target, offset, size, access); 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()"); 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(m_ptr); 4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~BufferMemMap (void) 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_gl.unmapBuffer(m_target); 4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* getPtr (void) const { return m_ptr; } 4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* operator* (void) const { return m_ptr; } 4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BufferMemMap (const BufferMemMap& other); 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BufferMemMap& operator= (const BufferMemMap& other); 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& m_gl; 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 m_target; 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* m_ptr; 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Utility for more readable uniform assignment logging; logs the name of the uniform when assigning. Handles the locations, querying them the first time they're assigned 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \note Assumes that the appropriate program is in use when assigning uniforms. 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass UniformAccessLogger 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger (const glw::Functions& gl, TestLog& log, deUint32 programGL) 5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_gl (gl) 5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_log (log) 5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_programGL (programGL) 5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void assign1i (const string& name, int x); 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void assign3f (const string& name, float x, float y, float z); 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int getLocation (const string& name); 5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& m_gl; 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& m_log; 5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 m_programGL; 5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::map<string, int> m_uniformLocations; 5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint UniformAccessLogger::getLocation (const string& name) 5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_uniformLocations.find(name) == m_uniformLocations.end()) 5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int loc = m_gl.getUniformLocation(m_programGL, name.c_str()); 5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(loc != -1); 5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_uniformLocations[name] = loc; 5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_uniformLocations[name]; 5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid UniformAccessLogger::assign1i (const string& name, int x) 5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int loc = getLocation(name); 5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_log << TestLog::Message << "// Assigning to uniform " << name << ": " << x << TestLog::EndMessage; 5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_gl.uniform1i(loc, x); 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid UniformAccessLogger::assign3f (const string& name, float x, float y, float z) 5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int loc = getLocation(name); 5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_log << TestLog::Message << "// Assigning to uniform " << name << ": " << Vec3(x, y, z) << TestLog::EndMessage; 5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_gl.uniform3f(loc, x, y, z); 5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Class containing a (single-level) texture of a given type. Supports accessing pixels with coordinate convention similar to that in imageStore() and imageLoad() in shaders; useful especially for cube maps. 5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LayeredImage 5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage (TextureType type, const TextureFormat& format, int w, int h, int d); 5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureType getImageType (void) const { return m_type; } 5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& getSize (void) const { return m_size; } 5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& getFormat (void) const { return m_format; } 5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note For cube maps, set/getPixel's z parameter specifies the cube face in the same manner as in imageStore/imageLoad in GL shaders (see glslImageFuncZToCubeFace), instead of directly as a tcu::CubeFace. 5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry template <typename ColorT> 5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void setPixel (int x, int y, int z, const ColorT& color) const; 5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec4 getPixel (int x, int y, int z) const; 5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec4 getPixelInt (int x, int y, int z) const; 5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UVec4 getPixelUint (int x, int y, int z) const { return getPixelInt(x, y, z).asUint(); } 5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PixelBufferAccess getAccess (void) { return getAccessInternal(); } 5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PixelBufferAccess getSliceAccess (int slice) { return getSliceAccessInternal(slice); } 5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PixelBufferAccess getCubeFaceAccess (tcu::CubeFace face) { return getCubeFaceAccessInternal(face); } 5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ConstPixelBufferAccess getAccess (void) const { return getAccessInternal(); } 5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ConstPixelBufferAccess getSliceAccess (int slice) const { return getSliceAccessInternal(slice); } 5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ConstPixelBufferAccess getCubeFaceAccess (tcu::CubeFace face) const { return getCubeFaceAccessInternal(face); } 5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage (const LayeredImage&); 5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage& operator= (const LayeredImage&); 5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Some helpers to reduce code duplication between const/non-const versions of getAccess and others. 5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PixelBufferAccess getAccessInternal (void) const; 5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PixelBufferAccess getSliceAccessInternal (int slice) const; 5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PixelBufferAccess getCubeFaceAccessInternal (tcu::CubeFace face) const; 5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_type; 5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 m_size; 5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_format; 5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Depending on m_type, exactly one of the following will contain non-null. 6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const SharedPtr<tcu::Texture1D> m_texBuffer; 6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const SharedPtr<tcu::Texture2D> m_tex2D; 6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const SharedPtr<tcu::TextureCube> m_texCube; 6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const SharedPtr<tcu::Texture3D> m_tex3D; 6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const SharedPtr<tcu::Texture2DArray> m_tex2DArray; 6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6073c827367444ee418f129b2c238299f49d3264554Jarkko PoyryLayeredImage::LayeredImage (TextureType type, const TextureFormat& format, int w, int h, int d) 6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type (type) 6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_size (w, h, d) 6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_format (format) 6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_texBuffer (type == TEXTURETYPE_BUFFER ? SharedPtr<tcu::Texture1D> (newOneLevelTexture1D (format, w)) : SharedPtr<tcu::Texture1D>()) 6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_tex2D (type == TEXTURETYPE_2D ? SharedPtr<tcu::Texture2D> (newOneLevelTexture2D (format, w, h)) : SharedPtr<tcu::Texture2D>()) 6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_texCube (type == TEXTURETYPE_CUBE ? SharedPtr<tcu::TextureCube> (newOneLevelTextureCube (format, w)) : SharedPtr<tcu::TextureCube>()) 6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_tex3D (type == TEXTURETYPE_3D ? SharedPtr<tcu::Texture3D> (newOneLevelTexture3D (format, w, h, d)) : SharedPtr<tcu::Texture3D>()) 6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_tex2DArray (type == TEXTURETYPE_2D_ARRAY ? SharedPtr<tcu::Texture2DArray> (newOneLevelTexture2DArray (format, w, h, d)) : SharedPtr<tcu::Texture2DArray>()) 6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_size.z() == 1 || 6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_type == TEXTURETYPE_3D || 6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_type == TEXTURETYPE_2D_ARRAY); 6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_size.y() == 1 || 6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_type == TEXTURETYPE_2D || 6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_type == TEXTURETYPE_CUBE || 6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_type == TEXTURETYPE_3D || 6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_type == TEXTURETYPE_2D_ARRAY); 6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(w == h || type != TEXTURETYPE_CUBE); 6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_texBuffer != DE_NULL || 6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_tex2D != DE_NULL || 6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_texCube != DE_NULL || 6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_tex3D != DE_NULL || 6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_tex2DArray != DE_NULL); 6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename ColorT> 6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid LayeredImage::setPixel (int x, int y, int z, const ColorT& color) const 6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PixelBufferAccess access = m_type == TEXTURETYPE_BUFFER ? m_texBuffer->getLevel(0) 6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type == TEXTURETYPE_2D ? m_tex2D->getLevel(0) 6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type == TEXTURETYPE_CUBE ? m_texCube->getLevelFace(0, glslImageFuncZToCubeFace(z)) 6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type == TEXTURETYPE_3D ? m_tex3D->getLevel(0) 6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type == TEXTURETYPE_2D_ARRAY ? m_tex2DArray->getLevel(0) 6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : PixelBufferAccess(TextureFormat(), -1, -1, -1, DE_NULL); 6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry access.setPixel(color, x, y, m_type == TEXTURETYPE_CUBE ? 0 : z); 6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6493c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVec4 LayeredImage::getPixel (int x, int y, int z) const 6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ConstPixelBufferAccess access = m_type == TEXTURETYPE_CUBE ? getCubeFaceAccess(glslImageFuncZToCubeFace(z)) : getAccess(); 6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return access.getPixel(x, y, m_type == TEXTURETYPE_CUBE ? 0 : z); 6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIVec4 LayeredImage::getPixelInt (int x, int y, int z) const 6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ConstPixelBufferAccess access = m_type == TEXTURETYPE_CUBE ? getCubeFaceAccess(glslImageFuncZToCubeFace(z)) : getAccess(); 6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return access.getPixelInt(x, y, m_type == TEXTURETYPE_CUBE ? 0 : z); 6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPixelBufferAccess LayeredImage::getAccessInternal (void) const 6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_type == TEXTURETYPE_BUFFER || m_type == TEXTURETYPE_2D || m_type == TEXTURETYPE_3D || m_type == TEXTURETYPE_2D_ARRAY); 6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_type == TEXTURETYPE_BUFFER ? m_texBuffer->getLevel(0) 6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type == TEXTURETYPE_2D ? m_tex2D->getLevel(0) 6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type == TEXTURETYPE_3D ? m_tex3D->getLevel(0) 6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_type == TEXTURETYPE_2D_ARRAY ? m_tex2DArray->getLevel(0) 6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : PixelBufferAccess(TextureFormat(), -1, -1, -1, DE_NULL); 6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6723c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPixelBufferAccess LayeredImage::getSliceAccessInternal (int slice) const 6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PixelBufferAccess srcAccess = getAccessInternal(); 6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::getSubregion(srcAccess, 0, 0, slice, srcAccess.getWidth(), srcAccess.getHeight(), 1); 6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6783c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPixelBufferAccess LayeredImage::getCubeFaceAccessInternal (tcu::CubeFace face) const 6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_type == TEXTURETYPE_CUBE); 6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_texCube->getLevelFace(0, face); 6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Set texture storage or, if using buffer texture, setup buffer and attach to texture. 6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void setTextureStorage (glu::CallLogWrapper& glLog, TextureType imageType, deUint32 internalFormat, const IVec3& imageSize, deUint32 textureBufGL) 6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTarget = getGLTextureTarget(imageType); 6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (imageType) 6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_BUFFER: 6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat format = glu::mapGLInternalFormat(internalFormat); 6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numBytes = format.getPixelSize() * imageSize.x(); 6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isFormatSupportedForTextureBuffer(format)); 6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindBuffer(GL_TEXTURE_BUFFER, textureBufGL); 6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBufferData(GL_TEXTURE_BUFFER, numBytes, DE_NULL, GL_STATIC_DRAW); 6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, textureBufGL); 6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(imageSize.y() == 1 && imageSize.z() == 1); 7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Fall-throughs. 7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D: 7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_CUBE: 7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexStorage2D(textureTarget, 1, internalFormat, imageSize.x(), imageSize.y()); 7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(imageSize.z() == 1); 7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_3D: 7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TEXTURETYPE_2D_ARRAY: 7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexStorage3D(textureTarget, 1, internalFormat, imageSize.x(), imageSize.y(), imageSize.z()); 7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void uploadTexture (glu::CallLogWrapper& glLog, const LayeredImage& src, deUint32 textureBufGL) 7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 internalFormat = glu::getInternalFormat(src.getFormat()); 7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::TransferFormat transferFormat = glu::getTransferFormat(src.getFormat()); 7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& imageSize = src.getSize(); 7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, src.getImageType(), internalFormat, imageSize, textureBufGL); 7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int pixelSize = src.getFormat().getPixelSize(); 7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int unpackAlignment; 7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (deIsPowerOfTwo32(pixelSize)) 7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry unpackAlignment = 8; 7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry unpackAlignment = 1; 7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glPixelStorei(GL_UNPACK_ALIGNMENT, unpackAlignment); 7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (src.getImageType() == TEXTURETYPE_BUFFER) 7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindBuffer(GL_TEXTURE_BUFFER, textureBufGL); 7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBufferData(GL_TEXTURE_BUFFER, src.getFormat().getPixelSize() * imageSize.x(), src.getAccess().getDataPtr(), GL_STATIC_DRAW); 7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (src.getImageType() == TEXTURETYPE_2D) 7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imageSize.x(), imageSize.y(), transferFormat.format, transferFormat.dataType, src.getAccess().getDataPtr()); 7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (src.getImageType() == TEXTURETYPE_CUBE) 7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int faceI = 0; faceI < tcu::CUBEFACE_LAST; faceI++) 7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::CubeFace face = (tcu::CubeFace)faceI; 7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexSubImage2D(cubeFaceToGLFace(face), 0, 0, 0, imageSize.x(), imageSize.y(), transferFormat.format, transferFormat.dataType, src.getCubeFaceAccess(face).getDataPtr()); 7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(src.getImageType() == TEXTURETYPE_3D || src.getImageType() == TEXTURETYPE_2D_ARRAY); 7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTarget = getGLTextureTarget(src.getImageType()); 7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexSubImage3D(textureTarget, 0, 0, 0, 0, imageSize.x(), imageSize.y(), imageSize.z(), transferFormat.format, transferFormat.dataType, src.getAccess().getDataPtr()); 7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void readPixelsRGBAInteger32 (const PixelBufferAccess& dst, int originX, int originY, glu::CallLogWrapper& glLog) 7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(dst.getDepth() == 1); 7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isFormatTypeUnsignedInteger(dst.getFormat().type)) 7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<UVec4> data(dst.getWidth()*dst.getHeight()); 7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glReadPixels(originX, originY, dst.getWidth(), dst.getHeight(), GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data[0]); 7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < dst.getHeight(); y++) 7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < dst.getWidth(); x++) 7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.setPixel(data[y*dst.getWidth() + x], x, y); 7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (isFormatTypeSignedInteger(dst.getFormat().type)) 7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<IVec4> data(dst.getWidth()*dst.getHeight()); 7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glReadPixels(originX, originY, dst.getWidth(), dst.getHeight(), GL_RGBA_INTEGER, GL_INT, &data[0]); 7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < dst.getHeight(); y++) 7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < dst.getWidth(); x++) 7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.setPixel(data[y*dst.getWidth() + x], x, y); 7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Base for a functor for verifying and logging a 2d texture layer (2d image, cube face, 3d slice, 2d layer). 7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ImageLayerVerifier 7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual bool operator() (TestLog&, const ConstPixelBufferAccess&, int sliceOrFaceNdx) const = 0; 7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual ~ImageLayerVerifier (void) {} 7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void setTexParameteri (glu::CallLogWrapper& glLog, deUint32 target) 8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (target != GL_TEXTURE_BUFFER) 8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Binds texture (one layer at a time) to color attachment of FBO and does glReadPixels(). Calls the verifier for each layer. 8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! \note Not for buffer textures. 8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool readIntegerTextureViaFBOAndVerify (const RenderContext& renderCtx, 8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper& glLog, 8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 textureGL, 8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureType textureType, 8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& textureFormat, 8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& textureSize, 8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ImageLayerVerifier& verifyLayer) 8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isFormatTypeInteger(textureFormat.type)); 8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(textureType != TEXTURETYPE_BUFFER); 8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log = glLog.getLog(); 8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::ScopedLogSection section(log, "Verification", "Result verification (bind texture layer-by-layer to FBO, read with glReadPixels())"); 8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = textureType == TEXTURETYPE_CUBE ? 6 : textureSize.z(); 8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(textureType); 8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::Framebuffer fbo (renderCtx); 8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureLevel resultSlice (textureFormat, textureSize.x(), textureSize.y()); 8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindFramebuffer(GL_FRAMEBUFFER, *fbo); 8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "Bind FBO"); 8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); 8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glMemoryBarrier"); 8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, textureGL); 8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int sliceOrFaceNdx = 0; sliceOrFaceNdx < numSlicesOrFaces; sliceOrFaceNdx++) 8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (textureType == TEXTURETYPE_CUBE) 8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeFaceToGLFace(glslImageFuncZToCubeFace(sliceOrFaceNdx)), textureGL, 0); 8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (textureType == TEXTURETYPE_2D) 8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureGL, 0); 8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (textureType == TEXTURETYPE_3D || textureType == TEXTURETYPE_2D_ARRAY) 8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureGL, 0, sliceOrFaceNdx); 8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "Bind texture to framebuffer color attachment 0"); 8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(glLog.glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry readPixelsRGBAInteger32(resultSlice.getAccess(), 0, 0, glLog); 8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glReadPixels"); 8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!verifyLayer(log, resultSlice, sliceOrFaceNdx)) 8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Reads texture with texture() in compute shader, one layer at a time, putting values into a SSBO and reading with a mapping. Calls the verifier for each layer. 8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! \note Not for buffer textures. 8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool readFloatOrNormTextureWithLookupsAndVerify (const RenderContext& renderCtx, 8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper& glLog, 8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 textureGL, 8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureType textureType, 8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& textureFormat, 8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& textureSize, 8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ImageLayerVerifier& verifyLayer) 8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!isFormatTypeInteger(textureFormat.type)); 8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(textureType != TEXTURETYPE_BUFFER); 8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log = glLog.getLog(); 8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::ScopedLogSection section(log, "Verification", "Result verification (read texture layer-by-layer in compute shader with texture() into SSBO)"); 8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource("#version 310 es\n" 8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (binding = 0) buffer Output\n" 8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " vec4 color[" + toString(textureSize.x()*textureSize.y()) + "];\n" 8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "} sb_out;\n" 8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp " + getShaderSamplerType(textureFormat.type, textureType) + ";\n" 8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "uniform highp " + getShaderSamplerType(textureFormat.type, textureType) + " u_texture;\n" 8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "uniform highp vec3 u_texCoordLD;\n" 8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "uniform highp vec3 u_texCoordRD;\n" 8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "uniform highp vec3 u_texCoordLU;\n" 8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "uniform highp vec3 u_texCoordRU;\n" 8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gx = int(gl_GlobalInvocationID.x);\n" 9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gy = int(gl_GlobalInvocationID.y);\n" 9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " highp float s = (float(gx) + 0.5) / float(" + toString(textureSize.x()) + ");\n" 9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " highp float t = (float(gy) + 0.5) / float(" + toString(textureType == TEXTURETYPE_CUBE ? textureSize.x() : textureSize.y()) + ");\n" 9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " highp vec3 texCoord = u_texCoordLD*(1.0-s)*(1.0-t)\n" 9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " + u_texCoordRD*( s)*(1.0-t)\n" 9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " + u_texCoordLU*(1.0-s)*( t)\n" 9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " + u_texCoordRU*( s)*( t);\n" 9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int ndx = gy*" + toString(textureSize.x()) + " + gx;\n" 9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " sb_out.color[ndx] = texture(u_texture, texCoord" + (textureType == TEXTURETYPE_2D ? ".xy" : "") + ");\n" 9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Failure: failed to compile program" << TestLog::EndMessage; 9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_FAIL("Program compilation failed"); 9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(textureType); 9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer outputBuffer (renderCtx); 9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms (renderCtx.getFunctions(), log, program.getProgram()); 9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup texture. 9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, textureGL); 9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign1i("u_texture", 0); 9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup output buffer. 9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 blockIndex = glLog.glGetProgramResourceIndex(program.getProgram(), GL_SHADER_STORAGE_BLOCK, "Output"); 9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int blockSize = glu::getProgramResourceInt(renderCtx.getFunctions(), program.getProgram(), GL_SHADER_STORAGE_BLOCK, blockIndex, GL_BUFFER_DATA_SIZE); 9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Got buffer data size = " << blockSize << TestLog::EndMessage; 9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(blockSize > 0); 9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindBuffer(GL_SHADER_STORAGE_BUFFER, *outputBuffer); 9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBufferData(GL_SHADER_STORAGE_BUFFER, blockSize, DE_NULL, GL_STREAM_READ); 9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *outputBuffer); 9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "SSB setup failed"); 9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Dispatch one layer at a time, read back and verify. 9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = textureType == TEXTURETYPE_CUBE ? 6 : textureSize.z(); 9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureLevel resultSlice (textureFormat, textureSize.x(), textureSize.y()); 9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PixelBufferAccess resultSliceAccess = resultSlice.getAccess(); 9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 blockIndex = glLog.glGetProgramResourceIndex(program.getProgram(), GL_SHADER_STORAGE_BLOCK, "Output"); 9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int blockSize = glu::getProgramResourceInt(renderCtx.getFunctions(), program.getProgram(), GL_SHADER_STORAGE_BLOCK, blockIndex, GL_BUFFER_DATA_SIZE); 9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 valueIndex = glLog.glGetProgramResourceIndex(program.getProgram(), GL_BUFFER_VARIABLE, "Output.color"); 9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::InterfaceVariableInfo valueInfo = glu::getProgramInterfaceVariableInfo(renderCtx.getFunctions(), program.getProgram(), GL_BUFFER_VARIABLE, valueIndex); 9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(valueInfo.arraySize == (deUint32)(textureSize.x()*textureSize.y())); 9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int sliceOrFaceNdx = 0; sliceOrFaceNdx < numSlicesOrFaces; sliceOrFaceNdx++) 9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (textureType == TEXTURETYPE_CUBE) 9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<float> coords; 9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry computeQuadTexCoordCube(coords, glslImageFuncZToCubeFace(sliceOrFaceNdx)); 9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordLD", coords[3*0 + 0], coords[3*0 + 1], coords[3*0 + 2]); 9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordRD", coords[3*2 + 0], coords[3*2 + 1], coords[3*2 + 2]); 9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordLU", coords[3*1 + 0], coords[3*1 + 1], coords[3*1 + 2]); 9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordRU", coords[3*3 + 0], coords[3*3 + 1], coords[3*3 + 2]); 9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float z = textureType == TEXTURETYPE_3D ? 9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float)sliceOrFaceNdx + 0.5f) / (float)numSlicesOrFaces : 9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (float)sliceOrFaceNdx; 9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordLD", 0.0f, 0.0f, z); 9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordRD", 1.0f, 0.0f, z); 9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordLU", 0.0f, 1.0f, z); 9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign3f("u_texCoordRU", 1.0f, 1.0f, z); 9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(textureSize.x(), textureSize.y(), 1); 9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Note: mapping buffer and reading color values written" << TestLog::EndMessage; 9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const BufferMemMap bufMap(renderCtx.getFunctions(), GL_SHADER_STORAGE_BUFFER, 0, blockSize, GL_MAP_READ_BIT); 9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < textureSize.y(); y++) 9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < textureSize.x(); x++) 9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ndx = y*textureSize.x() + x; 9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float* const clrData = (const float*)((const deUint8*)bufMap.getPtr() + valueInfo.offset + valueInfo.arrayStride*ndx); 9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (textureFormat.order) 10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::R: resultSliceAccess.setPixel(Vec4(clrData[0]), x, y); break; 10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case TextureFormat::RGBA: resultSliceAccess.setPixel(Vec4(clrData[0], clrData[1], clrData[2], clrData[3]), x, y); break; 10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!verifyLayer(log, resultSliceAccess, sliceOrFaceNdx)) 10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Read buffer texture by reading the corresponding buffer with a mapping. 10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool readBufferTextureWithMappingAndVerify (const RenderContext& renderCtx, 10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper& glLog, 10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 bufferGL, 10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& textureFormat, 10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int imageSize, 10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ImageLayerVerifier& verifyLayer) 10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureLevel result (textureFormat, imageSize, 1); 10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PixelBufferAccess resultAccess = result.getAccess(); 10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(resultAccess.getDataSize() == imageSize * textureFormat.getPixelSize()); 10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::ScopedLogSection section(glLog.getLog(), "Verification", "Result verification (read texture's buffer with a mapping)"); 10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindBuffer(GL_TEXTURE_BUFFER, bufferGL); 10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const BufferMemMap bufMap(renderCtx.getFunctions(), GL_TEXTURE_BUFFER, 0, resultAccess.getDataSize(), GL_MAP_READ_BIT); 10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy(resultAccess.getDataPtr(), bufMap.getPtr(), resultAccess.getDataSize()); 10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyLayer(glLog.getLog(), resultAccess, 0); 10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Calls the appropriate texture verification function depending on texture format or type. 10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool readTextureAndVerify (const RenderContext& renderCtx, 10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper& glLog, 10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 textureGL, 10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 bufferGL, 10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureType textureType, 10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& textureFormat, 10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& imageSize, 10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ImageLayerVerifier& verifyLayer) 10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (textureType == TEXTURETYPE_BUFFER) 10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return readBufferTextureWithMappingAndVerify(renderCtx, glLog, bufferGL, textureFormat, imageSize.x(), verifyLayer); 10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return isFormatTypeInteger(textureFormat.type) ? readIntegerTextureViaFBOAndVerify (renderCtx, glLog, textureGL, textureType, textureFormat, imageSize, verifyLayer) 10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : readFloatOrNormTextureWithLookupsAndVerify (renderCtx, glLog, textureGL, textureType, textureFormat, imageSize, verifyLayer); 10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! An ImageLayerVerifier that simply compares the result slice to a slice in a reference image. 10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! \note Holds the reference image as a reference (no pun intended) instead of a copy; caller must be aware of lifetime issues. 10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ImageLayerComparer : public ImageLayerVerifier 10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ImageLayerComparer (const LayeredImage& reference, 10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2& relevantRegion = IVec2(0) /* If given, only check this region of each slice. */) 10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_reference (reference) 10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_relevantRegion (relevantRegion.x() > 0 && relevantRegion.y() > 0 ? relevantRegion : reference.getSize().swizzle(0, 1)) 10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool operator() (TestLog& log, const tcu::ConstPixelBufferAccess& resultSlice, int sliceOrFaceNdx) const 10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isCube = m_reference.getImageType() == TEXTURETYPE_CUBE; 10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ConstPixelBufferAccess referenceSlice = tcu::getSubregion(isCube ? m_reference.getCubeFaceAccess(glslImageFuncZToCubeFace(sliceOrFaceNdx)) 10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_reference.getSliceAccess(sliceOrFaceNdx), 10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 0, 0, m_relevantRegion.x(), m_relevantRegion.y()); 10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string comparisonName = "Comparison" + toString(sliceOrFaceNdx); 10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string comparisonDesc = "Image Comparison, " 10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (isCube ? "face " + string(glu::getCubeMapFaceName(cubeFaceToGLFace(glslImageFuncZToCubeFace(sliceOrFaceNdx)))) 10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "slice " + toString(sliceOrFaceNdx)); 10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isFormatTypeInteger(m_reference.getFormat().type)) 10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), referenceSlice, resultSlice, UVec4(0), tcu::COMPARE_LOG_RESULT); 10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), referenceSlice, resultSlice, Vec4(0.01f), tcu::COMPARE_LOG_RESULT); 10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const LayeredImage& m_reference; 10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 m_relevantRegion; 10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Case that just stores some computation results into an image. 10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ImageStoreCase : public TestCase 10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum CaseFlag 10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CASEFLAG_SINGLE_LAYER_BIND = 1 << 0 //!< If given, glBindImageTexture() is called with GL_FALSE <layered> argument, and for each layer the compute shader is separately dispatched. 11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ImageStoreCase (Context& context, const char* name, const char* description, const TextureFormat& format, TextureType textureType, deUint32 caseFlags = 0) 11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_format (format) 11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_textureType (textureType) 11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_singleLayerBind ((caseFlags & CASEFLAG_SINGLE_LAYER_BIND) != 0) 11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void) { checkTextureTypeExtensions(m_context.getContextInfo(), m_textureType); } 11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_format; 11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_textureType; 11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool m_singleLayerBind; 11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11193c827367444ee418f129b2c238299f49d3264554Jarkko PoyryImageStoreCase::IterateResult ImageStoreCase::iterate (void) 11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const RenderContext& renderCtx = m_context.getRenderContext(); 11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log (m_testCtx.getLog()); 11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper glLog (renderCtx.getFunctions(), log); 11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 internalFormatGL = glu::getInternalFormat(m_format); 11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(m_textureType); 11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& imageSize = defaultImageSize(m_textureType); 11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = m_textureType == TEXTURETYPE_CUBE ? 6 : imageSize.z(); 11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxImageDimension = de::max(imageSize.x(), de::max(imageSize.y(), imageSize.z())); 11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float storeColorScale = isFormatTypeUnorm(m_format.type) ? 1.0f / (float)(maxImageDimension - 1) 11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : isFormatTypeSnorm(m_format.type) ? 2.0f / (float)(maxImageDimension - 1) 11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : 1.0f; 11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float storeColorBias = isFormatTypeSnorm(m_format.type) ? -1.0f : 0.0f; 11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer textureBuf (renderCtx); // \note Only really used if using buffer texture. 11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture texture (renderCtx); 11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.enableLogging(true); 11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup texture. 11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *texture << ")" << TestLog::EndMessage; 11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_textureType == TEXTURETYPE_BUFFER) 11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a buffer for the texture (name " << *textureBuf << ")" << TestLog::EndMessage; 11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *texture); 11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, m_textureType, internalFormatGL, imageSize, *textureBuf); 11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform image stores in compute shader. 11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Generate compute shader. 11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format); 11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType shaderImageType = m_singleLayerBind ? textureLayerType(m_textureType) : m_textureType; 11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageTypeStr = getShaderImageType(m_format.type, shaderImageType); 11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isUintFormat = isFormatTypeUnsignedInteger(m_format.type); 11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isIntFormat = isFormatTypeSignedInteger(m_format.type); 11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string colorBaseExpr = string(isUintFormat ? "u" : isIntFormat ? "i" : "") + "vec4(gx^gy^gz, " 11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "(" + toString(imageSize.x()-1) + "-gx)^gy^gz, " 11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "gx^(" + toString(imageSize.y()-1) + "-gy)^gz, " 11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "(" + toString(imageSize.x()-1) + "-gx)^(" + toString(imageSize.y()-1) + "-gy)^gz)"; 11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + toString(storeColorScale)) 11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (storeColorBias == 0.0f ? "" : " + float(" + toString(storeColorBias) + ")"); 11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource("#version 310 es\n" 11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + textureTypeExtensionShaderRequires(shaderImageType) + 11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp " + shaderImageTypeStr + ";\n" 11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=0) writeonly uniform " + shaderImageTypeStr + " u_image;\n" 11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_singleLayerBind ? "uniform int u_layerNdx;\n" : "") + 11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gx = int(gl_GlobalInvocationID.x);\n" 11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gy = int(gl_GlobalInvocationID.y);\n" 11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gz = " + (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") + ";\n" 11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (shaderImageType == TEXTURETYPE_BUFFER ? 11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_image, gx, " + colorExpr + ");\n" 11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : shaderImageType == TEXTURETYPE_2D ? 11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_image, ivec2(gx, gy), " + colorExpr + ");\n" 11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : shaderImageType == TEXTURETYPE_3D || shaderImageType == TEXTURETYPE_CUBE || shaderImageType == TEXTURETYPE_2D_ARRAY ? 11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_image, ivec3(gx, gy, gz), " + colorExpr + ");\n" 11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL) + 11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms(renderCtx.getFunctions(), log, program.getProgram()); 11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program compilation failed"); 11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup and dispatch. 12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_singleLayerBind) 12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int layerNdx = 0; layerNdx < numSlicesOrFaces; layerNdx++) 12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (layerNdx > 0) 12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uniforms.assign1i("u_layerNdx", layerNdx); 12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *texture, 0, GL_FALSE, layerNdx, GL_WRITE_ONLY, internalFormatGL); 12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(imageSize.x(), imageSize.y(), 1); 12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *texture, 0, GL_TRUE, 0, GL_WRITE_ONLY, internalFormatGL); 12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(imageSize.x(), imageSize.y(), numSlicesOrFaces); 12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Create reference, read texture and compare to reference. 12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int isIntegerFormat = isFormatTypeInteger(m_format.type); 12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage reference (m_textureType, m_format, imageSize.x(), imageSize.y(), imageSize.z()); 12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!isIntegerFormat || (storeColorScale == 1.0f && storeColorBias == 0.0f)); 12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec4 color(x^y^z, (imageSize.x()-1-x)^y^z, x^(imageSize.y()-1-y)^z, (imageSize.x()-1-x)^(imageSize.y()-1-y)^z); 12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isIntegerFormat) 12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, z, color); 12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, z, color.asFloat()*storeColorScale + storeColorBias); 12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool compareOk = readTextureAndVerify(renderCtx, glLog, *texture, *textureBuf, m_textureType, m_format, imageSize, ImageLayerComparer(reference)); 12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, compareOk ? "Pass" : "Image comparison failed"); 12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Case that copies an image to another, using imageLoad() and imageStore(). Texture formats don't necessarily match image formats. 12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ImageLoadAndStoreCase : public TestCase 12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum CaseFlag 12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CASEFLAG_SINGLE_LAYER_BIND = 1 << 0, //!< If given, glBindImageTexture() is called with GL_FALSE <layered> argument, and for each layer the compute shader is separately dispatched. 12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CASEFLAG_RESTRICT_IMAGES = 1 << 1 //!< If given, images in shader will be qualified with "restrict". 12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ImageLoadAndStoreCase (Context& context, const char* name, const char* description, const TextureFormat& format, TextureType textureType, deUint32 caseFlags = 0) 12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_textureFormat (format) 12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageFormat (format) 12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_textureType (textureType) 12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_restrictImages ((caseFlags & CASEFLAG_RESTRICT_IMAGES) != 0) 12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_singleLayerBind ((caseFlags & CASEFLAG_SINGLE_LAYER_BIND) != 0) 12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ImageLoadAndStoreCase (Context& context, const char* name, const char* description, const TextureFormat& textureFormat, const TextureFormat& imageFormat, TextureType textureType, deUint32 caseFlags = 0) 12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_textureFormat (textureFormat) 12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageFormat (imageFormat) 12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_textureType (textureType) 12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_restrictImages ((caseFlags & CASEFLAG_RESTRICT_IMAGES) != 0) 12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_singleLayerBind ((caseFlags & CASEFLAG_SINGLE_LAYER_BIND) != 0) 12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(textureFormat.getPixelSize() == imageFormat.getPixelSize()); 12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void) { checkTextureTypeExtensions(m_context.getContextInfo(), m_textureType); } 12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry template <TextureFormat::ChannelType ImageFormatType, typename TcuFloatType, typename TcuFloatStorageType> 12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static void replaceBadFloatReinterpretValues (LayeredImage& image, const TextureFormat& imageFormat); 12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_textureFormat; 12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_imageFormat; 12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_textureType; 12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool m_restrictImages; 12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool m_singleLayerBind; 12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureFormat::ChannelType ImageFormatType, typename TcuFloatType, typename TcuFloatTypeStorageType> 13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ImageLoadAndStoreCase::replaceBadFloatReinterpretValues (LayeredImage& image, const TextureFormat& imageFormat) 13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Find potential bad values, such as nan or inf, and replace with something else. 13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int pixelSize = imageFormat.getPixelSize(); 13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int imageNumChannels = imageFormat.order == tcu::TextureFormat::R ? 1 13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageFormat.order == tcu::TextureFormat::RGBA ? 4 13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : 0; 13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 imageSize = image.getSize(); 13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = image.getImageType() == TEXTURETYPE_CUBE ? 6 : imageSize.z(); 13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(pixelSize % imageNumChannels == 0); 13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PixelBufferAccess sliceAccess = image.getImageType() == TEXTURETYPE_CUBE ? image.getCubeFaceAccess((tcu::CubeFace)z) : image.getSliceAccess(z); 13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int rowPitch = sliceAccess.getRowPitch(); 13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void *const data = sliceAccess.getDataPtr(); 13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void *const pixelData = (deUint8*)data + y*rowPitch + x*pixelSize; 13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int c = 0; c < imageNumChannels; c++) 13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void *const channelData = (deUint8*)pixelData + c*pixelSize/imageNumChannels; 13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TcuFloatType f (*(TcuFloatTypeStorageType*)channelData); 13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (f.isDenorm() || f.isInf() || f.isNaN()) 13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(TcuFloatTypeStorageType*)channelData = TcuFloatType(0.0f).bits(); 13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13373c827367444ee418f129b2c238299f49d3264554Jarkko PoyryImageLoadAndStoreCase::IterateResult ImageLoadAndStoreCase::iterate (void) 13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const RenderContext& renderCtx = m_context.getRenderContext(); 13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log (m_testCtx.getLog()); 13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper glLog (renderCtx.getFunctions(), log); 13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureInternalFormatGL = glu::getInternalFormat(m_textureFormat); 13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 imageInternalFormatGL = glu::getInternalFormat(m_imageFormat); 13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(m_textureType); 13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& imageSize = defaultImageSize(m_textureType); 13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxImageDimension = de::max(imageSize.x(), de::max(imageSize.y(), imageSize.z())); 13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float storeColorScale = isFormatTypeUnorm(m_textureFormat.type) ? 1.0f / (float)(maxImageDimension - 1) 13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : isFormatTypeSnorm(m_textureFormat.type) ? 2.0f / (float)(maxImageDimension - 1) 13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : 1.0f; 13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float storeColorBias = isFormatTypeSnorm(m_textureFormat.type) ? -1.0f : 0.0f; 13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = m_textureType == TEXTURETYPE_CUBE ? 6 : imageSize.z(); 13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isIntegerTextureFormat = isFormatTypeInteger(m_textureFormat.type); 13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer texture0Buf (renderCtx); 13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer texture1Buf (renderCtx); 13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture texture0 (renderCtx); 13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture texture1 (renderCtx); 13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage reference (m_textureType, m_textureFormat, imageSize.x(), imageSize.y(), imageSize.z()); 13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.enableLogging(true); 13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup textures. 13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created 2 textures (names " << *texture0 << " and " << *texture1 << ")" << TestLog::EndMessage; 13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_textureType == TEXTURETYPE_BUFFER) 13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created buffers for the textures (names " << *texture0Buf << " and " << *texture1Buf << ")" << TestLog::EndMessage; 13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // First, fill reference with (a fairly arbitrary) initial pattern. This will be used as texture upload source data as well as for actual reference computation later on. 13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!isIntegerTextureFormat || (storeColorScale == 1.0f && storeColorBias == 0.0f)); 13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec4 color(x^y^z, (imageSize.x()-1-x)^y^z, x^(imageSize.y()-1-y)^z, (imageSize.x()-1-x)^(imageSize.y()-1-y)^z); 13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isIntegerTextureFormat) 13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, z, color); 13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, z, color.asFloat()*storeColorScale + storeColorBias); 13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If re-interpreting the texture contents as floating point values, need to get rid of inf, nan etc. 13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_imageFormat.type == TextureFormat::HALF_FLOAT && m_textureFormat.type != TextureFormat::HALF_FLOAT) 13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry replaceBadFloatReinterpretValues<TextureFormat::HALF_FLOAT, tcu::Float16, deUint16>(reference, m_imageFormat); 13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (m_imageFormat.type == TextureFormat::FLOAT && m_textureFormat.type != TextureFormat::FLOAT) 13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry replaceBadFloatReinterpretValues<TextureFormat::FLOAT, tcu::Float32, deUint32>(reference, m_imageFormat); 13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Upload initial pattern to texture 0. 13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *texture0); 13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Filling texture " << *texture0 << " with xor pattern" << TestLog::EndMessage; 13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uploadTexture(glLog, reference, *texture0Buf); 13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set storage for texture 1. 14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE1); 14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *texture1); 14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, m_textureType, textureInternalFormatGL, imageSize, *texture1Buf); 14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform image loads and stores in compute shader and finalize reference computation. 14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Generate compute shader. 14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const maybeRestrict = m_restrictImages ? "restrict" : ""; 14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageFormatStr = getShaderImageFormatQualifier(m_imageFormat); 14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType shaderImageType = m_singleLayerBind ? textureLayerType(m_textureType) : m_textureType; 14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageTypeStr = getShaderImageType(m_imageFormat.type, shaderImageType); 14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource("#version 310 es\n" 14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + textureTypeExtensionShaderRequires(shaderImageType) + 14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp " + shaderImageTypeStr + ";\n" 14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=0) " + maybeRestrict + " readonly uniform " + shaderImageTypeStr + " u_image0;\n" 14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=1) " + maybeRestrict + " writeonly uniform " + shaderImageTypeStr + " u_image1;\n" 14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (shaderImageType == TEXTURETYPE_BUFFER ? 14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int pos = int(gl_GlobalInvocationID.x);\n" 14308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry " imageStore(u_image1, pos, imageLoad(u_image0, " + toString(imageSize.x()-1) + "-pos));\n" 14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : shaderImageType == TEXTURETYPE_2D ? 14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n" 14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + toString(imageSize.x()-1) + "-pos.x, pos.y)));\n" 14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : shaderImageType == TEXTURETYPE_3D || shaderImageType == TEXTURETYPE_CUBE || shaderImageType == TEXTURETYPE_2D_ARRAY ? 14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " ivec3 pos = ivec3(gl_GlobalInvocationID);\n" 14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + toString(imageSize.x()-1) + "-pos.x, pos.y, pos.z)));\n" 14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL) + 14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms(renderCtx.getFunctions(), log, program.getProgram()); 14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program compilation failed"); 14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup and dispatch. 14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_singleLayerBind) 14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int layerNdx = 0; layerNdx < numSlicesOrFaces; layerNdx++) 14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (layerNdx > 0) 14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *texture0, 0, GL_FALSE, layerNdx, GL_READ_ONLY, imageInternalFormatGL); 14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(1, *texture1, 0, GL_FALSE, layerNdx, GL_WRITE_ONLY, imageInternalFormatGL); 14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(imageSize.x(), imageSize.y(), 1); 14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *texture0, 0, GL_TRUE, 0, GL_READ_ONLY, imageInternalFormatGL); 14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(1, *texture1, 0, GL_TRUE, 0, GL_WRITE_ONLY, imageInternalFormatGL); 14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(imageSize.x(), imageSize.y(), numSlicesOrFaces); 14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Finalize reference. 14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_textureFormat != m_imageFormat) 14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Format re-interpretation case. Read data with image format and write back, with the same image format. 14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // We do this because the data may change a little during lookups (e.g. unorm8 -> float; not all unorms can be exactly represented as floats). 14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int pixelSize = m_imageFormat.getPixelSize(); 14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureLevel scratch (m_imageFormat, 1, 1); 14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PixelBufferAccess scratchAccess = scratch.getAccess(); 14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PixelBufferAccess sliceAccess = m_textureType == TEXTURETYPE_CUBE ? reference.getCubeFaceAccess((tcu::CubeFace)z) : reference.getSliceAccess(z); 14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int rowPitch = sliceAccess.getRowPitch(); 14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void *const data = sliceAccess.getDataPtr(); 14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void *const pixelData = (deUint8*)data + y*rowPitch + x*pixelSize; 15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy(scratchAccess.getDataPtr(), pixelData, pixelSize); 15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isFormatTypeInteger(m_imageFormat.type)) 15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry scratchAccess.setPixel(scratchAccess.getPixelUint(0, 0), 0, 0); 15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry scratchAccess.setPixel(scratchAccess.getPixel(0, 0), 0, 0); 15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy(pixelData, scratchAccess.getDataPtr(), pixelSize); 15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x()/2; x++) 15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isIntegerTextureFormat) 15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const UVec4 temp = reference.getPixelUint(imageSize.x()-1-x, y, z); 15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(imageSize.x()-1-x, y, z, reference.getPixelUint(x, y, z)); 15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, z, temp); 15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec4 temp = reference.getPixel(imageSize.x()-1-x, y, z); 15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(imageSize.x()-1-x, y, z, reference.getPixel(x, y, z)); 15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, z, temp); 15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read texture 1 and compare to reference. 15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool compareOk = readTextureAndVerify(renderCtx, glLog, *texture1, *texture1Buf, m_textureType, m_textureFormat, imageSize, ImageLayerComparer(reference)); 15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, compareOk ? "Pass" : "Image comparison failed"); 15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum AtomicOperationCaseType 15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_CASE_TYPE_END_RESULT = 0, //!< Atomic case checks the end result of the operations, and not the return values. 15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES, //!< Atomic case checks the return values of the atomic function, and not the end result. 15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ATOMIC_OPERATION_CASE_TYPE_LAST 15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*! 15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Binary atomic operation case. 15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Case that performs binary atomic operations (i.e. any but compSwap) and 15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * verifies according to the given AtomicOperationCaseType. 15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * For the "end result" case type, a single texture (and image) is created, 15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * upon which the atomic operations operate. A compute shader is dispatched 15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * with dimensions equal to the image size, except with a bigger X size 15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * so that every pixel is operated on by multiple invocations. The end 15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * results are verified in BinaryAtomicOperationCase::EndResultVerifier. 15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The return values of the atomic function calls are ignored. 15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * For the "return value" case type, the case does much the same operations 15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * as in the "end result" case, but also creates an additional texture, 15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * of size equal to the dispatch size, into which the return values of the 15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * atomic functions are stored (with imageStore()). The return values are 15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * verified in BinaryAtomicOperationCase::ReturnValueVerifier. 15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The end result values are not checked. 15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The compute shader invocations contributing to a pixel (X, Y, Z) in the 15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * end result image are the invocations with global IDs 15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * (X, Y, Z), (X+W, Y, Z), (X+2*W, Y, Z), ..., (X+(N-1)*W, Y, W), where W 15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * is the width of the end result image and N is 15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * BinaryAtomicOperationCase::NUM_INVOCATIONS_PER_PIXEL. 15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BinaryAtomicOperationCase : public TestCase 15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BinaryAtomicOperationCase (Context& context, const char* name, const char* description, const TextureFormat& format, TextureType imageType, AtomicOperation operation, AtomicOperationCaseType caseType) 15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_format (format) 15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageType (imageType) 15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_operation (operation) 15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_caseType (caseType) 15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_format == TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32) || 15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_format == TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT32) || 15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (m_format == TextureFormat(TextureFormat::R, TextureFormat::FLOAT) && m_operation == ATOMIC_OPERATION_EXCHANGE)); 15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_operation != ATOMIC_OPERATION_COMP_SWAP); 15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void); 15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry class EndResultVerifier; 16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry class ReturnValueVerifier; 16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static int getOperationInitialValue (AtomicOperation op); //!< Appropriate value with which to initialize the texture. 16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //! Compute the argument given to the atomic function at the given invocation ID, when the entire dispatch has the given width and height. 16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static int getAtomicFuncArgument (AtomicOperation op, const IVec3& invocationID, const IVec2& dispatchSizeXY); 16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //! Generate the shader expression for the argument given to the atomic function. x, y and z are the identifiers for the invocation ID components. 16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static string getAtomicFuncArgumentShaderStr (AtomicOperation op, const string& x, const string& y, const string& z, const IVec2& dispatchSizeXY); 16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const int NUM_INVOCATIONS_PER_PIXEL = 5; 16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_format; 16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperation m_operation; 16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperationCaseType m_caseType; 16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint BinaryAtomicOperationCase::getOperationInitialValue (AtomicOperation op) 16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (op) 16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note 18 is just an arbitrary small nonzero value. 16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_ADD: return 18; 16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MIN: return (1<<15) - 1; 16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MAX: return 18; 16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_AND: return (1<<15) - 1; 16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_OR: return 18; 16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_XOR: return 18; 16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_EXCHANGE: return 18; 16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return -1; 16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint BinaryAtomicOperationCase::getAtomicFuncArgument (AtomicOperation op, const IVec3& invocationID, const IVec2& dispatchSizeXY) 16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int x = invocationID.x(); 16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int y = invocationID.y(); 16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int z = invocationID.z(); 16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int wid = dispatchSizeXY.x(); 16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int hei = dispatchSizeXY.y(); 16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (op) 16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Fall-throughs. 16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_ADD: 16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MIN: 16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MAX: 16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_AND: 16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_OR: 16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_XOR: 16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return x*x + y*y + z*z; 16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_EXCHANGE: 16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (z*wid + x)*hei + y; 16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return -1; 16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring BinaryAtomicOperationCase::getAtomicFuncArgumentShaderStr (AtomicOperation op, const string& x, const string& y, const string& z, const IVec2& dispatchSizeXY) 16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (op) 16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Fall-throughs. 16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_ADD: 16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MIN: 16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_MAX: 16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_AND: 16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_OR: 16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_XOR: 16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "("+ x+"*"+x +" + "+ y+"*"+y +" + "+ z+"*"+z +")"; 16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case ATOMIC_OPERATION_EXCHANGE: 16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "((" + z + "*" + toString(dispatchSizeXY.x()) + " + " + x + ")*" + toString(dispatchSizeXY.y()) + " + " + y + ")"; 16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_NULL; 16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BinaryAtomicOperationCase::EndResultVerifier : public ImageLayerVerifier 16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry EndResultVerifier (AtomicOperation operation, TextureType imageType) : m_operation(operation), m_imageType(imageType) {} 16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool operator() (TestLog& log, const ConstPixelBufferAccess& resultSlice, int sliceOrFaceNdx) const 16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isIntegerFormat = isFormatTypeInteger(resultSlice.getFormat().type); 16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 dispatchSizeXY (NUM_INVOCATIONS_PER_PIXEL*resultSlice.getWidth(), resultSlice.getHeight()); 16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Image("EndResults" + toString(sliceOrFaceNdx), 16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "Result Values, " + (m_imageType == TEXTURETYPE_CUBE ? "face " + string(glu::getCubeMapFaceName(cubeFaceToGLFace(glslImageFuncZToCubeFace(sliceOrFaceNdx)))) 16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "slice " + toString(sliceOrFaceNdx)), 16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resultSlice); 16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < resultSlice.getHeight(); y++) 17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < resultSlice.getWidth(); x++) 17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry union 17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int i; 17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float f; 17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } result; 17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isIntegerFormat) 17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.i = resultSlice.getPixelInt(x, y).x(); 17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.f = resultSlice.getPixel(x, y).x(); 17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute the arguments that were given to the atomic function in the invocations that contribute to this pixel. 17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3 invocationGlobalIDs[NUM_INVOCATIONS_PER_PIXEL]; 17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int atomicArgs[NUM_INVOCATIONS_PER_PIXEL]; 17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL; i++) 17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 gid(x + i*resultSlice.getWidth(), y, sliceOrFaceNdx); 17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry invocationGlobalIDs[i] = gid; 17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry atomicArgs[i] = getAtomicFuncArgument(m_operation, gid, dispatchSizeXY); 17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isOrderIndependentAtomicOperation(m_operation)) 17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Just accumulate the atomic args (and the initial value) according to the operation, and compare. 17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isIntegerFormat); 17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int reference = getOperationInitialValue(m_operation); 17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL; i++) 17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference = computeBinaryAtomicOperationResult(m_operation, reference, atomicArgs[i]); 17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (result.i != reference) 17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Failure: end result at pixel " << IVec2(x, y) << " of current layer is " << result.i << TestLog::EndMessage 17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: relevant shader invocation global IDs are " << arrayStr(invocationGlobalIDs) << TestLog::EndMessage 17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: data expression values for the IDs are " << arrayStr(atomicArgs) << TestLog::EndMessage 17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: reference value is " << reference << TestLog::EndMessage; 17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (m_operation == ATOMIC_OPERATION_EXCHANGE) 17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check that the end result equals one of the atomic args. 17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool matchFound = false; 17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL && !matchFound; i++) 17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry matchFound = isIntegerFormat ? result.i == atomicArgs[i] 17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : de::abs(result.f - (float)atomicArgs[i]) <= 0.01f; 17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!matchFound) 17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Failure: invalid value at pixel " << IVec2(x, y) << ": got " << (isIntegerFormat ? toString(result.i) : toString(result.f)) << TestLog::EndMessage 17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: expected one of " << arrayStr(atomicArgs) << TestLog::EndMessage; 17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperation m_operation; 17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BinaryAtomicOperationCase::ReturnValueVerifier : public ImageLayerVerifier 17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //! \note endResultImageLayerSize is (width, height) of the image operated on by the atomic ops, and not the size of the image where the return values are stored. 17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ReturnValueVerifier (AtomicOperation operation, TextureType imageType, const IVec2& endResultImageLayerSize) : m_operation(operation), m_imageType(imageType), m_endResultImageLayerSize(endResultImageLayerSize) {} 17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool operator() (TestLog& log, const ConstPixelBufferAccess& resultSlice, int sliceOrFaceNdx) const 17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isIntegerFormat (isFormatTypeInteger(resultSlice.getFormat().type)); 17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 dispatchSizeXY (resultSlice.getWidth(), resultSlice.getHeight()); 17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(resultSlice.getWidth() == NUM_INVOCATIONS_PER_PIXEL*m_endResultImageLayerSize.x() && 17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resultSlice.getHeight() == m_endResultImageLayerSize.y() && 17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resultSlice.getDepth() == 1); 17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Image("ReturnValues" + toString(sliceOrFaceNdx), 17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "Per-Invocation Return Values, " 17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_imageType == TEXTURETYPE_CUBE ? "face " + string(glu::getCubeMapFaceName(cubeFaceToGLFace(glslImageFuncZToCubeFace(sliceOrFaceNdx)))) 17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "slice " + toString(sliceOrFaceNdx)), 17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resultSlice); 17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < m_endResultImageLayerSize.y(); y++) 17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < m_endResultImageLayerSize.x(); x++) 17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry union IntFloatArr 18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int i[NUM_INVOCATIONS_PER_PIXEL]; 18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float f[NUM_INVOCATIONS_PER_PIXEL]; 18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Get the atomic function args and return values for all the invocations that contribute to the pixel (x, y) in the current end result slice. 18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IntFloatArr returnValues; 18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IntFloatArr atomicArgs; 18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3 invocationGlobalIDs[NUM_INVOCATIONS_PER_PIXEL]; 18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2 pixelCoords[NUM_INVOCATIONS_PER_PIXEL]; 18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL; i++) 18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 pixCoord (x + i*m_endResultImageLayerSize.x(), y); 18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 gid (pixCoord.x(), pixCoord.y(), sliceOrFaceNdx); 18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry invocationGlobalIDs[i] = gid; 18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelCoords[i] = pixCoord; 18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isIntegerFormat) 18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValues.i[i] = resultSlice.getPixelInt(gid.x(), y).x(); 18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry atomicArgs.i[i] = getAtomicFuncArgument(m_operation, gid, dispatchSizeXY); 18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValues.f[i] = resultSlice.getPixel(gid.x(), y).x(); 18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry atomicArgs.f[i] = (float)getAtomicFuncArgument(m_operation, gid, dispatchSizeXY); 18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Verify that the return values form a valid sequence. 18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool success = isIntegerFormat ? verifyOperationAccumulationIntermediateValues(m_operation, 18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getOperationInitialValue(m_operation), 18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry atomicArgs.i, 18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValues.i) 18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : verifyOperationAccumulationIntermediateValues(m_operation, 18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (float)getOperationInitialValue(m_operation), 18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry atomicArgs.f, 18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValues.f); 18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!success) 18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Failure: intermediate return values at pixels " << arrayStr(pixelCoords) << " of current layer are " 18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << (isIntegerFormat ? arrayStr(returnValues.i) : arrayStr(returnValues.f)) << TestLog::EndMessage 18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: relevant shader invocation global IDs are " << arrayStr(invocationGlobalIDs) << TestLog::EndMessage 18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: data expression values for the IDs are " 18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << (isIntegerFormat ? arrayStr(atomicArgs.i) : arrayStr(atomicArgs.f)) 18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "; return values are not a valid result for any order of operations" << TestLog::EndMessage; 18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperation m_operation; 18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 m_endResultImageLayerSize; 18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //! Check whether there exists an ordering of args such that { init*A", init*A*B, ..., init*A*B*...*LAST } is the "returnValues" sequence, where { A, B, ..., LAST } is args, and * denotes the operation. 18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // That is, whether "returnValues" is a valid sequence of intermediate return values when "operation" has been accumulated on "args" (and "init") in some arbitrary order. 18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry template <typename T> 18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static bool verifyOperationAccumulationIntermediateValues (AtomicOperation operation, T init, const T (&args)[NUM_INVOCATIONS_PER_PIXEL], const T (&returnValues)[NUM_INVOCATIONS_PER_PIXEL]) 18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool argsUsed[NUM_INVOCATIONS_PER_PIXEL] = { false }; 18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyRecursive(operation, 0, init, argsUsed, args, returnValues); 18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static bool compare (int a, int b) { return a == b; } 18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static bool compare (float a, float b) { return de::abs(a - b) <= 0.01f; } 18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //! Depth-first search for verifying the return value sequence. 18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry template <typename T> 18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static bool verifyRecursive (AtomicOperation operation, int index, T valueSoFar, bool (&argsUsed)[NUM_INVOCATIONS_PER_PIXEL], const T (&args)[NUM_INVOCATIONS_PER_PIXEL], const T (&returnValues)[NUM_INVOCATIONS_PER_PIXEL]) 18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (index < NUM_INVOCATIONS_PER_PIXEL) 18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL; i++) 18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!argsUsed[i] && compare(returnValues[i], valueSoFar)) 18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry argsUsed[i] = true; 18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (verifyRecursive(operation, index+1, computeBinaryAtomicOperationResult(operation, valueSoFar, args[i]), argsUsed, args, returnValues)) 18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry argsUsed[i] = false; 18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BinaryAtomicOperationCase::init (void) 19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_image_atomic")) 19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("Test requires OES_shader_image_atomic extension"); 19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry checkTextureTypeExtensions(m_context.getContextInfo(), m_imageType); 19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19123c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBinaryAtomicOperationCase::IterateResult BinaryAtomicOperationCase::iterate (void) 19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const RenderContext& renderCtx = m_context.getRenderContext(); 19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log (m_testCtx.getLog()); 19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper glLog (renderCtx.getFunctions(), log); 19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 internalFormatGL = glu::getInternalFormat(m_format); 19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(m_imageType); 19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& imageSize = defaultImageSize(m_imageType); 19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = m_imageType == TEXTURETYPE_CUBE ? 6 : imageSize.z(); 19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isUintFormat = isFormatTypeUnsignedInteger(m_format.type); 19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isIntFormat = isFormatTypeSignedInteger(m_format.type); 19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer endResultTextureBuf (renderCtx); 19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer returnValueTextureBuf (renderCtx); 19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture endResultTexture (renderCtx); //!< Texture for the final result; i.e. the texture on which the atomic operations are done. Size imageSize. 19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture returnValueTexture (renderCtx); //!< Texture into which the return values are stored if m_caseType == CASETYPE_RETURN_VALUES. 19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Size imageSize*IVec3(N, 1, 1) or, for cube maps, imageSize*IVec3(N, N, 1) where N is NUM_INVOCATIONS_PER_PIXEL. 19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.enableLogging(true); 19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup textures. 19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *endResultTexture << ") to act as the target of atomic operations" << TestLog::EndMessage; 19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_imageType == TEXTURETYPE_BUFFER) 19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a buffer for the texture (name " << *endResultTextureBuf << ")" << TestLog::EndMessage; 19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES) 19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *returnValueTexture << ") to which the intermediate return values of the atomic operation are stored" << TestLog::EndMessage; 19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_imageType == TEXTURETYPE_BUFFER) 19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a buffer for the texture (name " << *returnValueTextureBuf << ")" << TestLog::EndMessage; 19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Fill endResultTexture with initial pattern. 19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const LayeredImage imageData(m_imageType, m_format, imageSize.x(), imageSize.y(), imageSize.z()); 19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec4 initial(getOperationInitialValue(m_operation)); 19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageData.setPixel(x, y, z, initial); 19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Upload initial pattern to endResultTexture and bind to image. 19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *endResultTexture); 19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Filling end-result texture with initial pattern (initial value " << getOperationInitialValue(m_operation) << ")" << TestLog::EndMessage; 19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uploadTexture(glLog, imageData, *endResultTextureBuf); 19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *endResultTexture, 0, GL_TRUE, 0, GL_READ_WRITE, internalFormatGL); 19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES) 19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set storage for returnValueTexture and bind to image. 19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE1); 19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *returnValueTexture); 19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Setting storage of return-value texture" << TestLog::EndMessage; 19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, m_imageType, internalFormatGL, imageSize * (m_imageType == TEXTURETYPE_CUBE ? IVec3(NUM_INVOCATIONS_PER_PIXEL, NUM_INVOCATIONS_PER_PIXEL, 1) 19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : IVec3(NUM_INVOCATIONS_PER_PIXEL, 1, 1)), 19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *returnValueTextureBuf); 19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(1, *returnValueTexture, 0, GL_TRUE, 0, GL_WRITE_ONLY, internalFormatGL); 19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform image stores in compute shader and finalize reference computation. 19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Generate compute shader. 19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string colorVecTypeName = string(isUintFormat ? "u" : isIntFormat ? "i" : "") + "vec4"; 19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string atomicCoord = m_imageType == TEXTURETYPE_BUFFER ? "gx % " + toString(imageSize.x()) 19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D ? "ivec2(gx % " + toString(imageSize.x()) + ", gy)" 19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "ivec3(gx % " + toString(imageSize.x()) + ", gy, gz)"; 19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string invocationCoord = m_imageType == TEXTURETYPE_BUFFER ? "gx" 19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D ? "ivec2(gx, gy)" 20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "ivec3(gx, gy, gz)"; 20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string atomicArgExpr = (isUintFormat ? "uint" 20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : isIntFormat ? "" 20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "float") 20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + getAtomicFuncArgumentShaderStr(m_operation, "gx", "gy", "gz", IVec2(NUM_INVOCATIONS_PER_PIXEL*imageSize.x(), imageSize.y())); 20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string atomicInvocation = string() + getAtomicOperationShaderFuncName(m_operation) + "(u_results, " + atomicCoord + ", " + atomicArgExpr + ")"; 20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format); 20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageTypeStr = getShaderImageType(m_format.type, m_imageType); 20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource("#version 310 es\n" 20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "#extension GL_OES_shader_image_atomic : require\n" 20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + textureTypeExtensionShaderRequires(m_imageType) + 20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp " + shaderImageTypeStr + ";\n" 20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=0) coherent uniform " + shaderImageTypeStr + " u_results;\n" 20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? 20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=1) writeonly uniform " + shaderImageTypeStr + " u_returnValues;\n" 20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "") + 20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gx = int(gl_GlobalInvocationID.x);\n" 20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gy = int(gl_GlobalInvocationID.y);\n" 20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gz = int(gl_GlobalInvocationID.z);\n" 20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? 20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_returnValues, " + invocationCoord + ", " + colorVecTypeName + "(" + atomicInvocation + "));\n" 20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? 20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " " + atomicInvocation + ";\n" 20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL) + 20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms(renderCtx.getFunctions(), log, program.getProgram()); 20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program compilation failed"); 20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup and dispatch. 20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(NUM_INVOCATIONS_PER_PIXEL*imageSize.x(), imageSize.y(), numSlicesOrFaces); 20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read texture and check. 20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureToCheckGL = m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? *endResultTexture 20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? *returnValueTexture 20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (deUint32)-1; 20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureToCheckBufGL = m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? *endResultTextureBuf 20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? *returnValueTextureBuf 20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (deUint32)-1; 20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 textureToCheckSize = imageSize * IVec3(m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? 1 : NUM_INVOCATIONS_PER_PIXEL, 1, 1); 20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const UniquePtr<const ImageLayerVerifier> verifier (m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? new EndResultVerifier(m_operation, m_imageType) 20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? new ReturnValueVerifier(m_operation, m_imageType, imageSize.swizzle(0, 1)) 20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (ImageLayerVerifier*)DE_NULL); 20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (readTextureAndVerify(renderCtx, glLog, textureToCheckGL, textureToCheckBufGL, m_imageType, m_format, textureToCheckSize, *verifier)) 20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*! 20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Atomic compSwap operation case. 20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Similar in principle to BinaryAtomicOperationCase, but separated for 20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * convenience, since the atomic function is somewhat different. Like 20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * BinaryAtomicOperationCase, this has separate cases for checking end 20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * result and return values. 20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AtomicCompSwapCase : public TestCase 20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry AtomicCompSwapCase (Context& context, const char* name, const char* description, const TextureFormat& format, TextureType imageType, AtomicOperationCaseType caseType) 20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_format (format) 20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageType (imageType) 20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_caseType (caseType) 20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_format == TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32) || 20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_format == TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT32)); 20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void); 20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry class EndResultVerifier; 21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry class ReturnValueVerifier; 21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static int getCompareArg (const IVec3& invocationID, int imageWidth); 21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static int getAssignArg (const IVec3& invocationID, int imageWidth); 21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static string getCompareArgShaderStr (const string& x, const string& y, const string& z, int imageWidth); 21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static string getAssignArgShaderStr (const string& x, const string& y, const string& z, int imageWidth); 21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const int NUM_INVOCATIONS_PER_PIXEL = 5; 21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_format; 21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperationCaseType m_caseType; 21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint AtomicCompSwapCase::getCompareArg (const IVec3& invocationID, int imageWidth) 21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int x = invocationID.x(); 21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int y = invocationID.y(); 21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int z = invocationID.z(); 21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int wrapX = x % imageWidth; 21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int curPixelInvocationNdx = x / imageWidth; 21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return wrapX*wrapX + y*y + z*z + curPixelInvocationNdx*42; 21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint AtomicCompSwapCase::getAssignArg (const IVec3& invocationID, int imageWidth) 21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getCompareArg(IVec3(invocationID.x() + imageWidth, invocationID.y(), invocationID.z()), imageWidth); 21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring AtomicCompSwapCase::getCompareArgShaderStr (const string& x, const string& y, const string& z, int imageWidth) 21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string wrapX = "(" + x + "%" + toString(imageWidth) + ")"; 21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string curPixelInvocationNdx = "(" + x + "/" + toString(imageWidth) + ")"; 21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "(" +wrapX+"*"+wrapX+ " + " +y+"*"+y+ " + " +z+"*"+z+ " + " + curPixelInvocationNdx + "*42)"; 21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring AtomicCompSwapCase::getAssignArgShaderStr (const string& x, const string& y, const string& z, int imageWidth) 21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string wrapX = "(" + x + "%" + toString(imageWidth) + ")"; 21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string curPixelInvocationNdx = "(" + x + "/" + toString(imageWidth) + " + 1)"; 21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "(" +wrapX+"*"+wrapX+ " + " +y+"*"+y+ " + " +z+"*"+z+ " + " + curPixelInvocationNdx + "*42)"; 21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid AtomicCompSwapCase::init (void) 21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_image_atomic")) 21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("Test requires OES_shader_image_atomic extension"); 21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry checkTextureTypeExtensions(m_context.getContextInfo(), m_imageType); 21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AtomicCompSwapCase::EndResultVerifier : public ImageLayerVerifier 21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry EndResultVerifier (TextureType imageType, int imageWidth) : m_imageType(imageType), m_imageWidth(imageWidth) {} 21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool operator() (TestLog& log, const ConstPixelBufferAccess& resultSlice, int sliceOrFaceNdx) const 21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isFormatTypeInteger(resultSlice.getFormat().type)); 21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(resultSlice.getWidth() == m_imageWidth); 21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Image("EndResults" + toString(sliceOrFaceNdx), 21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "Result Values, " + (m_imageType == TEXTURETYPE_CUBE ? "face " + string(glu::getCubeMapFaceName(cubeFaceToGLFace(glslImageFuncZToCubeFace(sliceOrFaceNdx)))) 21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "slice " + toString(sliceOrFaceNdx)), 21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resultSlice); 21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < resultSlice.getHeight(); y++) 21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < resultSlice.getWidth(); x++) 21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute the value-to-assign arguments that were given to the atomic function in the invocations that contribute to this pixel. 21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // One of those should be the result. 21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int result = resultSlice.getPixelInt(x, y).x(); 21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3 invocationGlobalIDs[NUM_INVOCATIONS_PER_PIXEL]; 21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int assignArgs[NUM_INVOCATIONS_PER_PIXEL]; 21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL; i++) 21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 gid(x + i*resultSlice.getWidth(), y, sliceOrFaceNdx); 21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry invocationGlobalIDs[i] = gid; 21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry assignArgs[i] = getAssignArg(gid, m_imageWidth); 21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool matchFound = false; 21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL && !matchFound; i++) 21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry matchFound = result == assignArgs[i]; 21933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!matchFound) 21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Failure: invalid value at pixel " << IVec2(x, y) << ": got " << result << TestLog::EndMessage 21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: relevant shader invocation global IDs are " << arrayStr(invocationGlobalIDs) << TestLog::EndMessage 21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: expected one of " << arrayStr(assignArgs) 21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " (those are the values given as the 'data' argument in the invocations that contribute to this pixel)" 22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int m_imageWidth; 22123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AtomicCompSwapCase::ReturnValueVerifier : public ImageLayerVerifier 22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //! \note endResultImageLayerSize is (width, height) of the image operated on by the atomic ops, and not the size of the image where the return values are stored. 22183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ReturnValueVerifier (TextureType imageType, int endResultImageWidth) : m_imageType(imageType), m_endResultImageWidth(endResultImageWidth) {} 22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool operator() (TestLog& log, const ConstPixelBufferAccess& resultSlice, int sliceOrFaceNdx) const 22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isFormatTypeInteger(resultSlice.getFormat().type)); 22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(resultSlice.getWidth() == NUM_INVOCATIONS_PER_PIXEL*m_endResultImageWidth); 22243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Image("ReturnValues" + toString(sliceOrFaceNdx), 22263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "Per-Invocation Return Values, " 22273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_imageType == TEXTURETYPE_CUBE ? "face " + string(glu::getCubeMapFaceName(cubeFaceToGLFace(glslImageFuncZToCubeFace(sliceOrFaceNdx)))) 22283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "slice " + toString(sliceOrFaceNdx)), 22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resultSlice); 22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < resultSlice.getHeight(); y++) 22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < m_endResultImageWidth; x++) 22333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Get the atomic function args and return values for all the invocations that contribute to the pixel (x, y) in the current end result slice. 22353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int returnValues[NUM_INVOCATIONS_PER_PIXEL]; 22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int compareArgs[NUM_INVOCATIONS_PER_PIXEL]; 22383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3 invocationGlobalIDs[NUM_INVOCATIONS_PER_PIXEL]; 22393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2 pixelCoords[NUM_INVOCATIONS_PER_PIXEL]; 22403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL; i++) 22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 pixCoord (x + i*m_endResultImageWidth, y); 22443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 gid (pixCoord.x(), pixCoord.y(), sliceOrFaceNdx); 22453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelCoords[i] = pixCoord; 22473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry invocationGlobalIDs[i] = gid; 22483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValues[i] = resultSlice.getPixelInt(gid.x(), y).x(); 22493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry compareArgs[i] = getCompareArg(gid, m_endResultImageWidth); 22503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Verify that the return values form a valid sequence. 22533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Due to the way the compare and assign arguments to the atomic calls are organized 22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // among the different invocations contributing to the same pixel -- i.e. one invocation 22553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // compares to A and assigns B, another compares to B and assigns C, and so on, where 22568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry // A<B<C etc -- the first value in the return value sequence must be A, and each following 22578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry // value must be either the same as or the smallest value (among A, B, C, ...) bigger than 22588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry // the one just before it. E.g. sequences A A A A A A A A, A B C D E F G H and 22598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry // A A B B B C D E are all valid sequences (if there were 8 invocations contributing 22608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry // to each pixel). 22613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry int failingNdx = -1; 22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry int currentAtomicValueNdx = 0; 22678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry for (int i = 0; i < NUM_INVOCATIONS_PER_PIXEL; i++) 22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry if (returnValues[i] == compareArgs[currentAtomicValueNdx]) 22708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry continue; 22718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry if (i > 0 && returnValues[i] == compareArgs[currentAtomicValueNdx+1]) 22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry currentAtomicValueNdx++; 22748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry continue; 22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry failingNdx = i; 22778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry break; 22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry if (failingNdx >= 0) 22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Failure: intermediate return values at pixels " << arrayStr(pixelCoords) << " of current layer are " 22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << arrayStr(returnValues) << TestLog::EndMessage 22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::Message << "// Note: relevant shader invocation global IDs are " << arrayStr(invocationGlobalIDs) << TestLog::EndMessage 22868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << TestLog::Message << "// Note: 'compare' argument values for the IDs are " << arrayStr(compareArgs) << TestLog::EndMessage 22878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << TestLog::Message << "// Note: expected the return value sequence to fulfill the following conditions:\n" 22888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << "// - first value is " << compareArgs[0] << "\n" 22898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << "// - each value other than the first is either the same as the one just before it, or the smallest value (in the sequence " 22908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << arrayStr(compareArgs) << ") bigger than the one just before it" << TestLog::EndMessage; 22918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry if (failingNdx == 0) 22928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry log << TestLog::Message << "// Note: the first return value (" << returnValues[0] << ") isn't " << compareArgs[0] << TestLog::EndMessage; 22938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry else 22948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry log << TestLog::Message << "// Note: the return value at index " << failingNdx << " (value " << returnValues[failingNdx] << ") " 22958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << "is neither " << returnValues[failingNdx-1] << " (the one just before it) " 22968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << "nor " << compareArgs[arrayIndexOf(compareArgs, returnValues[failingNdx-1])+1] << " (the smallest value bigger than the one just before it)" 22978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << TestLog::EndMessage; 22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int m_endResultImageWidth; 23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23123c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAtomicCompSwapCase::IterateResult AtomicCompSwapCase::iterate (void) 23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const RenderContext& renderCtx = m_context.getRenderContext(); 23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log (m_testCtx.getLog()); 23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper glLog (renderCtx.getFunctions(), log); 23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 internalFormatGL = glu::getInternalFormat(m_format); 23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(m_imageType); 23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& imageSize = defaultImageSize(m_imageType); 23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = m_imageType == TEXTURETYPE_CUBE ? 6 : imageSize.z(); 23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isUintFormat = isFormatTypeUnsignedInteger(m_format.type); 23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isIntFormat = isFormatTypeSignedInteger(m_format.type); 23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer endResultTextureBuf (renderCtx); 23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer returnValueTextureBuf (renderCtx); 23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture endResultTexture (renderCtx); //!< Texture for the final result; i.e. the texture on which the atomic operations are done. Size imageSize. 23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture returnValueTexture (renderCtx); //!< Texture into which the return values are stored if m_caseType == CASETYPE_RETURN_VALUES. 23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Size imageSize*IVec3(N, 1, 1) or, for cube maps, imageSize*IVec3(N, N, 1) where N is NUM_INVOCATIONS_PER_PIXEL. 23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isUintFormat || isIntFormat); 23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.enableLogging(true); 23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup textures. 23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *endResultTexture << ") to act as the target of atomic operations" << TestLog::EndMessage; 23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_imageType == TEXTURETYPE_BUFFER) 23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a buffer for the texture (name " << *endResultTextureBuf << ")" << TestLog::EndMessage; 23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES) 23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *returnValueTexture << ") to which the intermediate return values of the atomic operation are stored" << TestLog::EndMessage; 23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_imageType == TEXTURETYPE_BUFFER) 23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a buffer for the texture (name " << *returnValueTextureBuf << ")" << TestLog::EndMessage; 23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Fill endResultTexture with initial pattern. 23473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const LayeredImage imageData(m_imageType, m_format, imageSize.x(), imageSize.y(), imageSize.z()); 23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageData.setPixel(x, y, z, IVec4(getCompareArg(IVec3(x, y, z), imageSize.x()))); 23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Upload initial pattern to endResultTexture and bind to image. 23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *endResultTexture); 23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Filling end-result texture with initial pattern" << TestLog::EndMessage; 23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uploadTexture(glLog, imageData, *endResultTextureBuf); 23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *endResultTexture, 0, GL_TRUE, 0, GL_READ_WRITE, internalFormatGL); 23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES) 23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set storage for returnValueTexture and bind to image. 23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE1); 23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *returnValueTexture); 23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Setting storage of return-value texture" << TestLog::EndMessage; 23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, m_imageType, internalFormatGL, imageSize * (m_imageType == TEXTURETYPE_CUBE ? IVec3(NUM_INVOCATIONS_PER_PIXEL, NUM_INVOCATIONS_PER_PIXEL, 1) 23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : IVec3(NUM_INVOCATIONS_PER_PIXEL, 1, 1)), 23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *returnValueTextureBuf); 23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(1, *returnValueTexture, 0, GL_TRUE, 0, GL_WRITE_ONLY, internalFormatGL); 23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform atomics in compute shader. 23903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Generate compute shader. 23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string colorScalarTypeName = isUintFormat ? "uint" : isIntFormat ? "int" : DE_NULL; 23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string colorVecTypeName = string(isUintFormat ? "u" : isIntFormat ? "i" : DE_NULL) + "vec4"; 23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string atomicCoord = m_imageType == TEXTURETYPE_BUFFER ? "gx % " + toString(imageSize.x()) 23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D ? "ivec2(gx % " + toString(imageSize.x()) + ", gy)" 23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "ivec3(gx % " + toString(imageSize.x()) + ", gy, gz)"; 23993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string invocationCoord = m_imageType == TEXTURETYPE_BUFFER ? "gx" 24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D ? "ivec2(gx, gy)" 24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "ivec3(gx, gy, gz)"; 24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format); 24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageTypeStr = getShaderImageType(m_format.type, m_imageType); 24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource("#version 310 es\n" 24073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "#extension GL_OES_shader_image_atomic : require\n" 24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + textureTypeExtensionShaderRequires(m_imageType) + 24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp " + shaderImageTypeStr + ";\n" 24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=0) coherent uniform " + shaderImageTypeStr + " u_results;\n" 24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? 24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=1) writeonly uniform " + shaderImageTypeStr + " u_returnValues;\n" 24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "") + 24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 24183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gx = int(gl_GlobalInvocationID.x);\n" 24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gy = int(gl_GlobalInvocationID.y);\n" 24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gz = int(gl_GlobalInvocationID.z);\n" 24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " " + colorScalarTypeName + " compare = " + colorScalarTypeName + getCompareArgShaderStr("gx", "gy", "gz", imageSize.x()) + ";\n" 24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " " + colorScalarTypeName + " data = " + colorScalarTypeName + getAssignArgShaderStr("gx", "gy", "gz", imageSize.x()) + ";\n" 24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " " + colorScalarTypeName + " status = " + colorScalarTypeName + "(-1);\n" 24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " status = imageAtomicCompSwap(u_results, " + atomicCoord + ", compare, data);\n" 24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? 24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_returnValues, " + invocationCoord + ", " + colorVecTypeName + "(status));\n" : 24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "") + 24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms(renderCtx.getFunctions(), log, program.getProgram()); 24333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 24353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 24373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program compilation failed"); 24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup and dispatch. 24433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(NUM_INVOCATIONS_PER_PIXEL*imageSize.x(), imageSize.y(), numSlicesOrFaces); 24473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 24483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 24493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Create reference, read texture and compare. 24513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 24533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureToCheckGL = m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? *endResultTexture 24543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? *returnValueTexture 24553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (deUint32)-1; 24563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureToCheckBufGL = m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? *endResultTextureBuf 24583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? *returnValueTextureBuf 24593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (deUint32)-1; 24603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Actual size of the texture being checked. 24623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 textureToCheckSize = imageSize * (m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? IVec3(1, 1, 1) 24633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_CUBE ? IVec3(NUM_INVOCATIONS_PER_PIXEL, NUM_INVOCATIONS_PER_PIXEL, 1) 24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : IVec3(NUM_INVOCATIONS_PER_PIXEL, 1, 1)); 24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // The relevant region of the texture being checked (potentially 24673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // different from actual texture size for cube maps, because cube maps 24683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // may have unused pixels due to square size restriction). 24693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 relevantRegion = imageSize * (m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? IVec3(1, 1, 1) 24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : IVec3(NUM_INVOCATIONS_PER_PIXEL, 1, 1)); 24713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const UniquePtr<const ImageLayerVerifier> verifier (m_caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? new EndResultVerifier(m_imageType, imageSize.x()) 24733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? new ReturnValueVerifier(m_imageType, imageSize.x()) 24743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (ImageLayerVerifier*)DE_NULL); 24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (readTextureAndVerify(renderCtx, glLog, textureToCheckGL, textureToCheckBufGL, m_imageType, m_format, relevantRegion, *verifier)) 24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Case testing the "coherent" or "volatile" qualifier, along with memoryBarrier() and barrier(). 24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CoherenceCase : public TestCase 24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum Qualifier 24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry QUALIFIER_COHERENT = 0, 24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry QUALIFIER_VOLATILE, 24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry QUALIFIER_LAST 24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 24963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CoherenceCase (Context& context, const char* name, const char* description, const TextureFormat& format, TextureType imageType, Qualifier qualifier) 24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_format (format) 25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageType (imageType) 25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_qualifier (qualifier) 25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(CoherenceCase::SHADER_READ_OFFSETS_Y) == DE_LENGTH_OF_ARRAY(CoherenceCase::SHADER_READ_OFFSETS_X) && 25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_LENGTH_OF_ARRAY(CoherenceCase::SHADER_READ_OFFSETS_Z) == DE_LENGTH_OF_ARRAY(CoherenceCase::SHADER_READ_OFFSETS_X)); 25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(qualifier == QUALIFIER_COHERENT || qualifier == QUALIFIER_VOLATILE); 25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_format == TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32) || 25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_format == TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT32) || 25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_format == TextureFormat(TextureFormat::R, TextureFormat::FLOAT)); 25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void) { checkTextureTypeExtensions(m_context.getContextInfo(), m_imageType); } 25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const int SHADER_READ_OFFSETS_X[4]; 25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const int SHADER_READ_OFFSETS_Y[4]; 25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const int SHADER_READ_OFFSETS_Z[4]; 25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const char* const SHADER_READ_OFFSETS_X_STR; 25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const char* const SHADER_READ_OFFSETS_Y_STR; 25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const char* const SHADER_READ_OFFSETS_Z_STR; 25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_format; 25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Qualifier m_qualifier; 25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int CoherenceCase::SHADER_READ_OFFSETS_X[4] = { 1, 4, 7, 10 }; 25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int CoherenceCase::SHADER_READ_OFFSETS_Y[4] = { 2, 5, 8, 11 }; 25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int CoherenceCase::SHADER_READ_OFFSETS_Z[4] = { 3, 6, 9, 12 }; 25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* const CoherenceCase::SHADER_READ_OFFSETS_X_STR = "int[]( 1, 4, 7, 10 )"; 25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* const CoherenceCase::SHADER_READ_OFFSETS_Y_STR = "int[]( 2, 5, 8, 11 )"; 25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* const CoherenceCase::SHADER_READ_OFFSETS_Z_STR = "int[]( 3, 6, 9, 12 )"; 25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25363c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCoherenceCase::IterateResult CoherenceCase::iterate (void) 25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const RenderContext& renderCtx = m_context.getRenderContext(); 25393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log (m_testCtx.getLog()); 25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper glLog (renderCtx.getFunctions(), log); 25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 internalFormatGL = glu::getInternalFormat(m_format); 25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(m_imageType); 25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& imageSize = defaultImageSize(m_imageType); 25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSlicesOrFaces = m_imageType == TEXTURETYPE_CUBE ? 6 : imageSize.z(); 25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isUintFormat = isFormatTypeUnsignedInteger(m_format.type); 25463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isIntFormat = isFormatTypeSignedInteger(m_format.type); 25473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const qualifierName = m_qualifier == QUALIFIER_COHERENT ? "coherent" 25483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_qualifier == QUALIFIER_VOLATILE ? "volatile" 25493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer textureBuf (renderCtx); 25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture texture (renderCtx); 25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 numGroups = IVec3(16, de::min(16, imageSize.y()), de::min(2, numSlicesOrFaces)); 25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 workItemSize = IVec3(imageSize.x(), imageSize.y(), numSlicesOrFaces); 25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 localSize = workItemSize / numGroups; 25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 minReqMaxLocalSize = IVec3(128, 128, 64); 25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minReqMaxLocalInvocations = 128; 25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(workItemSize == localSize*numGroups); 25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(tcu::boolAll(tcu::lessThanEqual(localSize, minReqMaxLocalSize))); 25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(localSize.x()*localSize.y()*localSize.z() <= minReqMaxLocalInvocations); 25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(minReqMaxLocalSize); 25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(minReqMaxLocalInvocations); 25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.enableLogging(true); 25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup texture. 25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *texture << ")" << TestLog::EndMessage; 25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_imageType == TEXTURETYPE_BUFFER) 25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a buffer for the texture (name " << *textureBuf << ")" << TestLog::EndMessage; 25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *texture); 25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, m_imageType, internalFormatGL, imageSize, *textureBuf); 25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *texture, 0, GL_TRUE, 0, GL_READ_WRITE, internalFormatGL); 25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform computations in compute shader. 25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Generate compute shader. 25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string colorVecTypeName = string(isUintFormat ? "u" : isIntFormat ? "i" : "") + "vec4"; 25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const colorScalarTypeName = isUintFormat ? "uint" : isIntFormat ? "int" : "float"; 25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string invocationCoord = m_imageType == TEXTURETYPE_BUFFER ? "gx" 25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D ? "ivec2(gx, gy)" 25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "ivec3(gx, gy, gz)"; 25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format); 25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageTypeStr = getShaderImageType(m_format.type, m_imageType); 25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string localSizeX = de::toString(localSize.x()); 25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string localSizeY = de::toString(localSize.y()); 25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string localSizeZ = de::toString(localSize.z()); 25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 25963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource("#version 310 es\n" 25973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + textureTypeExtensionShaderRequires(m_imageType) + 25983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 25993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp " + shaderImageTypeStr + ";\n" 26003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 26013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (local_size_x = " + localSizeX 26023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + ", local_size_y = " + localSizeY 26033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + ", local_size_z = " + localSizeZ 26043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + ") in;\n" 26053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=0) " + qualifierName + " uniform " + shaderImageTypeStr + " u_image;\n" 26063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 26073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 26083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gx = int(gl_GlobalInvocationID.x);\n" 26093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gy = int(gl_GlobalInvocationID.y);\n" 26103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int gz = int(gl_GlobalInvocationID.z);\n" 26113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_image, " + invocationCoord + ", " + colorVecTypeName + "(gx^gy^gz));\n" 26123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 26133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " memoryBarrier();\n" 26143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " barrier();\n" 26153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 26163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " " + colorScalarTypeName + " sum = " + colorScalarTypeName + "(0);\n" 26173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int groupBaseX = gx/" + localSizeX + "*" + localSizeX + ";\n" 26183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int groupBaseY = gy/" + localSizeY + "*" + localSizeY + ";\n" 26193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int groupBaseZ = gz/" + localSizeZ + "*" + localSizeZ + ";\n" 26203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int xOffsets[] = " + SHADER_READ_OFFSETS_X_STR + ";\n" 26213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int yOffsets[] = " + SHADER_READ_OFFSETS_Y_STR + ";\n" 26223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int zOffsets[] = " + SHADER_READ_OFFSETS_Z_STR + ";\n" 26233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " for (int i = 0; i < " + toString(DE_LENGTH_OF_ARRAY(SHADER_READ_OFFSETS_X)) + "; i++)\n" 26243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " {\n" 26253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int readX = groupBaseX + (gx + xOffsets[i]) % " + localSizeX + ";\n" 26263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int readY = groupBaseY + (gy + yOffsets[i]) % " + localSizeY + ";\n" 26273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int readZ = groupBaseZ + (gz + zOffsets[i]) % " + localSizeZ + ";\n" 26283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " sum += imageLoad(u_image, " + (m_imageType == TEXTURETYPE_BUFFER ? "readX" 26293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D ? "ivec2(readX, readY)" 26303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : "ivec3(readX, readY, readZ)") + ").x;\n" 26313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " }\n" 26323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 26333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " memoryBarrier();\n" 26343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " barrier();\n" 26353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 26363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_image, " + invocationCoord + ", " + colorVecTypeName + "(sum));\n" 26373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 26383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms(renderCtx.getFunctions(), log, program.getProgram()); 26403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 26423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 26443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 26453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program compilation failed"); 26463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 26473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 26483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup and dispatch. 26503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 26523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(numGroups.x(), numGroups.y(), numGroups.z()); 26543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 26553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 26563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Create reference, read texture and compare. 26583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 26603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage reference(m_imageType, m_format, imageSize.x(), imageSize.y(), imageSize.z()); 26613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 26633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage base(m_imageType, m_format, imageSize.x(), imageSize.y(), imageSize.z()); 26643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 26653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 26663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 26673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry base.setPixel(x, y, z, IVec4(x^y^z)); 26683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int z = 0; z < numSlicesOrFaces; z++) 26703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < imageSize.y(); y++) 26713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < imageSize.x(); x++) 26723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 26733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupBaseX = x / localSize.x() * localSize.x(); 26743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupBaseY = y / localSize.y() * localSize.y(); 26753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupBaseZ = z / localSize.z() * localSize.z(); 26763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int sum = 0; 26773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < DE_LENGTH_OF_ARRAY(SHADER_READ_OFFSETS_X); i++) 26783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry sum += base.getPixelInt(groupBaseX + (x + SHADER_READ_OFFSETS_X[i]) % localSize.x(), 26793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry groupBaseY + (y + SHADER_READ_OFFSETS_Y[i]) % localSize.y(), 26803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry groupBaseZ + (z + SHADER_READ_OFFSETS_Z[i]) % localSize.z()).x(); 26813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, z, IVec4(sum)); 26833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 26843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 26853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (readTextureAndVerify(renderCtx, glLog, *texture, *textureBuf, m_imageType, m_format, imageSize, ImageLayerComparer(reference))) 26873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 26883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 26893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 26903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 26923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 26933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 26943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 26953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass R32UIImageSingleValueVerifier : public ImageLayerVerifier 26963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 26973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 26983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry R32UIImageSingleValueVerifier (const deUint32 value) : m_min(value), m_max(value) {} 26993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry R32UIImageSingleValueVerifier (const deUint32 min, const deUint32 max) : m_min(min), m_max(max) {} 27003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool operator() (TestLog& log, const ConstPixelBufferAccess& resultSlice, int) const 27023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 27033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(resultSlice.getWidth() == 1 && resultSlice.getHeight() == 1 && resultSlice.getDepth() == 1); 27043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(resultSlice.getFormat() == TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32)); 27053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Note: expecting to get value " << (m_min == m_max ? toString(m_min) : "in range [" + toString(m_min) + ", " + toString(m_max) + "]") << TestLog::EndMessage; 27073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 resultValue = resultSlice.getPixelUint(0, 0).x(); 27093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!de::inRange(resultValue, m_min, m_max)) 27103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 27113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Failure: got value " << resultValue << TestLog::EndMessage; 27123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 27133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 27143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 27153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 27163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Success: got value " << resultValue << TestLog::EndMessage; 27173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 27183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 27193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 27203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 27223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 m_min; 27233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 m_max; 27243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 27253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Tests the imageSize() GLSL function. Stores result in a 1x1 R32UI image. The image with which imageSize() is called isn't read or written, and 27273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// can thus be qualifier readonly, writeonly, or both. 27283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ImageSizeCase : public TestCase 27293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 27303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 27313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum ImageAccess 27323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 27333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IMAGEACCESS_READ_ONLY = 0, 27343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IMAGEACCESS_WRITE_ONLY, 27353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IMAGEACCESS_READ_ONLY_WRITE_ONLY, 27363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IMAGEACCESS_LAST 27383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 27393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ImageSizeCase (Context& context, const char* name, const char* description, const TextureFormat& format, TextureType imageType, const IVec3& size, ImageAccess imageAccess) 27413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 27423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_format (format) 27433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageType (imageType) 27443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageSize (size) 27453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_imageAccess (imageAccess) 27463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 27473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 27483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void) { checkTextureTypeExtensions(m_context.getContextInfo(), m_imageType); } 27503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 27513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 27533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat m_format; 27543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType m_imageType; 27553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 m_imageSize; 27563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ImageAccess m_imageAccess; 27573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 27583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryImageSizeCase::IterateResult ImageSizeCase::iterate (void) 27603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 27613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const RenderContext& renderCtx = m_context.getRenderContext(); 27623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log (m_testCtx.getLog()); 27633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper glLog (renderCtx.getFunctions(), log); 27643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 internalFormatGL = glu::getInternalFormat(m_format); 27653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 textureTargetGL = getGLTextureTarget(m_imageType); 27663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Buffer mainTextureBuf (renderCtx); 27673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture mainTexture (renderCtx); 27683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture shaderOutResultTexture (renderCtx); 27693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.enableLogging(true); 27713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup textures. 27733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *mainTexture << ")" << TestLog::EndMessage; 27753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_imageType == TEXTURETYPE_BUFFER) 27763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a buffer for the texture (name " << *mainTextureBuf << ")" << TestLog::EndMessage; 27773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *shaderOutResultTexture << ") for storing the shader output" << TestLog::EndMessage; 27783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 27803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(textureTargetGL, *mainTexture); 27813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, textureTargetGL); 27823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, m_imageType, internalFormatGL, m_imageSize, *mainTextureBuf); 27833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *mainTexture, 0, GL_TRUE, 0, GL_READ_WRITE, internalFormatGL); 27843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 27853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE1); 27873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(GL_TEXTURE_2D, *shaderOutResultTexture); 27883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, GL_TEXTURE_2D); 27893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTextureStorage(glLog, TEXTURETYPE_2D, GL_R32UI, IVec3(1, 1, 1), 0 /* always 2d texture, no buffer needed */); 27903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(1, *shaderOutResultTexture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI); 27913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 27923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read texture size in compute shader. 27943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 27963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Generate compute shader. 27973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 27983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const shaderImageAccessStr = m_imageAccess == IMAGEACCESS_READ_ONLY ? "readonly" 27993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageAccess == IMAGEACCESS_WRITE_ONLY ? "writeonly" 28003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageAccess == IMAGEACCESS_READ_ONLY_WRITE_ONLY ? "readonly writeonly" 28013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 28023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format); 28033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string shaderImageTypeStr = getShaderImageType(m_format.type, m_imageType); 28043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 28063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource("#version 310 es\n" 28073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + textureTypeExtensionShaderRequires(m_imageType) + 28083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 28093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp " + shaderImageTypeStr + ";\n" 28103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp uimage2D;\n" 28113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 28123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 28133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (" + shaderImageFormatStr + ", binding=0) " + shaderImageAccessStr + " uniform " + shaderImageTypeStr + " u_image;\n" 28143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (r32ui, binding=1) writeonly uniform uimage2D u_result;\n" 28153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 28163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 28173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + (m_imageType == TEXTURETYPE_BUFFER ? 28183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int result = imageSize(u_image);\n" 28193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D || m_imageType == TEXTURETYPE_CUBE ? 28203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " ivec2 size = imageSize(u_image);\n" 28213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int result = size.y*1000 + size.x;\n" 28223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_3D || m_imageType == TEXTURETYPE_2D_ARRAY ? 28233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " ivec3 size = imageSize(u_image);\n" 28243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " int result = size.z*1000000 + size.y*1000 + size.x;\n" 28253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL) + 28263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageStore(u_result, ivec2(0, 0), uvec4(result));\n" 28273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 28283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms(renderCtx.getFunctions(), log, program.getProgram()); 28303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 28323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 28343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 28353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program compilation failed"); 28363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 28373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 28383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup and dispatch. 28403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 28423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDispatchCompute(1, 1, 1); 28443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glDispatchCompute"); 28453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 28463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read texture and compare to reference. 28483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 28503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 referenceOutput = m_imageType == TEXTURETYPE_BUFFER ? (deUint32)( m_imageSize.x()) 28513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_2D || m_imageType == TEXTURETYPE_CUBE ? (deUint32)( m_imageSize.y()*1000 + m_imageSize.x()) 28523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_imageType == TEXTURETYPE_3D || m_imageType == TEXTURETYPE_2D_ARRAY ? (deUint32)(m_imageSize.z()*1000000 + m_imageSize.y()*1000 + m_imageSize.x()) 28533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (deUint32)-1; 28543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (readIntegerTextureViaFBOAndVerify(renderCtx, glLog, *shaderOutResultTexture, TEXTURETYPE_2D, TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32), 28563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3(1, 1, 1), R32UIImageSingleValueVerifier(referenceOutput))) 28573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 28583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 28593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got wrong value"); 28603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 28623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 28633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 28643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Case testing the control over early/late fragment tests. 28663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass EarlyFragmentTestsCase : public TestCase 28673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 28683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 28693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum TestType 28703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 28713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TESTTYPE_DEPTH = 0, 28723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TESTTYPE_STENCIL, 28733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TESTTYPE_LAST 28753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 28763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry EarlyFragmentTestsCase (Context& context, const char* name, const char* description, TestType type, bool useEarlyTests) 28783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 28793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_type (type) 28803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_useEarlyTests (useEarlyTests) 28813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 28823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 28833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void) 28853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 28863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) == 0) 28873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("GL_MAX_FRAGMENT_IMAGE_UNIFORMS is zero"); 28883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_image_atomic")) 28903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("Test requires OES_shader_image_atomic extension"); 28913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_context.getRenderTarget().getWidth() < RENDER_SIZE || m_context.getRenderTarget().getHeight() < RENDER_SIZE) 28933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("Render target must have at least " + toString(RENDER_SIZE) + " width and height"); 28943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 28953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 28973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 28983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 28993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const int RENDER_SIZE; 29003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TestType m_type; 29023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool m_useEarlyTests; 29033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 29043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int EarlyFragmentTestsCase::RENDER_SIZE = 32; 29063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29073c827367444ee418f129b2c238299f49d3264554Jarkko PoyryEarlyFragmentTestsCase::IterateResult EarlyFragmentTestsCase::iterate (void) 29083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 29093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const RenderContext& renderCtx = m_context.getRenderContext(); 29103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestLog& log (m_testCtx.getLog()); 29113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::CallLogWrapper glLog (renderCtx.getFunctions(), log); 29123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName())); 29133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int viewportWidth = RENDER_SIZE; 29143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int viewportHeight = RENDER_SIZE; 29153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int viewportX = rnd.getInt(0, renderCtx.getRenderTarget().getWidth() - viewportWidth); 29163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int viewportY = rnd.getInt(0, renderCtx.getRenderTarget().getHeight() - viewportHeight); 29173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 imageSize = defaultImageSize(TEXTURETYPE_2D); 29183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Texture texture (renderCtx); 29193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.enableLogging(true); 29213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup texture. 29233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Message << "// Created a texture (name " << *texture << ")" << TestLog::EndMessage; 29253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glActiveTexture(GL_TEXTURE0); 29273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindTexture(GL_TEXTURE_2D, *texture); 29283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry setTexParameteri(glLog, GL_TEXTURE_2D); 29293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 29303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LayeredImage src(TEXTURETYPE_2D, TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32), 1, 1, 1); 29313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src.setPixel(0, 0, 0, IVec4(0)); 29323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uploadTexture(glLog, src, 0 /* always 2d texture, no buffer needed */); 29333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 29343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glBindImageTexture(0, *texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32UI); 29353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "glBindImageTexture"); 29363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set up appropriate conditions for the test. 29383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 29403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClear(GL_COLOR_BUFFER_BIT); 29413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_type == TESTTYPE_DEPTH) 29433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 29443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClearDepthf(0.5f); 29453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClear(GL_DEPTH_BUFFER_BIT); 29463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glEnable(GL_DEPTH_TEST); 29473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 29483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (m_type == TESTTYPE_STENCIL) 29493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 29503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClearStencil(0); 29513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClear(GL_STENCIL_BUFFER_BIT); 29523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glScissor(viewportX, viewportY, viewportWidth/2, viewportHeight); 29533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glEnable(GL_SCISSOR_TEST); 29543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClearStencil(1); 29553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glClear(GL_STENCIL_BUFFER_BIT); 29563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glDisable(GL_SCISSOR_TEST); 29573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glStencilFunc(GL_EQUAL, 1, 1); 29583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 29593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glEnable(GL_STENCIL_TEST); 29603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 29613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 29623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 29633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform image stores in fragment shader. 29653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 29673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Generate fragment shader. 29683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::ShaderProgram program(renderCtx, 29703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::VertexSource( "#version 310 es\n" 29713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 29723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "highp in vec3 a_position;\n" 29733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 29743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 29753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 29763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " gl_Position = vec4(a_position, 1.0);\n" 29773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n") 29783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::FragmentSource( "#version 310 es\n" 29803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "#extension GL_OES_shader_image_atomic : require\n" 29813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 29823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + string(m_useEarlyTests ? "layout (early_fragment_tests) in;\n\n" : "") + 29833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (location = 0) out highp vec4 o_color;\n" 29843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 29853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "precision highp uimage2D;\n" 29863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 29873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "layout (r32ui, binding=0) coherent uniform uimage2D u_image;\n" 29883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "\n" 29893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "void main (void)\n" 29903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "{\n" 29913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " imageAtomicAdd(u_image, ivec2(0, 0), uint(1));\n" 29923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry " o_color = vec4(1.0);\n" 29933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "}\n")); 29943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniformAccessLogger uniforms(renderCtx.getFunctions(), log, program.getProgram()); 29963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << program; 29983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 29993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!program.isOk()) 30003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program compilation failed"); 30023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 30033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 30043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup and draw full-viewport quad. 30063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glUseProgram(program.getProgram()); 30083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const float vertexPositions[4*3] = 30113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry -1.0, -1.0, -1.0f, 30133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1.0, -1.0, 0.0f, 30143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry -1.0, 1.0, 0.0f, 30153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1.0, 1.0, 1.0f, 30163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 30173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 }; 30193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VertexArrayBinding attrBindings[] = 30213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::va::Float("a_position", 3, 4, 0, &vertexPositions[0]) 30233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 30243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glLog.glViewport(viewportX, viewportY, viewportWidth, viewportHeight); 30263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(attrBindings), &attrBindings[0], 30283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); 30293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(renderCtx.getFunctions().getError(), "Draw failed"); 30303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 30313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 30323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Log rendered result for convenience. 30343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Surface rendered(viewportWidth, viewportHeight); 30363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::readPixels(renderCtx, viewportX, viewportY, rendered.getAccess()); 30373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << TestLog::Image("Rendered", "Rendered image", rendered); 30383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 30393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read counter value and check. 30413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSamples = de::max(1, renderCtx.getRenderTarget().getNumSamples()); 30433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int expectedCounter = m_useEarlyTests ? viewportWidth*viewportHeight/2 : viewportWidth*viewportHeight; 30443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int tolerance = m_useEarlyTests ? de::max(viewportWidth, viewportHeight)*3 : 0; 30453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int expectedMin = de::max(0, expectedCounter - tolerance); 30463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int expectedMax = (expectedCounter + tolerance) * numSamples; 30473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (readIntegerTextureViaFBOAndVerify(renderCtx, glLog, *texture, TEXTURETYPE_2D, TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32), 30493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3(1, 1, 1), R32UIImageSingleValueVerifier(expectedMin, expectedMax))) 30503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 30513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 30523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got wrong value"); 30533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 30553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 30563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 30573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous 30593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30603c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderImageLoadStoreTests::ShaderImageLoadStoreTests (Context& context) 30613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCaseGroup(context, "image_load_store", "Shader Image Load & Store Tests") 30623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 30633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 30643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30653c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderImageLoadStoreTests::~ShaderImageLoadStoreTests (void) 30663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 30673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 30683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderImageLoadStoreTests::init (void) 30703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 30713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Per-image-type tests. 30723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const TextureType imageTypes[] = 30753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TEXTURETYPE_2D, 30773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TEXTURETYPE_CUBE, 30783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TEXTURETYPE_3D, 30793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TEXTURETYPE_2D_ARRAY, 30803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TEXTURETYPE_BUFFER 30813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 30823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const TextureFormat formats[] = 30843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 30853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT), 30863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::HALF_FLOAT), 30873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::R, TextureFormat::FLOAT), 30883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), 30903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT16), 30913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT8), 30923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32), 30933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32), 30953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT16), 30963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT8), 30973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT32), 30983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 30993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), 31003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TextureFormat(TextureFormat::RGBA, TextureFormat::SNORM_INT8) 31023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 31033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(imageTypes); imageTypeNdx++) 31053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 31063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureType imageType = imageTypes[imageTypeNdx]; 31073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const imageTypeGroup = new TestCaseGroup(m_context, getTextureTypeName(imageType), ""); 31083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(imageTypeGroup); 31093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const storeGroup = new TestCaseGroup(m_context, "store", "Plain imageStore() cases"); 31113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const loadStoreGroup = new TestCaseGroup(m_context, "load_store", "Cases with imageLoad() followed by imageStore()"); 31123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const atomicGroup = new TestCaseGroup(m_context, "atomic", "Atomic image operation cases"); 31133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const qualifierGroup = new TestCaseGroup(m_context, "qualifiers", "Coherent, volatile and restrict"); 31143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const reinterpretGroup = new TestCaseGroup(m_context, "format_reinterpret", "Cases with differing texture and image formats"); 31153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const imageSizeGroup = new TestCaseGroup(m_context, "image_size", "imageSize() cases"); 31163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageTypeGroup->addChild(storeGroup); 31173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageTypeGroup->addChild(loadStoreGroup); 31183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageTypeGroup->addChild(atomicGroup); 31193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageTypeGroup->addChild(qualifierGroup); 31203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageTypeGroup->addChild(reinterpretGroup); 31213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageTypeGroup->addChild(imageSizeGroup); 31223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 31243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 31253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& format = formats[formatNdx]; 31263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string formatName = getShaderImageFormatQualifier(formats[formatNdx]); 31273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (imageType == TEXTURETYPE_BUFFER && !isFormatSupportedForTextureBuffer(format)) 31293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 31303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Store cases. 31323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry storeGroup->addChild(new ImageStoreCase(m_context, formatName.c_str(), "", format, imageType)); 31343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (textureLayerType(imageType) != imageType) 31353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry storeGroup->addChild(new ImageStoreCase(m_context, (formatName + "_single_layer").c_str(), "", format, imageType, ImageStoreCase::CASEFLAG_SINGLE_LAYER_BIND)); 31363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Load & store. 31383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry loadStoreGroup->addChild(new ImageLoadAndStoreCase(m_context, formatName.c_str(), "", format, imageType)); 31403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (textureLayerType(imageType) != imageType) 31413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry loadStoreGroup->addChild(new ImageLoadAndStoreCase(m_context, (formatName + "_single_layer").c_str(), "", format, imageType, ImageLoadAndStoreCase::CASEFLAG_SINGLE_LAYER_BIND)); 31423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (format.order == TextureFormat::R) 31443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 31453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Atomic operations. 31463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int operationI = 0; operationI < ATOMIC_OPERATION_LAST; operationI++) 31483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 31493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int atomicCaseTypeI = 0; atomicCaseTypeI < ATOMIC_OPERATION_CASE_TYPE_LAST; atomicCaseTypeI++) 31503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 31513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperation operation = (AtomicOperation)operationI; 31523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (format.type == TextureFormat::FLOAT && operation != ATOMIC_OPERATION_EXCHANGE) 31543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 31553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperationCaseType caseType = (AtomicOperationCaseType)atomicCaseTypeI; 31573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string caseTypeName = caseType == ATOMIC_OPERATION_CASE_TYPE_END_RESULT ? "result" 31583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : caseType == ATOMIC_OPERATION_CASE_TYPE_RETURN_VALUES ? "return_value" 31593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 31603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string caseName = string() + getAtomicOperationCaseName(operation) + "_" + formatName + "_" + caseTypeName; 31613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (operation == ATOMIC_OPERATION_COMP_SWAP) 31633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry atomicGroup->addChild(new AtomicCompSwapCase(m_context, caseName.c_str(), "", format, imageType, caseType)); 31643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 31653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry atomicGroup->addChild(new BinaryAtomicOperationCase(m_context, caseName.c_str(), "", format, imageType, operation, caseType)); 31663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 31673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 31683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Coherence. 31703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int coherenceQualifierI = 0; coherenceQualifierI < CoherenceCase::QUALIFIER_LAST; coherenceQualifierI++) 31723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 31733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const CoherenceCase::Qualifier coherenceQualifier = (CoherenceCase::Qualifier)coherenceQualifierI; 31743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const coherenceQualifierName = coherenceQualifier == CoherenceCase::QUALIFIER_COHERENT ? "coherent" 31753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : coherenceQualifier == CoherenceCase::QUALIFIER_VOLATILE ? "volatile" 31763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 31773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string caseName = string() + coherenceQualifierName + "_" + formatName; 31783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry qualifierGroup->addChild(new CoherenceCase(m_context, caseName.c_str(), "", format, imageType, coherenceQualifier)); 31803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 31813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 31823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 31833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Restrict. 31853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry qualifierGroup->addChild(new ImageLoadAndStoreCase(m_context, "restrict", "", TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), imageType, ImageLoadAndStoreCase::CASEFLAG_RESTRICT_IMAGES)); 31863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Format re-interpretation. 31883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int texFmtNdx = 0; texFmtNdx < DE_LENGTH_OF_ARRAY(formats); texFmtNdx++) 31903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int imgFmtNdx = 0; imgFmtNdx < DE_LENGTH_OF_ARRAY(formats); imgFmtNdx++) 31913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 31923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& texFmt = formats[texFmtNdx]; 31933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TextureFormat& imgFmt = formats[imgFmtNdx]; 31943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (imageType == TEXTURETYPE_BUFFER && !isFormatSupportedForTextureBuffer(texFmt)) 31963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 31973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 31983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (texFmt != imgFmt && texFmt.getPixelSize() == imgFmt.getPixelSize()) 31993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reinterpretGroup->addChild(new ImageLoadAndStoreCase(m_context, 32003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (getShaderImageFormatQualifier(texFmt) + "_" + getShaderImageFormatQualifier(imgFmt)).c_str(), "", 32013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry texFmt, imgFmt, imageType)); 32023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // imageSize(). 32053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 32073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const IVec3 baseImageSizes[] = 32083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 32093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3(32, 32, 32), 32103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3(12, 34, 56), 32113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3(1, 1, 1), 32123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec3(7, 1, 1) 32133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 32143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int imageAccessI = 0; imageAccessI < ImageSizeCase::IMAGEACCESS_LAST; imageAccessI++) 32163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 32173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ImageSizeCase::ImageAccess imageAccess = (ImageSizeCase::ImageAccess)imageAccessI; 32183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* const imageAccessStr = imageAccess == ImageSizeCase::IMAGEACCESS_READ_ONLY ? "readonly" 32193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageAccess == ImageSizeCase::IMAGEACCESS_WRITE_ONLY ? "writeonly" 32203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageAccess == ImageSizeCase::IMAGEACCESS_READ_ONLY_WRITE_ONLY ? "readonly_writeonly" 32213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 32223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int imageSizeNdx = 0; imageSizeNdx < DE_LENGTH_OF_ARRAY(baseImageSizes); imageSizeNdx++) 32243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 32253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3& baseSize = baseImageSizes[imageSizeNdx]; 32263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec3 imageSize = imageType == TEXTURETYPE_BUFFER ? IVec3(baseSize.x(), 1, 1) 32273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_2D ? IVec3(baseSize.x(), baseSize.y(), 1) 32283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_CUBE ? IVec3(baseSize.x(), baseSize.x(), 1) 32293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_3D ? baseSize 32303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_2D_ARRAY ? baseSize 32313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : IVec3(-1, -1, -1); 32323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string sizeStr = imageType == TEXTURETYPE_BUFFER ? toString(imageSize.x()) 32343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_2D ? toString(imageSize.x()) + "x" + toString(imageSize.y()) 32353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_CUBE ? toString(imageSize.x()) + "x" + toString(imageSize.y()) 32363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_3D ? toString(imageSize.x()) + "x" + toString(imageSize.y()) + "x" + toString(imageSize.z()) 32373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : imageType == TEXTURETYPE_2D_ARRAY ? toString(imageSize.x()) + "x" + toString(imageSize.y()) + "x" + toString(imageSize.z()) 32383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 32393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string caseName = string() + imageAccessStr + "_" + sizeStr; 32413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageSizeGroup->addChild(new ImageSizeCase(m_context, caseName.c_str(), "", TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT), imageType, imageSize, imageAccess)); 32433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // early_fragment_tests cases. 32503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 32523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestCaseGroup* const earlyTestsGroup = new TestCaseGroup(m_context, "early_fragment_tests", ""); 32533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(earlyTestsGroup); 32543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int useEarlyTestsI = 0; useEarlyTestsI <= 1; useEarlyTestsI++) 32563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 32573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool useEarlyTests = useEarlyTestsI != 0; 32583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int testTypeI = 0; testTypeI < EarlyFragmentTestsCase::TESTTYPE_LAST; testTypeI++) 32603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 32613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const EarlyFragmentTestsCase::TestType testType = (EarlyFragmentTestsCase::TestType)testTypeI; 32623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string testTypeName = testType == EarlyFragmentTestsCase::TESTTYPE_DEPTH ? "depth" 32643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : testType == EarlyFragmentTestsCase::TESTTYPE_STENCIL ? "stencil" 32653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : DE_NULL; 32663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string caseName = string(useEarlyTests ? "" : "no_") + "early_fragment_tests_" + testTypeName; 32683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string caseDesc = string(useEarlyTests ? "Specify" : "Don't specify") 32703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry + " early_fragment_tests, target the " + testTypeName + " test"; 32713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry earlyTestsGroup->addChild(new EarlyFragmentTestsCase(m_context, caseName.c_str(), caseDesc.c_str(), testType, useEarlyTests)); 32733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 32763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 32773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 32783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional 32793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31 32803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp 3281