1 #ifndef _VKTSSBOLAYOUTCASE_HPP 2 #define _VKTSSBOLAYOUTCASE_HPP 3 /*------------------------------------------------------------------------ 4 * Vulkan Conformance Tests 5 * ------------------------ 6 * 7 * Copyright (c) 2015 The Khronos Group Inc. 8 * Copyright (c) 2015 Samsung Electronics Co., Ltd. 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief SSBO layout tests. 25 *//*--------------------------------------------------------------------*/ 26 27 #include "vktTestCase.hpp" 28 #include "tcuDefs.hpp" 29 #include "gluShaderUtil.hpp" 30 #include "gluVarType.hpp" 31 32 namespace vkt 33 { 34 35 namespace ssbo 36 { 37 38 enum BufferVarFlags 39 { 40 LAYOUT_STD140 = (1 << 0), 41 LAYOUT_STD430 = (1 << 1), 42 LAYOUT_ROW_MAJOR = (1 << 2), 43 LAYOUT_COLUMN_MAJOR = (1 << 3), //!< \note Lack of both flags means column-major matrix. 44 LAYOUT_SCALAR = (1 << 4), 45 LAYOUT_MASK = LAYOUT_STD430 | LAYOUT_STD140 | LAYOUT_ROW_MAJOR | LAYOUT_COLUMN_MAJOR | LAYOUT_SCALAR, 46 47 // \todo [2013-10-14 pyry] Investigate adding these. 48 /* QUALIFIER_COHERENT = (1<<4), 49 QUALIFIER_VOLATILE = (1<<5), 50 QUALIFIER_RESTRICT = (1<<6), 51 QUALIFIER_READONLY = (1<<7), 52 QUALIFIER_WRITEONLY = (1<<8),*/ 53 ACCESS_READ = (1 << 9), //!< Buffer variable is read in the shader. 54 ACCESS_WRITE = (1 << 10), //!< Buffer variable is written in the shader. 55 LAYOUT_RELAXED = (1 << 11), //!< Support VK_KHR_relaxed_block_layout extension 56 LAYOUT_16BIT_STORAGE = (1 << 12), //!< Support VK_KHR_16bit_storage extension 57 LAYOUT_8BIT_STORAGE = (1 << 13), //!< Support VK_KHR_8bit_storage extension 58 LAYOUT_DESCRIPTOR_INDEXING = (1 << 14), //!< Support VK_KHR_descriptor_indexing extension 59 }; 60 61 enum MatrixLoadFlags 62 { 63 LOAD_FULL_MATRIX = 0, 64 LOAD_MATRIX_COMPONENTS = 1, 65 }; 66 67 enum MatrixStoreFlags 68 { 69 STORE_FULL_MATRIX = 0, 70 STORE_MATRIX_COLUMNS = 1, 71 }; 72 73 class BufferVar 74 { 75 public: 76 BufferVar(const char *name, const glu::VarType &type, uint32_t flags); 77 getName(void) const78 const char *getName(void) const 79 { 80 return m_name.c_str(); 81 } getType(void) const82 const glu::VarType &getType(void) const 83 { 84 return m_type; 85 } getFlags(void) const86 uint32_t getFlags(void) const 87 { 88 return m_flags; 89 } getOffset(void) const90 uint32_t getOffset(void) const 91 { 92 return m_offset; 93 } 94 setOffset(uint32_t offset)95 void setOffset(uint32_t offset) 96 { 97 m_offset = offset; 98 } 99 100 private: 101 std::string m_name; 102 glu::VarType m_type; 103 uint32_t m_flags; 104 uint32_t m_offset; 105 }; 106 107 class BufferBlock 108 { 109 public: 110 typedef std::vector<BufferVar>::iterator iterator; 111 typedef std::vector<BufferVar>::const_iterator const_iterator; 112 113 BufferBlock(const char *blockName); 114 getBlockName(void) const115 const char *getBlockName(void) const 116 { 117 return m_blockName.c_str(); 118 } getInstanceName(void) const119 const char *getInstanceName(void) const 120 { 121 return m_instanceName.empty() ? DE_NULL : m_instanceName.c_str(); 122 } isArray(void) const123 bool isArray(void) const 124 { 125 return m_arraySize > 0; 126 } getArraySize(void) const127 int getArraySize(void) const 128 { 129 return m_arraySize; 130 } getFlags(void) const131 uint32_t getFlags(void) const 132 { 133 return m_flags; 134 } 135 setInstanceName(const char * name)136 void setInstanceName(const char *name) 137 { 138 m_instanceName = name; 139 } setFlags(uint32_t flags)140 void setFlags(uint32_t flags) 141 { 142 m_flags = flags; 143 } addMember(const BufferVar & var)144 void addMember(const BufferVar &var) 145 { 146 m_variables.push_back(var); 147 } 148 void setArraySize(int arraySize); 149 getLastUnsizedArraySize(int instanceNdx) const150 int getLastUnsizedArraySize(int instanceNdx) const 151 { 152 return m_lastUnsizedArraySizes[instanceNdx]; 153 } setLastUnsizedArraySize(int instanceNdx,int size)154 void setLastUnsizedArraySize(int instanceNdx, int size) 155 { 156 m_lastUnsizedArraySizes[instanceNdx] = size; 157 } 158 begin(void)159 inline iterator begin(void) 160 { 161 return m_variables.begin(); 162 } begin(void) const163 inline const_iterator begin(void) const 164 { 165 return m_variables.begin(); 166 } end(void)167 inline iterator end(void) 168 { 169 return m_variables.end(); 170 } end(void) const171 inline const_iterator end(void) const 172 { 173 return m_variables.end(); 174 } 175 176 private: 177 std::string m_blockName; 178 std::string m_instanceName; 179 std::vector<BufferVar> m_variables; 180 int m_arraySize; //!< Array size or 0 if not interface block array. 181 std::vector<int> m_lastUnsizedArraySizes; //!< Sizes of last unsized array element, can be different per instance. 182 uint32_t m_flags; 183 }; 184 185 class ShaderInterface 186 { 187 public: 188 ShaderInterface(void); 189 ~ShaderInterface(void); 190 191 glu::StructType &allocStruct(const char *name); 192 const glu::StructType *findStruct(const char *name) const; 193 void getNamedStructs(std::vector<const glu::StructType *> &structs) const; 194 195 BufferBlock &allocBlock(const char *name); 196 getNumBlocks(void) const197 int getNumBlocks(void) const 198 { 199 return (int)m_bufferBlocks.size(); 200 } getBlock(int ndx) const201 const BufferBlock &getBlock(int ndx) const 202 { 203 return *m_bufferBlocks[ndx]; 204 } getBlock(int ndx)205 BufferBlock &getBlock(int ndx) 206 { 207 return *m_bufferBlocks[ndx]; 208 } 209 210 private: 211 ShaderInterface(const ShaderInterface &); 212 ShaderInterface &operator=(const ShaderInterface &); 213 214 std::vector<glu::StructType *> m_structs; 215 std::vector<BufferBlock *> m_bufferBlocks; 216 }; 217 218 struct BufferVarLayoutEntry 219 { BufferVarLayoutEntryvkt::ssbo::BufferVarLayoutEntry220 BufferVarLayoutEntry(void) 221 : type(glu::TYPE_LAST) 222 , blockNdx(-1) 223 , offset(-1) 224 , arraySize(-1) 225 , arrayStride(-1) 226 , matrixStride(-1) 227 , topLevelArraySize(-1) 228 , topLevelArrayStride(-1) 229 , isRowMajor(false) 230 { 231 } 232 233 std::string name; 234 glu::DataType type; 235 int blockNdx; 236 int offset; 237 int arraySize; 238 int arrayStride; 239 int matrixStride; 240 int topLevelArraySize; 241 int topLevelArrayStride; 242 bool isRowMajor; 243 }; 244 245 struct BlockLayoutEntry 246 { BlockLayoutEntryvkt::ssbo::BlockLayoutEntry247 BlockLayoutEntry(void) : size(0) 248 { 249 } 250 251 std::string name; 252 int size; 253 std::vector<int> activeVarIndices; 254 }; 255 256 class BufferLayout 257 { 258 public: 259 std::vector<BlockLayoutEntry> blocks; 260 std::vector<BufferVarLayoutEntry> bufferVars; 261 262 int getVariableIndex(const std::string &name) const; 263 int getBlockIndex(const std::string &name) const; 264 }; 265 266 // BlockDataPtr 267 268 struct BlockDataPtr 269 { 270 void *ptr; 271 int size; //!< Redundant, for debugging purposes. 272 int lastUnsizedArraySize; 273 BlockDataPtrvkt::ssbo::BlockDataPtr274 BlockDataPtr(void *ptr_, int size_, int lastUnsizedArraySize_) 275 : ptr(ptr_) 276 , size(size_) 277 , lastUnsizedArraySize(lastUnsizedArraySize_) 278 { 279 } 280 BlockDataPtrvkt::ssbo::BlockDataPtr281 BlockDataPtr(void) : ptr(DE_NULL), size(0), lastUnsizedArraySize(0) 282 { 283 } 284 }; 285 286 struct RefDataStorage 287 { 288 std::vector<uint8_t> data; 289 std::vector<BlockDataPtr> pointers; 290 }; 291 292 class SSBOLayoutCase : public vkt::TestCase 293 { 294 public: 295 enum BufferMode 296 { 297 BUFFERMODE_SINGLE = 0, //!< Single buffer shared between uniform blocks. 298 BUFFERMODE_PER_BLOCK, //!< Per-block buffers 299 300 BUFFERMODE_LAST 301 }; 302 303 SSBOLayoutCase(tcu::TestContext &testCtx, const char *name, BufferMode bufferMode, MatrixLoadFlags matrixLoadFlag, 304 MatrixStoreFlags matrixStoreFlag, bool usePhysStorageBuffer); 305 virtual ~SSBOLayoutCase(void); 306 307 virtual void delayedInit(void); 308 virtual void initPrograms(vk::SourceCollections &programCollection) const; 309 virtual TestInstance *createInstance(Context &context) const; 310 virtual void checkSupport(Context &context) const; 311 312 protected: 313 BufferMode m_bufferMode; 314 ShaderInterface m_interface; 315 MatrixLoadFlags m_matrixLoadFlag; 316 MatrixStoreFlags m_matrixStoreFlag; 317 std::string m_computeShaderSrc; 318 bool m_usePhysStorageBuffer; 319 320 private: 321 SSBOLayoutCase(const SSBOLayoutCase &); 322 SSBOLayoutCase &operator=(const SSBOLayoutCase &); 323 324 BufferLayout m_refLayout; 325 RefDataStorage m_initialData; // Initial data stored in buffer. 326 RefDataStorage m_writeData; // Data written by compute shader. 327 }; 328 329 } // namespace ssbo 330 } // namespace vkt 331 332 #endif // _VKTSSBOLAYOUTCASE_HPP 333