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