ShaderExecutor tests: Add Opaque type indexing tests and uniform support for shader...
authorAkos Dirner <adirner.uszeged@partner.samsung.com>
Wed, 16 Dec 2015 18:00:46 +0000 (19:00 +0100)
committerRobert Sipka <rsipka.uszeged@partner.samsung.com>
Wed, 16 Dec 2015 18:39:07 +0000 (19:39 +0100)
external/vulkancts/modules/vulkan/shaderexecutor/CMakeLists.txt
external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/shaderexecutor/vktShaderExecutor.cpp
external/vulkancts/modules/vulkan/shaderexecutor/vktShaderExecutor.hpp
external/vulkancts/modules/vulkan/shaderexecutor/vktShaderExecutorTests.cpp

index 63a1b22..d49c8d6 100644 (file)
@@ -16,6 +16,8 @@ set(DEQP_VK_SHADEREXECUTOR_SRCS
    vktShaderPackingFunctionTests.hpp
    vktShaderBuiltinPrecisionTests.cpp
    vktShaderBuiltinPrecisionTests.hpp
    vktShaderPackingFunctionTests.hpp
    vktShaderBuiltinPrecisionTests.cpp
    vktShaderBuiltinPrecisionTests.hpp
+   vktOpaqueTypeIndexingTests.cpp
+   vktOpaqueTypeIndexingTests.hpp
 )
 
 set(DEQP_VK_SHADEREXECUTOR_LIBS
 )
 
 set(DEQP_VK_SHADEREXECUTOR_LIBS
diff --git a/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp b/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp
new file mode 100644 (file)
index 0000000..fefc6b4
--- /dev/null
@@ -0,0 +1,1385 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Opaque type (sampler, buffer, atomic counter, ...) indexing tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktOpaqueTypeIndexingTests.hpp"
+
+#include "tcuTexture.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "deStringUtil.hpp"
+#include "deRandom.hpp"
+
+#include "vktShaderExecutor.hpp"
+
+#include <sstream>
+
+namespace vkt
+{
+namespace shaderexecutor
+{
+
+namespace
+{
+
+enum IndexExprType
+{
+       INDEX_EXPR_TYPE_CONST_LITERAL   = 0,
+       INDEX_EXPR_TYPE_CONST_EXPRESSION,
+       INDEX_EXPR_TYPE_UNIFORM,
+       INDEX_EXPR_TYPE_DYNAMIC_UNIFORM,
+
+       INDEX_EXPR_TYPE_LAST
+};
+
+enum TextureType
+{
+       TEXTURE_TYPE_1D = 0,
+       TEXTURE_TYPE_2D,
+       TEXTURE_TYPE_CUBE,
+       TEXTURE_TYPE_2D_ARRAY,
+       TEXTURE_TYPE_3D,
+
+       TEXTURE_TYPE_LAST
+};
+
+class OpaqueTypeIndexingCase : public TestCase
+{
+public:
+                                                                               OpaqueTypeIndexingCase          (tcu::TestContext&                      testCtx,
+                                                                                                                                        const char*                            name,
+                                                                                                                                        const char*                            description,
+                                                                                                                                        const glu::ShaderType          shaderType,
+                                                                                                                                        const IndexExprType            indexExprType);
+       virtual                                                         ~OpaqueTypeIndexingCase         (void);
+       virtual void                                            initPrograms                            (vk::SourceCollections& programCollection) const
+                                                                               {
+                                                                                       m_executor->setShaderSources(programCollection);
+                                                                               }
+       virtual TestInstance*                           createInstance                          (Context& context) const = 0;
+       void                                                            init                                            (void);
+
+protected:
+       const char*                                                     m_name;
+       const glu::ShaderType                           m_shaderType;
+       const IndexExprType                                     m_indexExprType;
+       ShaderSpec                                                      m_shaderSpec;
+       de::MovePtr<ShaderExecutor>                     m_executor;
+       UniformSetup*                                           m_uniformSetup;
+};
+
+class OpaqueTypeIndexingTestInstance : public TestInstance
+{
+public:
+                                                                               OpaqueTypeIndexingTestInstance          (Context&                                       context,
+                                                                                                                                                        const glu::ShaderType          shaderType,
+                                                                                                                                                        const ShaderSpec&                      shaderSpec,
+                                                                                                                                                        ShaderExecutor&                        executor,
+                                                                                                                                                        const char*                            name,
+                                                                                                                                                        UniformSetup*                          uniformSetup,
+                                                                                                                                                        const IndexExprType            indexExprType);
+       virtual                                                         ~OpaqueTypeIndexingTestInstance         (void);
+
+       virtual tcu::TestStatus                         iterate                                                         (void) = 0;
+
+protected:
+       tcu::TestContext&                                       m_testCtx;
+       const glu::ShaderType                           m_shaderType;
+       const ShaderSpec&                                       m_shaderSpec;
+       const char*                                                     m_name;
+       const IndexExprType                                     m_indexExprType;
+       ShaderExecutor&                                         m_executor;
+       UniformSetup*                                           m_uniformSetup;
+};
+
+OpaqueTypeIndexingCase::OpaqueTypeIndexingCase (tcu::TestContext&                      testCtx,
+                                                                                               const char*                                     name,
+                                                                                               const char*                                     description,
+                                                                                               const glu::ShaderType           shaderType,
+                                                                                               const IndexExprType                     indexExprType)
+       : TestCase                      (testCtx, name, description)
+       , m_name                        (name)
+       , m_shaderType          (shaderType)
+       , m_indexExprType       (indexExprType)
+       , m_executor            (DE_NULL)
+       , m_uniformSetup        (new UniformSetup())
+{
+}
+
+OpaqueTypeIndexingCase::~OpaqueTypeIndexingCase (void)
+{
+}
+
+void OpaqueTypeIndexingCase::init (void)
+{
+       DE_ASSERT(!m_executor);
+
+       m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_shaderType, m_shaderSpec));
+       m_testCtx.getLog() << *m_executor;
+}
+
+OpaqueTypeIndexingTestInstance::OpaqueTypeIndexingTestInstance (Context&                                       context,
+                                                                                                                               const glu::ShaderType           shaderType,
+                                                                                                                               const ShaderSpec&                       shaderSpec,
+                                                                                                                               ShaderExecutor&                         executor,
+                                                                                                                               const char*                                     name,
+                                                                                                                               UniformSetup*                           uniformSetup,
+                                                                                                                               const IndexExprType                     indexExprType)
+       : TestInstance          (context)
+       , m_testCtx                     (context.getTestContext())
+       , m_shaderType          (shaderType)
+       , m_shaderSpec          (shaderSpec)
+       , m_name                        (name)
+       , m_indexExprType       (indexExprType)
+       , m_executor            (executor)
+       , m_uniformSetup        (uniformSetup)
+{
+}
+
+OpaqueTypeIndexingTestInstance::~OpaqueTypeIndexingTestInstance (void)
+{
+}
+
+static deUint32 getFirstFreeBindingLocation (const glu::ShaderType shaderType, const bool hasInputParam)
+{
+       deUint32 location;
+
+       switch (shaderType)
+       {
+               case glu::SHADERTYPE_TESSELLATION_CONTROL:
+               case glu::SHADERTYPE_TESSELLATION_EVALUATION:
+               case glu::SHADERTYPE_COMPUTE:
+                       // 0 - output buffer
+                       // 1 - input buffer (if any)
+                       if (hasInputParam)
+                               location = 2u;
+                       else
+                               location = 1u;
+                       break;
+
+               default:
+                       location = 0u;
+                       break;
+       }
+
+       return location;
+}
+
+static deUint32 getFirstFreeBindingLocation (const glu::ShaderType shaderType, const ShaderSpec& shaderSpec)
+{
+       return getFirstFreeBindingLocation(shaderType, !shaderSpec.inputs.empty());
+}
+
+static void declareUniformIndexVars (std::ostream& str, const char* varPrefix, int numVars, deUint32& bindingLocation)
+{
+       for (int varNdx = 0; varNdx < numVars; varNdx++)
+               str << "layout(set = 0, binding = " << bindingLocation++ << ") uniform buf" << varNdx << " { highp int " << varPrefix << varNdx << "; }" << ";\n";
+}
+
+static void uploadUniformIndices (UniformSetup* uniformSetup, int numIndices, const int* indices, deUint32& bindingLocation)
+{
+       for (int varNdx = 0; varNdx < numIndices; varNdx++)
+               uniformSetup->addData(new UniformData<int>(bindingLocation++, indices[varNdx]));
+}
+
+static TextureType getTextureType (glu::DataType samplerType)
+{
+       switch (samplerType)
+       {
+               case glu::TYPE_SAMPLER_1D:
+               case glu::TYPE_INT_SAMPLER_1D:
+               case glu::TYPE_UINT_SAMPLER_1D:
+               case glu::TYPE_SAMPLER_1D_SHADOW:
+                       return TEXTURE_TYPE_1D;
+
+               case glu::TYPE_SAMPLER_2D:
+               case glu::TYPE_INT_SAMPLER_2D:
+               case glu::TYPE_UINT_SAMPLER_2D:
+               case glu::TYPE_SAMPLER_2D_SHADOW:
+                       return TEXTURE_TYPE_2D;
+
+               case glu::TYPE_SAMPLER_CUBE:
+               case glu::TYPE_INT_SAMPLER_CUBE:
+               case glu::TYPE_UINT_SAMPLER_CUBE:
+               case glu::TYPE_SAMPLER_CUBE_SHADOW:
+                       return TEXTURE_TYPE_CUBE;
+
+               case glu::TYPE_SAMPLER_2D_ARRAY:
+               case glu::TYPE_INT_SAMPLER_2D_ARRAY:
+               case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
+               case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
+                       return TEXTURE_TYPE_2D_ARRAY;
+
+               case glu::TYPE_SAMPLER_3D:
+               case glu::TYPE_INT_SAMPLER_3D:
+               case glu::TYPE_UINT_SAMPLER_3D:
+                       return TEXTURE_TYPE_3D;
+
+               default:
+                       throw tcu::InternalError("Invalid sampler type");
+       }
+}
+
+static bool isShadowSampler (glu::DataType samplerType)
+{
+       return samplerType == glu::TYPE_SAMPLER_1D_SHADOW               ||
+                  samplerType == glu::TYPE_SAMPLER_2D_SHADOW           ||
+                  samplerType == glu::TYPE_SAMPLER_2D_ARRAY_SHADOW     ||
+                  samplerType == glu::TYPE_SAMPLER_CUBE_SHADOW;
+}
+
+static glu::DataType getSamplerOutputType (glu::DataType samplerType)
+{
+       switch (samplerType)
+       {
+               case glu::TYPE_SAMPLER_1D:
+               case glu::TYPE_SAMPLER_2D:
+               case glu::TYPE_SAMPLER_CUBE:
+               case glu::TYPE_SAMPLER_2D_ARRAY:
+               case glu::TYPE_SAMPLER_3D:
+                       return glu::TYPE_FLOAT_VEC4;
+
+               case glu::TYPE_SAMPLER_1D_SHADOW:
+               case glu::TYPE_SAMPLER_2D_SHADOW:
+               case glu::TYPE_SAMPLER_CUBE_SHADOW:
+               case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
+                       return glu::TYPE_FLOAT;
+
+               case glu::TYPE_INT_SAMPLER_1D:
+               case glu::TYPE_INT_SAMPLER_2D:
+               case glu::TYPE_INT_SAMPLER_CUBE:
+               case glu::TYPE_INT_SAMPLER_2D_ARRAY:
+               case glu::TYPE_INT_SAMPLER_3D:
+                       return glu::TYPE_INT_VEC4;
+
+               case glu::TYPE_UINT_SAMPLER_1D:
+               case glu::TYPE_UINT_SAMPLER_2D:
+               case glu::TYPE_UINT_SAMPLER_CUBE:
+               case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
+               case glu::TYPE_UINT_SAMPLER_3D:
+                       return glu::TYPE_UINT_VEC4;
+
+               default:
+                       throw tcu::InternalError("Invalid sampler type");
+       }
+}
+
+static tcu::TextureFormat getSamplerTextureFormat (glu::DataType samplerType)
+{
+       const glu::DataType             outType                 = getSamplerOutputType(samplerType);
+       const glu::DataType             outScalarType   = glu::getDataTypeScalarType(outType);
+
+       switch (outScalarType)
+       {
+               case glu::TYPE_FLOAT:
+                       if (isShadowSampler(samplerType))
+                               return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
+                       else
+                               return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
+
+               case glu::TYPE_INT:             return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8);
+               case glu::TYPE_UINT:    return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8);
+
+               default:
+                       throw tcu::InternalError("Invalid sampler type");
+       }
+}
+
+static glu::DataType getSamplerCoordType (glu::DataType samplerType)
+{
+       const TextureType       texType         = getTextureType(samplerType);
+       int                                     numCoords       = 0;
+
+       switch (texType)
+       {
+               case TEXTURE_TYPE_1D:           numCoords = 1;  break;
+               case TEXTURE_TYPE_2D:           numCoords = 2;  break;
+               case TEXTURE_TYPE_2D_ARRAY:     numCoords = 3;  break;
+               case TEXTURE_TYPE_CUBE:         numCoords = 3;  break;
+               case TEXTURE_TYPE_3D:           numCoords = 3;  break;
+               default:
+                       DE_ASSERT(false);
+       }
+
+       if (isShadowSampler(samplerType))
+               numCoords += 1;
+
+       DE_ASSERT(de::inRange(numCoords, 1, 4));
+
+       return numCoords == 1 ? glu::TYPE_FLOAT : glu::getDataTypeFloatVec(numCoords);
+}
+
+static void fillTextureData (const tcu::PixelBufferAccess& access, de::Random& rnd)
+{
+       DE_ASSERT(access.getHeight() == 1 && access.getDepth() == 1);
+
+       if (access.getFormat().order == tcu::TextureFormat::D)
+       {
+               // \note Texture uses odd values, lookup even values to avoid precision issues.
+               const float values[] = { 0.1f, 0.3f, 0.5f, 0.7f, 0.9f };
+
+               for (int ndx = 0; ndx < access.getWidth(); ndx++)
+                       access.setPixDepth(rnd.choose<float>(DE_ARRAY_BEGIN(values), DE_ARRAY_END(values)), ndx, 0);
+       }
+       else
+       {
+               TCU_CHECK_INTERNAL(access.getFormat().order == tcu::TextureFormat::RGBA && access.getFormat().getPixelSize() == 4);
+
+               for (int ndx = 0; ndx < access.getWidth(); ndx++)
+                       *((deUint32*)access.getDataPtr() + ndx) = rnd.getUint32();
+       }
+}
+
+static vk::VkImageType getVkImageType (TextureType texType)
+{
+       switch (texType)
+       {
+               case TEXTURE_TYPE_1D:                   return vk::VK_IMAGE_TYPE_1D;
+               case TEXTURE_TYPE_2D:
+               case TEXTURE_TYPE_2D_ARRAY:             return vk::VK_IMAGE_TYPE_2D;
+               case TEXTURE_TYPE_CUBE:                 return vk::VK_IMAGE_TYPE_3D;
+               case TEXTURE_TYPE_3D:                   return vk::VK_IMAGE_TYPE_3D;
+               default:
+                       DE_FATAL("Impossible");
+                       return (vk::VkImageType)0;
+       }
+}
+
+static vk::VkImageViewType getVkImageViewType (TextureType texType)
+{
+       switch (texType)
+       {
+               case TEXTURE_TYPE_1D:                   return vk::VK_IMAGE_VIEW_TYPE_1D;
+               case TEXTURE_TYPE_2D:                   return vk::VK_IMAGE_VIEW_TYPE_2D;
+               case TEXTURE_TYPE_2D_ARRAY:             return vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+               case TEXTURE_TYPE_CUBE:                 return vk::VK_IMAGE_VIEW_TYPE_3D; // \todo vk::VK_IMAGE_VIEW_TYPE_CUBE ?
+               case TEXTURE_TYPE_3D:                   return vk::VK_IMAGE_VIEW_TYPE_3D;
+               default:
+                       DE_FATAL("Impossible");
+                       return (vk::VkImageViewType)0;
+       }
+}
+
+// SamplerIndexingCaseInstance
+
+class SamplerIndexingCaseInstance : public OpaqueTypeIndexingTestInstance
+{
+public:
+       enum
+       {
+               NUM_INVOCATIONS         = 64,
+               NUM_SAMPLERS            = 8,
+               NUM_LOOKUPS                     = 4
+       };
+
+                                                               SamplerIndexingCaseInstance             (Context&                                       context,
+                                                                                                                                const glu::ShaderType          shaderType,
+                                                                                                                                const ShaderSpec&                      shaderSpec,
+                                                                                                                                ShaderExecutor&                        executor,
+                                                                                                                                const char*                            name,
+                                                                                                                                glu::DataType                          samplerType,
+                                                                                                                                const IndexExprType            indexExprType,
+                                                                                                                                UniformSetup*                          uniformSetup,
+                                                                                                                                const std::vector<int>&        lookupIndices);
+       virtual                                         ~SamplerIndexingCaseInstance    (void);
+
+       virtual tcu::TestStatus         iterate                                                 (void);
+
+protected:
+       const glu::DataType                     m_samplerType;
+       const std::vector<int>&         m_lookupIndices;
+};
+
+SamplerIndexingCaseInstance::SamplerIndexingCaseInstance (Context&                                             context,
+                                                                                                                 const glu::ShaderType                 shaderType,
+                                                                                                                 const ShaderSpec&                             shaderSpec,
+                                                                                                                 ShaderExecutor&                               executor,
+                                                                                                                 const char*                                   name,
+                                                                                                                 glu::DataType                                 samplerType,
+                                                                                                                 const IndexExprType                   indexExprType,
+                                                                                                                 UniformSetup*                                 uniformSetup,
+                                                                                                                 const std::vector<int>&               lookupIndices)
+       : OpaqueTypeIndexingTestInstance        (context, shaderType, shaderSpec, executor, name, uniformSetup, indexExprType)
+       , m_samplerType                                         (samplerType)
+       , m_lookupIndices                                       (lookupIndices)
+{
+}
+
+SamplerIndexingCaseInstance::~SamplerIndexingCaseInstance (void)
+{
+}
+
+tcu::TestStatus SamplerIndexingCaseInstance::iterate (void)
+{
+       const int                                               numInvocations          = SamplerIndexingCaseInstance::NUM_INVOCATIONS;
+       const int                                               numSamplers                     = SamplerIndexingCaseInstance::NUM_SAMPLERS;
+       const int                                               numLookups                      = SamplerIndexingCaseInstance::NUM_LOOKUPS;
+       const glu::DataType                             coordType                       = getSamplerCoordType(m_samplerType);
+       const glu::DataType                             outputType                      = getSamplerOutputType(m_samplerType);
+       const tcu::TextureFormat                texFormat                       = getSamplerTextureFormat(m_samplerType);
+       const int                                               outLookupStride         = numInvocations*getDataTypeScalarSize(outputType);
+       std::vector<float>                              coords;
+       std::vector<deUint32>                   outData;
+       std::vector<deUint8>                    texData                         (numSamplers * texFormat.getPixelSize());
+       const tcu::PixelBufferAccess    refTexAccess            (texFormat, numSamplers, 1, 1, &texData[0]);
+       de::Random                                              rnd                                     (deInt32Hash(m_samplerType) ^ deInt32Hash(m_shaderType) ^ deInt32Hash(m_indexExprType));
+       const TextureType                               texType                         = getTextureType(m_samplerType);
+       const vk::VkImageType                   imageType                       = getVkImageType(texType);
+       const vk::VkImageViewType               imageViewType           = getVkImageViewType(texType);
+       const tcu::Sampler                              refSampler                      = isShadowSampler(m_samplerType)
+                                                                                                                               ? tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
+                                                                                                                                                               tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, false /* non-normalized */,
+                                                                                                                                                               tcu::Sampler::COMPAREMODE_LESS)
+                                                                                                                               : tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
+                                                                                                                                                               tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
+
+       coords.resize(numInvocations * getDataTypeScalarSize(coordType));
+
+       if (isShadowSampler(m_samplerType))
+       {
+               // Use different comparison value per invocation.
+               // \note Texture uses odd values, comparison even values.
+               const int       numCoordComps   = getDataTypeScalarSize(coordType);
+               const float     cmpValues[]             = { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f };
+
+               for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
+                       coords[invocationNdx*numCoordComps + (numCoordComps-1)] = rnd.choose<float>(DE_ARRAY_BEGIN(cmpValues), DE_ARRAY_END(cmpValues));
+       }
+
+       fillTextureData(refTexAccess, rnd);
+
+       outData.resize(numLookups*outLookupStride);
+
+       {
+               std::vector<void*>              inputs;
+               std::vector<void*>              outputs;
+               std::vector<int>                expandedIndices;
+               deUint32                                bindingLocation         = getFirstFreeBindingLocation(m_shaderType, m_shaderSpec);
+
+               inputs.push_back(&coords[0]);
+
+               m_uniformSetup->addData(new SamplerUniformData(bindingLocation++, (deUint32)numSamplers, refSampler, texFormat, tcu::IVec3(1, 1, 1), imageType, imageViewType, &texData[0]));
+
+               if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
+               {
+                       expandedIndices.resize(numInvocations * m_lookupIndices.size());
+                       for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
+                       {
+                               for (int invNdx = 0; invNdx < numInvocations; invNdx++)
+                                       expandedIndices[lookupNdx*numInvocations + invNdx] = m_lookupIndices[lookupNdx];
+                       }
+
+                       for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
+                               inputs.push_back(&expandedIndices[lookupNdx*numInvocations]);
+               }
+               else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
+                       uploadUniformIndices(m_uniformSetup, numLookups, &m_lookupIndices[0], bindingLocation);
+
+               for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
+                       outputs.push_back(&outData[outLookupStride*lookupNdx]);
+
+               m_executor.setUniforms(m_uniformSetup);
+
+               m_executor.execute(m_context, numInvocations, &inputs[0], &outputs[0]);
+       }
+
+       {
+               tcu::TestLog&           log                             = m_context.getTestContext().getLog();
+               tcu::TestStatus         testResult              = tcu::TestStatus::pass("Pass");
+
+               if (isShadowSampler(m_samplerType))
+               {
+                       const int                       numCoordComps   = getDataTypeScalarSize(coordType);
+
+                       TCU_CHECK_INTERNAL(getDataTypeScalarSize(outputType) == 1);
+
+                       // Each invocation may have different results.
+                       for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
+                       {
+                               const float     coord   = coords[invocationNdx*numCoordComps + (numCoordComps-1)];
+
+                               for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
+                               {
+                                       const int               texNdx          = m_lookupIndices[lookupNdx];
+                                       const float             result          = *((const float*)(const deUint8*)&outData[lookupNdx*outLookupStride + invocationNdx]);
+                                       const float             reference       = refTexAccess.sample2DCompare(refSampler, tcu::Sampler::NEAREST, coord, (float)texNdx, 0.0f, tcu::IVec3(0));
+
+                                       if (de::abs(result-reference) > 0.005f)
+                                       {
+                                               log << tcu::TestLog::Message << "ERROR: at invocation " << invocationNdx << ", lookup " << lookupNdx << ": expected "
+                                                       << reference << ", got " << result
+                                                       << tcu::TestLog::EndMessage;
+
+                                               if (testResult.getCode() == QP_TEST_RESULT_PASS)
+                                                       testResult = tcu::TestStatus::fail("Got invalid lookup result");
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       TCU_CHECK_INTERNAL(getDataTypeScalarSize(outputType) == 4);
+
+                       // Validate results from first invocation
+                       for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
+                       {
+                               const int               texNdx  = m_lookupIndices[lookupNdx];
+                               const deUint8*  resPtr  = (const deUint8*)&outData[lookupNdx*outLookupStride];
+                               bool                    isOk;
+
+                               if (outputType == glu::TYPE_FLOAT_VEC4)
+                               {
+                                       const float                     threshold               = 1.0f / 256.0f;
+                                       const tcu::Vec4         reference               = refTexAccess.getPixel(texNdx, 0);
+                                       const float*            floatPtr                = (const float*)resPtr;
+                                       const tcu::Vec4         result                  (floatPtr[0], floatPtr[1], floatPtr[2], floatPtr[3]);
+
+                                       isOk = boolAll(lessThanEqual(abs(reference-result), tcu::Vec4(threshold)));
+
+                                       if (!isOk)
+                                       {
+                                               log << tcu::TestLog::Message << "ERROR: at lookup " << lookupNdx << ": expected "
+                                                       << reference << ", got " << result
+                                                       << tcu::TestLog::EndMessage;
+                                       }
+                               }
+                               else
+                               {
+                                       const tcu::UVec4        reference               = refTexAccess.getPixelUint(texNdx, 0);
+                                       const deUint32*         uintPtr                 = (const deUint32*)resPtr;
+                                       const tcu::UVec4        result                  (uintPtr[0], uintPtr[1], uintPtr[2], uintPtr[3]);
+
+                                       isOk = boolAll(equal(reference, result));
+
+                                       if (!isOk)
+                                       {
+                                               log << tcu::TestLog::Message << "ERROR: at lookup " << lookupNdx << ": expected "
+                                                       << reference << ", got " << result
+                                                       << tcu::TestLog::EndMessage;
+                                       }
+                               }
+
+                               if (!isOk && testResult.getCode() == QP_TEST_RESULT_PASS)
+                                       testResult = tcu::TestStatus::fail("Got invalid lookup result");
+                       }
+
+                       // Check results of other invocations against first one
+                       for (int invocationNdx = 1; invocationNdx < numInvocations; invocationNdx++)
+                       {
+                               for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
+                               {
+                                       const deUint32*         refPtr          = &outData[lookupNdx*outLookupStride];
+                                       const deUint32*         resPtr          = refPtr + invocationNdx*4;
+                                       bool                            isOk            = true;
+
+                                       for (int ndx = 0; ndx < 4; ndx++)
+                                               isOk = isOk && (refPtr[ndx] == resPtr[ndx]);
+
+                                       if (!isOk)
+                                       {
+                                               log << tcu::TestLog::Message << "ERROR: invocation " << invocationNdx << " result "
+                                                       << tcu::formatArray(tcu::Format::HexIterator<deUint32>(resPtr), tcu::Format::HexIterator<deUint32>(resPtr+4))
+                                                       << " for lookup " << lookupNdx << " doesn't match result from first invocation "
+                                                       << tcu::formatArray(tcu::Format::HexIterator<deUint32>(refPtr), tcu::Format::HexIterator<deUint32>(refPtr+4))
+                                                       << tcu::TestLog::EndMessage;
+
+                                               if (testResult.getCode() == QP_TEST_RESULT_PASS)
+                                                       testResult = tcu::TestStatus::fail("Inconsistent lookup results");
+                                       }
+                               }
+                       }
+               }
+
+               return testResult;
+       }
+}
+
+class SamplerIndexingCase : public OpaqueTypeIndexingCase
+{
+public:
+                                                               SamplerIndexingCase                     (tcu::TestContext&                      testCtx,
+                                                                                                                        const char*                            name,
+                                                                                                                        const char*                            description,
+                                                                                                                        const glu::ShaderType          shaderType,
+                                                                                                                        glu::DataType                          samplerType,
+                                                                                                                        IndexExprType                          indexExprType);
+       virtual                                         ~SamplerIndexingCase            (void);
+
+       virtual TestInstance*           createInstance                          (Context& ctx) const;
+
+private:
+                                                               SamplerIndexingCase                     (const SamplerIndexingCase&);
+       SamplerIndexingCase&            operator=                                       (const SamplerIndexingCase&);
+
+       void                                            createShaderSpec                        (void);
+
+       const glu::DataType                     m_samplerType;
+       const int                                       m_numSamplers;
+       const int                                       m_numLookups;
+       std::vector<int>                        m_lookupIndices;
+};
+
+SamplerIndexingCase::SamplerIndexingCase (tcu::TestContext&                    testCtx,
+                                                                                 const char*                           name,
+                                                                                 const char*                           description,
+                                                                                 const glu::ShaderType         shaderType,
+                                                                                 glu::DataType                         samplerType,
+                                                                                 IndexExprType                         indexExprType)
+       : OpaqueTypeIndexingCase        (testCtx, name, description, shaderType, indexExprType)
+       , m_samplerType                         (samplerType)
+       , m_numSamplers                         (SamplerIndexingCaseInstance::NUM_SAMPLERS)
+       , m_numLookups                          (SamplerIndexingCaseInstance::NUM_LOOKUPS)
+       , m_lookupIndices                       (m_numLookups)
+{
+       createShaderSpec();
+       init();
+}
+
+SamplerIndexingCase::~SamplerIndexingCase (void)
+{
+}
+
+TestInstance* SamplerIndexingCase::createInstance (Context& ctx) const
+{
+       return new SamplerIndexingCaseInstance(ctx,
+                                                                                  m_shaderType,
+                                                                                  m_shaderSpec,
+                                                                                  *m_executor,
+                                                                                  m_name,
+                                                                                  m_samplerType,
+                                                                                  m_indexExprType,
+                                                                                  m_uniformSetup,
+                                                                                  m_lookupIndices);
+}
+
+void SamplerIndexingCase::createShaderSpec (void)
+{
+       de::Random                      rnd                             (deInt32Hash(m_samplerType) ^ deInt32Hash(m_shaderType) ^ deInt32Hash(m_indexExprType));
+       deUint32                        binding                 = getFirstFreeBindingLocation(m_shaderType, true);
+       const char*                     samplersName    = "texSampler";
+       const char*                     coordsName              = "coords";
+       const char*                     indicesPrefix   = "index";
+       const char*                     resultPrefix    = "result";
+       const glu::DataType     coordType               = getSamplerCoordType(m_samplerType);
+       const glu::DataType     outType                 = getSamplerOutputType(m_samplerType);
+       std::ostringstream      global, code;
+
+       for (int ndx = 0; ndx < m_numLookups; ndx++)
+               m_lookupIndices[ndx] = rnd.getInt(0, m_numSamplers-1);
+
+       m_shaderSpec.inputs.push_back(Symbol(coordsName, glu::VarType(coordType, glu::PRECISION_HIGHP)));
+
+       if (m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL)
+               global << "#extension GL_EXT_gpu_shader5 : require\n";
+
+       if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
+               global << "const highp int indexBase = 1;\n";
+
+       global <<
+               "layout(set = 0, binding = " << binding++ << ") uniform highp " << getDataTypeName(m_samplerType) << " " << samplersName << "[" << m_numSamplers << "];\n";
+
+       if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
+       {
+               for (int lookupNdx = 0; lookupNdx < m_numLookups; lookupNdx++)
+               {
+                       const std::string varName = indicesPrefix + de::toString(lookupNdx);
+                       m_shaderSpec.inputs.push_back(Symbol(varName, glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
+               }
+       }
+       else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
+               declareUniformIndexVars(global, indicesPrefix, m_numLookups, binding);
+
+       for (int lookupNdx = 0; lookupNdx < m_numLookups; lookupNdx++)
+       {
+               const std::string varName = resultPrefix + de::toString(lookupNdx);
+               m_shaderSpec.outputs.push_back(Symbol(varName, glu::VarType(outType, glu::PRECISION_HIGHP)));
+       }
+
+       for (int lookupNdx = 0; lookupNdx < m_numLookups; lookupNdx++)
+       {
+               code << resultPrefix << "" << lookupNdx << " = texture(" << samplersName << "[";
+
+               if (m_indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL)
+                       code << m_lookupIndices[lookupNdx];
+               else if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
+                       code << "indexBase + " << (m_lookupIndices[lookupNdx]-1);
+               else
+                       code << indicesPrefix << lookupNdx;
+
+               code << "], " << coordsName << ");\n";
+       }
+
+       m_shaderSpec.globalDeclarations = global.str();
+       m_shaderSpec.source                             = code.str();
+}
+
+enum BlockType
+{
+       BLOCKTYPE_UNIFORM = 0,
+       BLOCKTYPE_BUFFER,
+
+       BLOCKTYPE_LAST
+};
+
+class BlockArrayIndexingCaseInstance : public OpaqueTypeIndexingTestInstance
+{
+public:
+       enum
+       {
+               NUM_INVOCATIONS         = 32,
+               NUM_INSTANCES           = 4,
+               NUM_READS                       = 4
+       };
+
+                                                                       BlockArrayIndexingCaseInstance  (Context&                                               context,
+                                                                                                                                        const glu::ShaderType                  shaderType,
+                                                                                                                                        const ShaderSpec&                              shaderSpec,
+                                                                                                                                        ShaderExecutor&                                executor,
+                                                                                                                                        const char*                                    name,
+                                                                                                                                        BlockType                                              blockType,
+                                                                                                                                        const IndexExprType                    indexExprType,
+                                                                                                                                        UniformSetup*                                  uniformSetup,
+                                                                                                                                        const std::vector<int>&                readIndices,
+                                                                                                                                        const std::vector<deUint32>&   inValues);
+       virtual                                                 ~BlockArrayIndexingCaseInstance (void);
+
+       virtual tcu::TestStatus                 iterate                                                 (void);
+
+private:
+       const BlockType                                 m_blockType;
+       const std::vector<int>&                 m_readIndices;
+       const std::vector<deUint32>&    m_inValues;
+};
+
+BlockArrayIndexingCaseInstance::BlockArrayIndexingCaseInstance (Context&                                               context,
+                                                                                                                               const glu::ShaderType                   shaderType,
+                                                                                                                               const ShaderSpec&                               shaderSpec,
+                                                                                                                               ShaderExecutor&                                 executor,
+                                                                                                                               const char*                                             name,
+                                                                                                                               BlockType                                               blockType,
+                                                                                                                               const IndexExprType                             indexExprType,
+                                                                                                                               UniformSetup*                                   uniformSetup,
+                                                                                                                               const std::vector<int>&                 readIndices,
+                                                                                                                               const std::vector<deUint32>&    inValues)
+       : OpaqueTypeIndexingTestInstance        (context, shaderType, shaderSpec, executor, name, uniformSetup, indexExprType)
+       , m_blockType                                           (blockType)
+       , m_readIndices                                         (readIndices)
+       , m_inValues                                            (inValues)
+{
+}
+
+BlockArrayIndexingCaseInstance::~BlockArrayIndexingCaseInstance (void)
+{
+}
+
+tcu::TestStatus BlockArrayIndexingCaseInstance::iterate (void)
+{
+       const int                                       numInvocations          = NUM_INVOCATIONS;
+       const int                                       numReads                        = NUM_READS;
+       std::vector<deUint32>           outValues                       (numInvocations*numReads);
+
+       {
+               tcu::TestLog&                   log                                     = m_context.getTestContext().getLog();
+               tcu::TestStatus                 testResult                      = tcu::TestStatus::pass("Pass");
+               std::vector<int>                expandedIndices;
+               std::vector<void*>              inputs;
+               std::vector<void*>              outputs;
+               deUint32                                bindingLocation         = getFirstFreeBindingLocation(m_shaderType, m_shaderSpec);
+
+               for (size_t i = 0 ; i < m_inValues.size(); i++)
+                       m_uniformSetup->addData(new UniformData<deUint32>(bindingLocation++, m_inValues[i]));
+
+               if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
+               {
+                       expandedIndices.resize(numInvocations * m_readIndices.size());
+
+                       for (int readNdx = 0; readNdx < numReads; readNdx++)
+                       {
+                               int* dst = &expandedIndices[numInvocations*readNdx];
+                               std::fill(dst, dst+numInvocations, m_readIndices[readNdx]);
+                       }
+
+                       for (int readNdx = 0; readNdx < numReads; readNdx++)
+                               inputs.push_back(&expandedIndices[readNdx*numInvocations]);
+               }
+               else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
+                       uploadUniformIndices(m_uniformSetup, numReads, &m_readIndices[0], bindingLocation);
+
+               for (int readNdx = 0; readNdx < numReads; readNdx++)
+                       outputs.push_back(&outValues[readNdx*numInvocations]);
+
+               m_executor.setUniforms(m_uniformSetup);
+
+               m_executor.execute(m_context, numInvocations, inputs.empty() ? DE_NULL : &inputs[0], &outputs[0]);
+
+               for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
+               {
+                       for (int readNdx = 0; readNdx < numReads; readNdx++)
+                       {
+                               const deUint32  refValue        = m_inValues[m_readIndices[readNdx]];
+                               const deUint32  resValue        = outValues[readNdx*numInvocations + invocationNdx];
+
+                               if (refValue != resValue)
+                               {
+                                       log << tcu::TestLog::Message << "ERROR: at invocation " << invocationNdx
+                                               << ", read " << readNdx << ": expected "
+                                               << tcu::toHex(refValue) << ", got " << tcu::toHex(resValue)
+                                               << tcu::TestLog::EndMessage;
+
+                                       if (testResult.getCode() == QP_TEST_RESULT_PASS)
+                                               testResult = tcu::TestStatus::fail("Invalid result value");
+                               }
+                       }
+               }
+
+               return testResult;
+       }
+}
+
+class BlockArrayIndexingCase : public OpaqueTypeIndexingCase
+{
+public:
+                                                               BlockArrayIndexingCase          (tcu::TestContext&                      testCtx,
+                                                                                                                        const char*                            name,
+                                                                                                                        const char*                            description,
+                                                                                                                        BlockType                                      blockType,
+                                                                                                                        IndexExprType                          indexExprType,
+                                                                                                                        const glu::ShaderType          shaderType);
+       virtual                                         ~BlockArrayIndexingCase         (void);
+
+       virtual TestInstance*           createInstance                          (Context& ctx) const;
+
+private:
+                                                               BlockArrayIndexingCase          (const BlockArrayIndexingCase&);
+       BlockArrayIndexingCase&         operator=                                       (const BlockArrayIndexingCase&);
+
+       void                                            createShaderSpec                        (void);
+
+       const BlockType                         m_blockType;
+       std::vector<int>                        m_readIndices;
+       std::vector<deUint32>           m_inValues;
+};
+
+BlockArrayIndexingCase::BlockArrayIndexingCase (tcu::TestContext&                      testCtx,
+                                                                                               const char*                                     name,
+                                                                                               const char*                                     description,
+                                                                                               BlockType                                       blockType,
+                                                                                               IndexExprType                           indexExprType,
+                                                                                               const glu::ShaderType           shaderType)
+       : OpaqueTypeIndexingCase        (testCtx, name, description, shaderType, indexExprType)
+       , m_blockType                           (blockType)
+       , m_readIndices                         (BlockArrayIndexingCaseInstance::NUM_READS)
+       , m_inValues                            (BlockArrayIndexingCaseInstance::NUM_INSTANCES)
+{
+       createShaderSpec();
+       init();
+}
+
+BlockArrayIndexingCase::~BlockArrayIndexingCase (void)
+{
+}
+
+TestInstance* BlockArrayIndexingCase::createInstance (Context& ctx) const
+{
+       return new BlockArrayIndexingCaseInstance(ctx,
+                                                                                         m_shaderType,
+                                                                                         m_shaderSpec,
+                                                                                         *m_executor,
+                                                                                         m_name,
+                                                                                         m_blockType,
+                                                                                         m_indexExprType,
+                                                                                         m_uniformSetup,
+                                                                                         m_readIndices,
+                                                                                         m_inValues);
+}
+
+void BlockArrayIndexingCase::createShaderSpec (void)
+{
+       const int                       numInstances    = BlockArrayIndexingCaseInstance::NUM_INSTANCES;
+       const int                       numReads                = BlockArrayIndexingCaseInstance::NUM_READS;
+       de::Random                      rnd                             (deInt32Hash(m_shaderType) ^ deInt32Hash(m_blockType) ^ deInt32Hash(m_indexExprType));
+       deUint32                        binding                 = getFirstFreeBindingLocation(m_shaderType, m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM && numReads > 0);
+       const char*                     blockName               = "Block";
+       const char*                     instanceName    = "block";
+       const char*                     indicesPrefix   = "index";
+       const char*                     resultPrefix    = "result";
+       const char*                     interfaceName   = m_blockType == BLOCKTYPE_UNIFORM ? "uniform" : "buffer";
+       std::ostringstream      global, code;
+
+       for (int readNdx = 0; readNdx < numReads; readNdx++)
+               m_readIndices[readNdx] = rnd.getInt(0, numInstances-1);
+
+       for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
+               m_inValues[instanceNdx] = rnd.getUint32();
+
+       if (m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL)
+               global << "#extension GL_EXT_gpu_shader5 : require\n";
+
+       if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
+               global << "const highp int indexBase = 1;\n";
+
+       global <<
+               "layout(set = 0, binding = " << binding++ << ") " << interfaceName << " " << blockName << "\n"
+               "{\n"
+               "       highp uint value;\n"
+               "} " << instanceName << "[" << numInstances << "];\n";
+
+       if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
+       {
+               for (int readNdx = 0; readNdx < numReads; readNdx++)
+               {
+                       const std::string varName = indicesPrefix + de::toString(readNdx);
+                       m_shaderSpec.inputs.push_back(Symbol(varName, glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
+               }
+       }
+       else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
+               declareUniformIndexVars(global, indicesPrefix, numReads, binding);
+
+       for (int readNdx = 0; readNdx < numReads; readNdx++)
+       {
+               const std::string varName = resultPrefix + de::toString(readNdx);
+               m_shaderSpec.outputs.push_back(Symbol(varName, glu::VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP)));
+       }
+
+       for (int readNdx = 0; readNdx < numReads; readNdx++)
+       {
+               code << resultPrefix << readNdx << " = " << instanceName << "[";
+
+               if (m_indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL)
+                       code << m_readIndices[readNdx];
+               else if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
+                       code << "indexBase + " << (m_readIndices[readNdx]-1);
+               else
+                       code << indicesPrefix << readNdx;
+
+               code << "].value;\n";
+       }
+
+       m_shaderSpec.globalDeclarations = global.str();
+       m_shaderSpec.source                             = code.str();
+}
+
+class AtomicCounterIndexingCaseInstance : public OpaqueTypeIndexingTestInstance
+{
+public:
+       enum
+       {
+               NUM_INVOCATIONS         = 32,
+               NUM_COUNTERS            = 4,
+               NUM_OPS                         = 4
+       };
+
+                                                               AtomicCounterIndexingCaseInstance       (Context&                                       context,
+                                                                                                                                        const glu::ShaderType          shaderType,
+                                                                                                                                        const ShaderSpec&                      shaderSpec,
+                                                                                                                                        ShaderExecutor&                        executor,
+                                                                                                                                        const char*                            name,
+                                                                                                                                        UniformSetup*                          uniformSetup,
+                                                                                                                                        const std::vector<int>&        opIndices,
+                                                                                                                                        const IndexExprType            indexExprType);
+       virtual                                         ~AtomicCounterIndexingCaseInstance      (void);
+
+       virtual tcu::TestStatus         iterate                                                         (void);
+
+private:
+       const std::vector<int>&         m_opIndices;
+};
+
+AtomicCounterIndexingCaseInstance::AtomicCounterIndexingCaseInstance (Context&                                 context,
+                                                                                                                                         const glu::ShaderType         shaderType,
+                                                                                                                                         const ShaderSpec&                     shaderSpec,
+                                                                                                                                         ShaderExecutor&                       executor,
+                                                                                                                                         const char*                           name,
+                                                                                                                                         UniformSetup*                         uniformSetup,
+                                                                                                                                         const std::vector<int>&       opIndices,
+                                                                                                                                         const IndexExprType           indexExprType)
+       : OpaqueTypeIndexingTestInstance        (context, shaderType, shaderSpec, executor, name, uniformSetup, indexExprType)
+       , m_opIndices                                           (opIndices)
+{
+}
+
+AtomicCounterIndexingCaseInstance::~AtomicCounterIndexingCaseInstance (void)
+{
+}
+
+tcu::TestStatus AtomicCounterIndexingCaseInstance::iterate (void)
+{
+       // \todo [2015-12-02 elecro] Add vertexPipelineStoresAndAtomics feature check.
+       const int                                       numInvocations          = NUM_INVOCATIONS;
+       const int                                       numCounters                     = NUM_COUNTERS;
+       const int                                       numOps                          = NUM_OPS;
+       std::vector<int>                        expandedIndices;
+       std::vector<void*>                      inputs;
+       std::vector<void*>                      outputs;
+       std::vector<deUint32>           outValues                       (numInvocations*numOps);
+       deUint32                                        bindingLocation         = getFirstFreeBindingLocation(m_shaderType, m_shaderSpec);
+
+       {
+               DE_ASSERT(numCounters <= 4);
+               // Add the atomic counters' base value, all zero.
+               m_uniformSetup->addData(new UniformData<tcu::Mat4>(bindingLocation++, tcu::Mat4(0.0)));
+
+               if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
+               {
+                       expandedIndices.resize(numInvocations * m_opIndices.size());
+
+                       for (int opNdx = 0; opNdx < numOps; opNdx++)
+                       {
+                               int* dst = &expandedIndices[numInvocations*opNdx];
+                               std::fill(dst, dst+numInvocations, m_opIndices[opNdx]);
+                       }
+
+                       for (int opNdx = 0; opNdx < numOps; opNdx++)
+                               inputs.push_back(&expandedIndices[opNdx*numInvocations]);
+               }
+               else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
+                       uploadUniformIndices(m_uniformSetup, numOps, &m_opIndices[0], bindingLocation);
+
+               for (int opNdx = 0; opNdx < numOps; opNdx++)
+                       outputs.push_back(&outValues[opNdx*numInvocations]);
+
+               m_executor.setUniforms(m_uniformSetup);
+
+               m_executor.execute(m_context, numInvocations, inputs.empty() ? DE_NULL : &inputs[0], &outputs[0]);
+       }
+
+       {
+               tcu::TestLog&                                   log                             = m_context.getTestContext().getLog();
+               tcu::TestStatus                                 testResult              = tcu::TestStatus::pass("Pass");
+               std::vector<int>                                numHits                 (numCounters, 0);       // Number of hits per counter.
+               std::vector<deUint32>                   counterValues   (numCounters);
+               std::vector<std::vector<bool> > counterMasks    (numCounters);
+
+               for (int opNdx = 0; opNdx < numOps; opNdx++)
+                       numHits[m_opIndices[opNdx]] += 1;
+
+               // Verify counter values
+               for (int counterNdx = 0; counterNdx < numCounters; counterNdx++)
+               {
+                       const deUint32          refCount        = (deUint32)(numHits[counterNdx]*numInvocations);
+                       const deUint32          resCount        = counterValues[counterNdx];
+
+                       if (refCount != resCount)
+                       {
+                               log << tcu::TestLog::Message << "ERROR: atomic counter " << counterNdx << " has value " << resCount
+                                       << ", expected " << refCount
+                                       << tcu::TestLog::EndMessage;
+
+                               if (testResult.getCode() == QP_TEST_RESULT_PASS)
+                                       testResult = tcu::TestStatus::fail("Invalid atomic counter value");
+                       }
+               }
+
+               // Allocate bitmasks - one bit per each valid result value
+               for (int counterNdx = 0; counterNdx < numCounters; counterNdx++)
+               {
+                       const int       counterValue    = numHits[counterNdx]*numInvocations;
+                       counterMasks[counterNdx].resize(counterValue, false);
+               }
+
+               // Verify result values from shaders
+               for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
+               {
+                       for (int opNdx = 0; opNdx < numOps; opNdx++)
+                       {
+                               const int               counterNdx      = m_opIndices[opNdx];
+                               const deUint32  resValue        = outValues[opNdx*numInvocations + invocationNdx];
+                               const bool              rangeOk         = de::inBounds(resValue, 0u, (deUint32)counterMasks[counterNdx].size());
+                               const bool              notSeen         = rangeOk && !counterMasks[counterNdx][resValue];
+                               const bool              isOk            = rangeOk && notSeen;
+
+                               if (!isOk)
+                               {
+                                       log << tcu::TestLog::Message << "ERROR: at invocation " << invocationNdx
+                                               << ", op " << opNdx << ": got invalid result value "
+                                               << resValue
+                                               << tcu::TestLog::EndMessage;
+
+                                       if (testResult.getCode() == QP_TEST_RESULT_PASS)
+                                               testResult = tcu::TestStatus::fail("Invalid result value");
+                               }
+                               else
+                               {
+                                       // Mark as used - no other invocation should see this value from same counter.
+                                       counterMasks[counterNdx][resValue] = true;
+                               }
+                       }
+               }
+
+               if (testResult.getCode() == QP_TEST_RESULT_PASS)
+               {
+                       // Consistency check - all masks should be 1 now
+                       for (int counterNdx = 0; counterNdx < numCounters; counterNdx++)
+                       {
+                               for (std::vector<bool>::const_iterator i = counterMasks[counterNdx].begin(); i != counterMasks[counterNdx].end(); i++)
+                                       TCU_CHECK_INTERNAL(*i);
+                       }
+               }
+
+               return testResult;
+       }
+}
+
+class AtomicCounterIndexingCase : public OpaqueTypeIndexingCase
+{
+public:
+                                                               AtomicCounterIndexingCase       (tcu::TestContext&                      testCtx,
+                                                                                                                        const char*                            name,
+                                                                                                                        const char*                            description,
+                                                                                                                        IndexExprType                          indexExprType,
+                                                                                                                        const glu::ShaderType          shaderType);
+       virtual                                         ~AtomicCounterIndexingCase      (void);
+
+       virtual TestInstance*           createInstance                          (Context& ctx) const;
+
+private:
+                                                               AtomicCounterIndexingCase       (const BlockArrayIndexingCase&);
+       AtomicCounterIndexingCase&      operator=                                       (const BlockArrayIndexingCase&);
+
+       void                                            createShaderSpec                        (void);
+
+       std::vector<int>                        m_opIndices;
+};
+
+AtomicCounterIndexingCase::AtomicCounterIndexingCase (tcu::TestContext&                        testCtx,
+                                                                                                         const char*                           name,
+                                                                                                         const char*                           description,
+                                                                                                         IndexExprType                         indexExprType,
+                                                                                                         const glu::ShaderType         shaderType)
+       : OpaqueTypeIndexingCase        (testCtx, name, description, shaderType, indexExprType)
+       , m_opIndices                           (AtomicCounterIndexingCaseInstance::NUM_OPS)
+{
+       createShaderSpec();
+       init();
+}
+
+AtomicCounterIndexingCase::~AtomicCounterIndexingCase (void)
+{
+}
+
+TestInstance* AtomicCounterIndexingCase::createInstance (Context& ctx) const
+{
+       return new AtomicCounterIndexingCaseInstance(ctx,
+                                                                                                m_shaderType,
+                                                                                                m_shaderSpec,
+                                                                                                *m_executor,
+                                                                                                m_name,
+                                                                                                m_uniformSetup,
+                                                                                                m_opIndices,
+                                                                                                m_indexExprType);
+}
+
+void AtomicCounterIndexingCase::createShaderSpec (void)
+{
+       const int                               numCounters             = AtomicCounterIndexingCaseInstance::NUM_COUNTERS;
+       const int                               numOps                  = AtomicCounterIndexingCaseInstance::NUM_OPS;
+       deUint32                                binding                 = getFirstFreeBindingLocation(m_shaderType, m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM && numOps > 0);
+       de::Random                              rnd                             (deInt32Hash(m_shaderType) ^ deInt32Hash(m_indexExprType));
+
+       for (int opNdx = 0; opNdx < numOps; opNdx++)
+               m_opIndices[opNdx] = rnd.getInt(0, numOps-1);
+
+       {
+               const char*                     indicesPrefix   = "index";
+               const char*                     resultPrefix    = "result";
+               std::ostringstream      global, code;
+
+               if (m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL)
+                       global << "#extension GL_EXT_gpu_shader5 : require\n";
+
+               if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
+                       global << "const highp int indexBase = 1;\n";
+
+               global <<
+                       "layout(set = 0, binding = " << binding++ << ") buffer AtomicBuffer { highp uint counter[" << numCounters << "]; };\n";
+
+               if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
+               {
+                       for (int opNdx = 0; opNdx < numOps; opNdx++)
+                       {
+                               const std::string varName = indicesPrefix + de::toString(opNdx);
+                               m_shaderSpec.inputs.push_back(Symbol(varName, glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
+                       }
+               }
+               else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
+                       declareUniformIndexVars(global, indicesPrefix, numOps, binding);
+
+               for (int opNdx = 0; opNdx < numOps; opNdx++)
+               {
+                       const std::string varName = resultPrefix + de::toString(opNdx);
+                       m_shaderSpec.outputs.push_back(Symbol(varName, glu::VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP)));
+               }
+
+               for (int opNdx = 0; opNdx < numOps; opNdx++)
+               {
+                       code << resultPrefix << opNdx << " = atomicAdd(counter[";
+
+                       if (m_indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL)
+                               code << m_opIndices[opNdx];
+                       else if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
+                               code << "indexBase + " << (m_opIndices[opNdx]-1);
+                       else
+                               code << indicesPrefix << opNdx;
+
+                       code << "], uint(1));\n";
+               }
+
+               m_shaderSpec.globalDeclarations = global.str();
+               m_shaderSpec.source                             = code.str();
+       }
+}
+
+} // anonymous
+
+OpaqueTypeIndexingTests::OpaqueTypeIndexingTests (tcu::TestContext& testCtx)
+       : tcu::TestCaseGroup(testCtx, "opaque_type_indexing", "Opaque Type Indexing Tests")
+{
+}
+
+OpaqueTypeIndexingTests::~OpaqueTypeIndexingTests (void)
+{
+}
+
+void OpaqueTypeIndexingTests::init (void)
+{
+       static const struct
+       {
+               IndexExprType   type;
+               const char*             name;
+               const char*             description;
+       } indexingTypes[] =
+       {
+               { INDEX_EXPR_TYPE_CONST_LITERAL,        "const_literal",                "Indexing by constant literal"                                  },
+               { INDEX_EXPR_TYPE_CONST_EXPRESSION,     "const_expression",             "Indexing by constant expression"                               },
+               { INDEX_EXPR_TYPE_UNIFORM,                      "uniform",                              "Indexing by uniform value"                                             },
+               { INDEX_EXPR_TYPE_DYNAMIC_UNIFORM,      "dynamically_uniform",  "Indexing by dynamically uniform expression"    }
+       };
+
+       static const struct
+       {
+               glu::ShaderType type;
+               const char*             name;
+       } shaderTypes[] =
+       {
+               { glu::SHADERTYPE_VERTEX,               "vertex"        },
+               { glu::SHADERTYPE_FRAGMENT,             "fragment"      },
+               { glu::SHADERTYPE_COMPUTE,              "compute"       }
+       };
+
+       // .sampler
+       {
+               static const glu::DataType samplerTypes[] =
+               {
+                       // \note 1D images will be added by a later extension.
+//                     glu::TYPE_SAMPLER_1D,
+                       glu::TYPE_SAMPLER_2D,
+                       glu::TYPE_SAMPLER_CUBE,
+                       glu::TYPE_SAMPLER_2D_ARRAY,
+                       glu::TYPE_SAMPLER_3D,
+//                     glu::TYPE_SAMPLER_1D_SHADOW,
+                       glu::TYPE_SAMPLER_2D_SHADOW,
+                       glu::TYPE_SAMPLER_CUBE_SHADOW,
+                       glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
+//                     glu::TYPE_INT_SAMPLER_1D,
+                       glu::TYPE_INT_SAMPLER_2D,
+                       glu::TYPE_INT_SAMPLER_CUBE,
+                       glu::TYPE_INT_SAMPLER_2D_ARRAY,
+                       glu::TYPE_INT_SAMPLER_3D,
+//                     glu::TYPE_UINT_SAMPLER_1D,
+                       glu::TYPE_UINT_SAMPLER_2D,
+                       glu::TYPE_UINT_SAMPLER_CUBE,
+                       glu::TYPE_UINT_SAMPLER_2D_ARRAY,
+                       glu::TYPE_UINT_SAMPLER_3D,
+               };
+
+               tcu::TestCaseGroup* const samplerGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Sampler Array Indexing Tests");
+               addChild(samplerGroup);
+
+               for (int indexTypeNdx = 0; indexTypeNdx < DE_LENGTH_OF_ARRAY(indexingTypes); indexTypeNdx++)
+               {
+                       const IndexExprType                     indexExprType   = indexingTypes[indexTypeNdx].type;
+                       tcu::TestCaseGroup* const       indexGroup              = new tcu::TestCaseGroup(m_testCtx, indexingTypes[indexTypeNdx].name, indexingTypes[indexTypeNdx].description);
+                       samplerGroup->addChild(indexGroup);
+
+                       for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(shaderTypes); shaderTypeNdx++)
+                       {
+                               const glu::ShaderType           shaderType              = shaderTypes[shaderTypeNdx].type;
+                               tcu::TestCaseGroup* const       shaderGroup             = new tcu::TestCaseGroup(m_testCtx, shaderTypes[shaderTypeNdx].name, "");
+                               indexGroup->addChild(shaderGroup);
+
+                               for (int samplerTypeNdx = 0; samplerTypeNdx < DE_LENGTH_OF_ARRAY(samplerTypes); samplerTypeNdx++)
+                               {
+                                       const glu::DataType     samplerType     = samplerTypes[samplerTypeNdx];
+                                       const char*                     samplerName     = getDataTypeName(samplerType);
+                                       const std::string       caseName        = de::toLower(samplerName);
+
+                                       shaderGroup->addChild(new SamplerIndexingCase(m_testCtx, caseName.c_str(), "", shaderType, samplerType, indexExprType));
+                               }
+                       }
+               }
+       }
+
+       // .ubo / .ssbo / .atomic_counter
+       {
+               tcu::TestCaseGroup* const       uboGroup        = new tcu::TestCaseGroup(m_testCtx, "ubo",                              "Uniform Block Instance Array Indexing Tests");
+               tcu::TestCaseGroup* const       ssboGroup       = new tcu::TestCaseGroup(m_testCtx, "ssbo",                             "Buffer Block Instance Array Indexing Tests");
+               tcu::TestCaseGroup* const       acGroup         = new tcu::TestCaseGroup(m_testCtx, "atomic_counter",   "Atomic Counter Array Indexing Tests");
+               addChild(uboGroup);
+               addChild(ssboGroup);
+               addChild(acGroup);
+
+               for (int indexTypeNdx = 0; indexTypeNdx < DE_LENGTH_OF_ARRAY(indexingTypes); indexTypeNdx++)
+               {
+                       const IndexExprType             indexExprType           = indexingTypes[indexTypeNdx].type;
+                       const char*                             indexExprName           = indexingTypes[indexTypeNdx].name;
+                       const char*                             indexExprDesc           = indexingTypes[indexTypeNdx].description;
+
+                       for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(shaderTypes); shaderTypeNdx++)
+                       {
+                               const glu::ShaderType   shaderType              = shaderTypes[shaderTypeNdx].type;
+                               const std::string               name                    = std::string(indexExprName) + "_" + shaderTypes[shaderTypeNdx].name;
+
+                               uboGroup->addChild      (new BlockArrayIndexingCase             (m_testCtx, name.c_str(), indexExprDesc, BLOCKTYPE_UNIFORM,     indexExprType, shaderType));
+                               acGroup->addChild       (new AtomicCounterIndexingCase  (m_testCtx, name.c_str(), indexExprDesc, indexExprType, shaderType));
+
+                               if (indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL || indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
+                                       ssboGroup->addChild     (new BlockArrayIndexingCase     (m_testCtx, name.c_str(), indexExprDesc, BLOCKTYPE_BUFFER, indexExprType, shaderType));
+                       }
+               }
+       }
+}
+
+} // shaderexecutor
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.hpp b/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.hpp
new file mode 100644 (file)
index 0000000..0127f5b
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _VKTOPAQUETYPEINDEXINGTESTS_HPP
+#define _VKTOPAQUETYPEINDEXINGTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Opaque type (sampler, buffer, atomic counter, ...) indexing tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace shaderexecutor
+{
+
+class OpaqueTypeIndexingTests : public tcu::TestCaseGroup
+{
+public:
+                                                               OpaqueTypeIndexingTests         (tcu::TestContext& testCtx);
+       virtual                                         ~OpaqueTypeIndexingTests        (void);
+
+       virtual void                            init                                            (void);
+
+private:
+                                                               OpaqueTypeIndexingTests         (const OpaqueTypeIndexingTests&);
+       OpaqueTypeIndexingTests&        operator=                                       (const OpaqueTypeIndexingTests&);
+};
+
+} // shaderexecutor
+} // vkt
+
+#endif // _VKTOPAQUETYPEINDEXINGTESTS_HPP
index 2d7249e..3adc3d4 100644 (file)
@@ -55,6 +55,7 @@
 #include "vkTypeUtil.hpp"
 #include "vkQueryUtil.hpp"
 #include "vkDeviceUtil.hpp"
 #include "vkTypeUtil.hpp"
 #include "vkQueryUtil.hpp"
 #include "vkDeviceUtil.hpp"
+#include "vkImageUtil.hpp"
 
 #include "gluShaderUtil.hpp"
 
 
 #include "gluShaderUtil.hpp"
 
@@ -754,6 +755,10 @@ void FragmentOutExecutor::execute (const Context& ctx, int numValues, const void
 
        Move<VkFence>                                                                           fence;
 
 
        Move<VkFence>                                                                           fence;
 
+       Move<VkDescriptorPool>                                                          descriptorPool;
+       Move<VkDescriptorSetLayout>                                                     descriptorSetLayout;
+       Move<VkDescriptorSet>                                                           descriptorSet;
+
        clearRenderData();
 
        // Compute positions - 1px points are used to drive fragment shading.
        clearRenderData();
 
        // Compute positions - 1px points are used to drive fragment shading.
@@ -922,6 +927,35 @@ void FragmentOutExecutor::execute (const Context& ctx, int numValues, const void
                framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
        }
 
                framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
        }
 
+       // Create descriptors
+       {
+               addUniforms(vkDevice, vk, queueFamilyIndex, memAlloc);
+
+               descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
+               descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+               const VkDescriptorSetAllocateInfo allocInfo =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+                       DE_NULL,
+                       *descriptorPool,
+                       1u,
+                       &*descriptorSetLayout
+               };
+
+               descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
+
+               // Update descriptors
+               {
+                       vk::DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
+
+                       uploadUniforms(descriptorSetUpdateBuilder, *descriptorSet);
+
+                       descriptorSetUpdateBuilder.update(vk, vkDevice);
+               }
+       }
+
+
        // Create pipeline layout
        {
                const VkPipelineLayoutCreateInfo pipelineLayoutParams =
        // Create pipeline layout
        {
                const VkPipelineLayoutCreateInfo pipelineLayoutParams =
@@ -929,8 +963,8 @@ void FragmentOutExecutor::execute (const Context& ctx, int numValues, const void
                        VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
                        DE_NULL,                                                                                        // const void*                                  pNext;
                        (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
                        VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
                        DE_NULL,                                                                                        // const void*                                  pNext;
                        (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
-                       0u,                                                                                                     // deUint32                                             descriptorSetCount;
-                       DE_NULL,                                                                                        // const VkDescriptorSetLayout* pSetLayouts;
+                       1,                                                                                                      // deUint32                                             descriptorSetCount;
+                       &*descriptorSetLayout,                                                          // const VkDescriptorSetLayout* pSetLayouts;
                        0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
                        DE_NULL                                                                                         // const VkPushConstantRange*   pPushConstantRanges;
                };
                        0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
                        DE_NULL                                                                                         // const VkPushConstantRange*   pPushConstantRanges;
                };
@@ -1165,6 +1199,7 @@ void FragmentOutExecutor::execute (const Context& ctx, int numValues, const void
                vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
 
                vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
                vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
 
                vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+               vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
 
                const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
                std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
 
                const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
                std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
@@ -1868,6 +1903,7 @@ void ComputeShaderExecutor::execute (const Context& ctx, int numValues, const vo
        const DeviceInterface&                  vk                                              = ctx.getDeviceInterface();
        const VkQueue                                   queue                                   = ctx.getUniversalQueue();
        const deUint32                                  queueFamilyIndex                = ctx.getUniversalQueueFamilyIndex();
        const DeviceInterface&                  vk                                              = ctx.getDeviceInterface();
        const VkQueue                                   queue                                   = ctx.getUniversalQueue();
        const deUint32                                  queueFamilyIndex                = ctx.getUniversalQueueFamilyIndex();
+       Allocator&                                              memAlloc                                = ctx.getDefaultAllocator();
 
        Move<VkShaderModule>                    computeShaderModule;
        Move<VkPipeline>                                computePipeline;
 
        Move<VkShaderModule>                    computeShaderModule;
        Move<VkPipeline>                                computePipeline;
@@ -1920,6 +1956,8 @@ void ComputeShaderExecutor::execute (const Context& ctx, int numValues, const vo
 
        };
 
 
        };
 
+       addUniforms(vkDevice, vk, queueFamilyIndex, memAlloc);
+
        const VkDescriptorSetLayoutBinding layoutBindings[2] =
        {
                {
        const VkDescriptorSetLayoutBinding layoutBindings[2] =
        {
                {
@@ -2054,37 +2092,32 @@ void ComputeShaderExecutor::execute (const Context& ctx, int numValues, const vo
                Move<VkCommandBuffer>           cmdBuffer;
                const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset);
 
                Move<VkCommandBuffer>           cmdBuffer;
                const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset);
 
-               const VkDescriptorBufferInfo descriptorBufferInfo[] =
+               // Update descriptors
                {
                {
-                       {
-                               *m_inputBuffer,                                 // VkBuffer                     buffer;
-                               curOffset * inputStride,                // VkDeviceSize         offset;
-                               numToExec * inputStride                 // VkDeviceSize         range;
-                       },
+                       DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
+
+                       const VkDescriptorBufferInfo outputDescriptorBufferInfo =
                        {
                                *m_outputBuffer,                                // VkBuffer                     buffer;
                                curOffset * outputStride,               // VkDeviceSize         offset;
                                numToExec * outputStride                // VkDeviceSize         range;
                        {
                                *m_outputBuffer,                                // VkBuffer                     buffer;
                                curOffset * outputStride,               // VkDeviceSize         offset;
                                numToExec * outputStride                // VkDeviceSize         range;
-                       }
-               };
+                       };
 
 
-               const VkWriteDescriptorSet writeDescritporSets[] =
-               {
-                       {
-                               VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,         // VkStructureType                                      sType;
-                               DE_NULL,                                                                        // const void*                                          pNext;
-                               *descriptorSet,                                                         // VkDescriptorSet                                      destSet;
-                               0u,                                                                                     // deUint32                                                     destBinding;
-                               0u,                                                                                     // deUint32                                                     destArrayElement;
-                               2u,                                                                             // deUint32                                                     count;
-                               VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                      // VkDescriptorType                                     descriptorType;
-                               DE_NULL,                                                                        // const VkDescriptorImageInfo*         pImageInfo;
-                               descriptorBufferInfo,                                           // const VkDescriptorBufferInfo*        pBufferInfo;
-                               DE_NULL                                                                         // const VkBufferView*                          pTexelBufferView;
+                       descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo);
+
+                       if (inputStride) {
+                               const VkDescriptorBufferInfo inputDescriptorBufferInfo =
+                               {
+                                       *m_inputBuffer,                                 // VkBuffer                     buffer;
+                                       curOffset * inputStride,                // VkDeviceSize         offset;
+                                       numToExec * inputStride                 // VkDeviceSize         range;
+                               };
+                               descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo);
                        }
                        }
-               };
+                       uploadUniforms(descriptorSetUpdateBuilder, *descriptorSet);
 
 
-               vk.updateDescriptorSets(vkDevice, 1, writeDescritporSets, 0u, DE_NULL);
+                       descriptorSetUpdateBuilder.update(vk, vkDevice);
+               }
 
                cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
                VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
 
                cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
                VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
@@ -2157,6 +2190,7 @@ TessellationExecutor::~TessellationExecutor (void)
 
 void TessellationExecutor::renderTess (const Context& ctx, deUint32 vertexCount)
 {
 
 void TessellationExecutor::renderTess (const Context& ctx, deUint32 vertexCount)
 {
+       const size_t                                            inputBufferSize                         = (vertexCount/2) * getInputStride();
        const VkDevice                                          vkDevice                                        = ctx.getDevice();
        const DeviceInterface&                          vk                                                      = ctx.getDeviceInterface();
        const VkQueue                                           queue                                           = ctx.getUniversalQueue();
        const VkDevice                                          vkDevice                                        = ctx.getDevice();
        const DeviceInterface&                          vk                                                      = ctx.getDeviceInterface();
        const VkQueue                                           queue                                           = ctx.getUniversalQueue();
@@ -2349,6 +2383,7 @@ void TessellationExecutor::renderTess (const Context& ctx, deUint32 vertexCount)
                        layoutBindings                                                                                  // const VkDescriptorSetLayoutBinding   pBinding;
                };
 
                        layoutBindings                                                                                  // const VkDescriptorSetLayoutBinding   pBinding;
                };
 
+               addUniforms(vkDevice, vk, queueFamilyIndex, memAlloc);
                descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorLayoutParams);
 
                const VkDescriptorPoolSize descriptorPoolSizes[] =
                descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorLayoutParams);
 
                const VkDescriptorPoolSize descriptorPoolSizes[] =
@@ -2385,38 +2420,33 @@ void TessellationExecutor::renderTess (const Context& ctx, deUint32 vertexCount)
                };
 
                descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
                };
 
                descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
-
-               const VkDescriptorBufferInfo descriptorBufferInfo[] =
+               // Update descriptors
                {
                {
-                       {
-                               *m_inputBuffer,                                 // VkBuffer                     buffer;
-                               0u,                                                             // VkDeviceSize         offset;
-                               VK_WHOLE_SIZE                                   // VkDeviceSize         range;
-                       },
+                       DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
+                       const VkDescriptorBufferInfo outputDescriptorBufferInfo =
                        {
                                *m_outputBuffer,                                // VkBuffer                     buffer;
                                0u,                                                             // VkDeviceSize         offset;
                                VK_WHOLE_SIZE                                   // VkDeviceSize         range;
                        {
                                *m_outputBuffer,                                // VkBuffer                     buffer;
                                0u,                                                             // VkDeviceSize         offset;
                                VK_WHOLE_SIZE                                   // VkDeviceSize         range;
-                       },
-               };
+                       };
+
+                       descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo);
+
+                       if (inputBufferSize) {
+                               const VkDescriptorBufferInfo inputDescriptorBufferInfo =
+                {
+                    *m_inputBuffer,                 // VkBuffer         buffer;
+                    0u,                             // VkDeviceSize     offset;
+                    VK_WHOLE_SIZE                   // VkDeviceSize     range;
+                };
+
+                               descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo);
 
 
-               const VkWriteDescriptorSet writeDescritporSets[] =
-               {
-                       {
-                               VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,         // VkStructureType                                      sType;
-                               DE_NULL,                                                                        // const void*                                          pNext;
-                               *descriptorSet,                                                         // VkDescriptorSet                                      destSet;
-                               0u,                                                                                     // deUint32                                                     destBinding;
-                               0u,                                                                                     // deUint32                                                     destArrayElement;
-                               2u,                                                                                     // deUint32                                                     count;
-                               VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                      // VkDescriptorType                                     descriptorType;
-                               DE_NULL,                                                                        // const VkDescriptorImageInfo*         pImageInfo;
-                               descriptorBufferInfo,                                           // const VkDescriptorBufferInfo*        pBufferInfo;
-                               DE_NULL                                                                         // const VkBufferView*                          pTexelBufferView;
                        }
                        }
-               };
+                       uploadUniforms(descriptorSetUpdateBuilder, *descriptorSet);
 
 
-               vk.updateDescriptorSets(vkDevice, 1, writeDescritporSets, 0u, DE_NULL);
+                       descriptorSetUpdateBuilder.update(vk, vkDevice);
+               }
        }
 
        // Create pipeline layout
        }
 
        // Create pipeline layout
@@ -2959,5 +2989,301 @@ ShaderExecutor* createExecutor (glu::ShaderType shaderType, const ShaderSpec& sh
        }
 }
 
        }
 }
 
+void ShaderExecutor::setupUniformData (const VkDevice& vkDevice, const DeviceInterface& vk, const deUint32 queueFamilyIndex, Allocator& memAlloc, deUint32 bindingLocation, deUint32 size, const void* dataPtr)
+{
+       const VkBufferCreateInfo uniformBufferParams =
+       {
+               VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
+               DE_NULL,                                                                        // const void*                  pNext;
+               size,                                                                           // VkDeviceSize                 size;
+               VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                     // VkBufferUsageFlags   usage;
+               0u,                                                                                     // VkBufferCreateFlags  flags;
+               VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
+               1u,                                                                                     // deUint32                             queueFamilyCount;
+               &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
+       };
+
+       Move<VkBuffer>                                  buffer                          = createBuffer(vk, vkDevice, &uniformBufferParams);
+       de::MovePtr<Allocation>                 alloc                           = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
+       VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
+
+       deMemcpy(alloc->getHostPtr(), dataPtr, size);
+       flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
+
+       de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
+       //? storage vagy uniform  shaderben mi van???? storage v unuiform
+       uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+       uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size);
+       uniformInfo->location = bindingLocation;
+       uniformInfo->buffer = VkBufferSp(new Unique<VkBuffer>(buffer));
+       uniformInfo->alloc = AllocationSp(alloc.release());
+
+       m_descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
+       m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
+
+       m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
+}
+
+void ShaderExecutor::setupSamplerData  (const VkDevice&                                vkDevice,
+                                                                                const DeviceInterface&                 vk,
+                                                                                const deUint32                                 queueFamilyIndex,
+                                                                                Allocator&                                             memAlloc,
+                                                                                deUint32                                               bindingLocation,
+                                                                                deUint32                                               numSamplers,
+                                                                                const tcu::Sampler&                    refSampler,
+                                                                                const tcu::TextureFormat&              texFormat,
+                                                                                const tcu::IVec3&                              texSize,
+                                                                                VkImageType                                    imageType,
+                                                                                VkImageViewType                                imageViewType,
+                                                                                const void*                                    data)
+{
+       DE_ASSERT(numSamplers > 0);
+
+       std::vector<VkSampler>                          vkSamplers;
+       de::MovePtr<SamplerArrayUniform>        samplers                (new SamplerArrayUniform());
+
+       samplers->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+       samplers->location = bindingLocation;
+
+       for (deUint32 ndx = 0; ndx < numSamplers; ++ndx)
+       {
+               const int                                               offset                  = ndx * texSize.x() * texSize.y() * texSize.z() * texFormat.getPixelSize();
+               const void*                                             samplerData             = ((deUint32*)data) + offset;
+               de::MovePtr<SamplerUniform>             uniform                 = createSamplerUniform(vkDevice, vk, queueFamilyIndex, memAlloc, bindingLocation, refSampler, texFormat, texSize, imageType, imageViewType, samplerData);
+
+               vkSamplers.push_back(uniform->sampler.get()->get());
+
+               samplers->uniforms.push_back(SamplerUniformSp(new de::UniquePtr<SamplerUniform>(uniform)));
+               //samplers->uniforms.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
+       }
+
+       m_descriptorSetLayoutBuilder.addArraySamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, numSamplers, VK_SHADER_STAGE_ALL, &vkSamplers[0]);
+       m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, numSamplers);
+
+       m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(samplers)));
+}
+
+
+void ShaderExecutor::addUniforms (const VkDevice& vkDevice, const DeviceInterface& vk, const deUint32 queueFamilyIndex, Allocator& memAlloc)
+{
+       if (!m_uniformSetup)
+               return;
+
+       for (std::vector<UniformDataSp>::const_iterator it = m_uniformSetup->uniforms().begin(); it != m_uniformSetup->uniforms().end(); ++it)
+       {
+               const UniformDataBase* uniformData = it->get()->get();
+               uniformData->setup(*this, vkDevice, vk, queueFamilyIndex, memAlloc);
+       }
+}
+
+void ShaderExecutor::uploadUniforms (DescriptorSetUpdateBuilder& descriptorSetUpdateBuilder, VkDescriptorSet descriptorSet)
+{
+       for (std::vector<UniformInfoSp>::const_iterator it = m_uniformInfos.begin(); it != m_uniformInfos.end(); ++it)
+       {
+               const UniformInfo* uniformInfo = it->get()->get();
+
+               if (uniformInfo->isSamplerArray())
+               {
+                       const SamplerArrayUniform*                      arrayInfo               = static_cast<const SamplerArrayUniform*>(uniformInfo);
+                       std::vector<VkDescriptorImageInfo>      descriptors;
+
+                       for (std::vector<SamplerUniformSp>::const_iterator ait = arrayInfo->uniforms.begin(); ait != arrayInfo->uniforms.end(); ++ait)
+                       {
+                               descriptors.push_back(ait->get()->get()->descriptor);
+                       }
+
+                       descriptorSetUpdateBuilder.writeArray(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(uniformInfo->location), uniformInfo->type, (deUint32)descriptors.size(), &descriptors[0]);
+               }
+               else if (uniformInfo->isBufferUniform()) {
+                       const BufferUniform* bufferUniform = static_cast<const BufferUniform*>(uniformInfo);
+                       descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferUniform->location), bufferUniform->type, &bufferUniform->descriptor);
+               }
+               else if (uniformInfo->isSamplerUniform()) {
+            const SamplerUniform* samplerUniform = static_cast<const SamplerUniform*>(uniformInfo);
+            descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(samplerUniform->location),  samplerUniform->type, &samplerUniform->descriptor);
+        }
+       }
+}
+
+Move<VkImage> ShaderExecutor::createCombinedImage      (const VkDevice&                                vkDevice,
+                                                                                                        const DeviceInterface&                 vk,
+                                                                                                        const deUint32                                 queueFamilyIndex,
+                                                                                                        const tcu::IVec3&                              texSize,
+                                                                                                        const VkFormat                                 format,
+                                                                                                        const VkImageType                              imageType,
+                                                                                                        const VkImageUsageFlags                usage,
+                                                                                                        const VkImageTiling                    tiling)
+{
+       const VkImageCreateInfo imageCreateInfo         =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                            // VkStructureType                      sType;
+               DE_NULL,                                                                                                        // const void*                          pnext;
+               0,                                                                                                                      // VkImageCreateFlags           flags;
+               imageType,                                                                                                      // VkImageType                          imageType;
+               format,                                                                                                         // VkFormat                                     format;
+               { texSize.x(), texSize.y(), texSize.z() },                                      // VkExtend3D                           extent;
+               1u,                                                                                                                     // deUint32                                     mipLevels;
+               1u,                                                                                                                     // deUint32                                     arraySize;
+               VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits        samples;
+               tiling,                                                                                                         // VkImageTiling                        tiling;
+               usage,                                                                                                          // VkImageUsageFlags            usage;
+               VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                        sharingMode;
+               1,                                                                                                                      // deuint32                                     queueFamilyCount;
+               &queueFamilyIndex,                                                                                      // const deUint32*                      pQueueFamilyIndices;
+               VK_IMAGE_LAYOUT_UNDEFINED,                                                                      // VkImageLayout                        initialLayout;
+       };
+
+       Move<VkImage>                   vkTexture                       = createImage(vk, vkDevice, &imageCreateInfo);
+       return vkTexture;
+}
+
+de::MovePtr<Allocation> ShaderExecutor::uploadImage (const VkDevice&                           vkDevice,
+                                                                                                        const DeviceInterface&                 vk,
+                                                                                                        Allocator&                                             memAlloc,
+                                                                                                        const tcu::TextureFormat&              texFormat,
+                                                                                                        const tcu::IVec3&                              texSize,
+                                                                                                        const void*                                    data,
+                                                                                                        const VkImage&                                 vkTexture)
+{
+       de::MovePtr<Allocation>         allocation                      = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, vkTexture), MemoryRequirement::HostVisible);
+       VK_CHECK(vk.bindImageMemory(vkDevice, vkTexture, allocation->getMemory(), allocation->getOffset()));
+
+       const VkImageSubresource        subres                          =
+       {
+               VK_IMAGE_ASPECT_COLOR_BIT,                                              // VkImageAspectFlags   aspectMask;
+               0u,                                                                                             // deUint32                             mipLevel;
+               0u                                                                                              // deUint32                             arraySlice
+       };
+
+       VkSubresourceLayout layout;
+       vk.getImageSubresourceLayout(vkDevice, vkTexture, &subres, &layout);
+
+       tcu::ConstPixelBufferAccess     access (texFormat, texSize, data);
+       tcu::PixelBufferAccess          destAccess      (texFormat, texSize, allocation->getHostPtr());
+
+       tcu::copy(destAccess, access);
+
+       flushMappedMemoryRange(vk, vkDevice, allocation->getMemory(), allocation, layout.size);
+
+       return allocation;
+}
+
+
+de::MovePtr<ShaderExecutor::SamplerUniform> ShaderExecutor::createSamplerUniform       (const VkDevice&                        vkDevice,
+                                                                                                                                                                        const DeviceInterface&         vk,
+                                                                                                                                                                        const deUint32                         queueFamilyIndex,
+                                                                                                                                                                        Allocator&                                     memAlloc,
+                                                                                                                                                                        deUint32                                       bindingLocation,
+                                                                                                                                                                        const tcu::Sampler&            refSampler,
+                                                                                                                                                                        const tcu::TextureFormat&      texFormat,
+                                                                                                                                                                        const tcu::IVec3&                      texSize,
+                                                                                                                                                                        VkImageType                            imageType,
+                                                                                                                                                                        VkImageViewType                        imageViewType,
+                                                                                                                                                                        const void*                            data)
+{
+       const VkFormat                                  format          = mapTextureFormat(texFormat);
+       Move<VkImage>                                   vkTexture;
+       de::MovePtr<Allocation>                 allocation;
+
+       vkTexture = createCombinedImage(vkDevice, vk, queueFamilyIndex, texSize, format, imageType, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_LINEAR);
+       allocation = uploadImage(vkDevice, vk, memAlloc, texFormat, texSize, data, *vkTexture);
+
+       // Create sampler
+       const bool                                              compareEnabled  = (refSampler.compare != tcu::Sampler::COMPAREMODE_NONE);
+       const VkSamplerCreateInfo               samplerParams   =
+       {
+               VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,                  // VkStructureType              sType;
+               DE_NULL,                                                                                // const void*                  pNext;
+               VkSamplerCreateFlags(0u),                                               // VkSamplerCreateFlags flags;
+               mapFilterMode(refSampler.magFilter),                    // VkTexFilter                  magFilter;
+               mapFilterMode(refSampler.minFilter),                    // VkTexFilter                  minFilter;
+               mapMipmapMode(refSampler.minFilter),                    // VkTexMipmapMode              mipMode;
+               mapWrapMode(refSampler.wrapS),                                  // VkTexAddressMode             addressModeU;
+               mapWrapMode(refSampler.wrapT),                                  // VkTexAddressMode             addressModeV;
+               mapWrapMode(refSampler.wrapR),                                  // VkTexAddressMode             addressModeW;
+               refSampler.lodThreshold,                                                // float                                mipLodBias;
+               1,                                                                                              // float                                maxAnisotropy;
+               compareEnabled,                                                                 // VkBool32                             compareEnable;
+               mapCompareMode(refSampler.compare),                             // VkCompareOp                  compareOp;
+               0.0f,                                                                                   // float                                minLod;
+               0.0f,                                                                                   // float                                maxLod;
+               VK_BORDER_COLOR_INT_OPAQUE_WHITE,                               // VkBorderColor                boderColor;
+               VK_FALSE,                                                                               // VkBool32                             unnormalizerdCoordinates;
+       };
+
+       Move<VkSampler>                                 sampler                 = createSampler(vk, vkDevice, &samplerParams);
+
+       const VkImageViewCreateInfo             viewParams              =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                      sType;
+               NULL,                                                                           // const voide*                         pNexŧ;
+               0u,                                                                                     // VkImageViewCreateFlags       flags;
+               *vkTexture,                                                                     // VkImage                                      image;
+               imageViewType,                                                          // VkImageViewType                      viewType;
+               format,                                                                         // VkFormat                                     format;
+               {
+                       VK_COMPONENT_SWIZZLE_R,                                         // VkComponentSwizzle           r;
+                       VK_COMPONENT_SWIZZLE_G,                                         // VkComponentSwizzle           g;
+                       VK_COMPONENT_SWIZZLE_B,                                         // VkComponentSwizzle           b;
+                       VK_COMPONENT_SWIZZLE_A                                          // VkComponentSwizzle           a;
+               },                                                                                      // VkComponentMapping                   components;
+               {
+                       VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags   aspectMask;
+                       0,                                                                                      // deUint32                             baseMipLevel;
+                       1,                                                                                      // deUint32                             mipLevels;
+                       0,                                                                                      // deUint32                             baseArraySlice;
+                       1                                                                                       // deUint32                             arraySize;
+               }                                                                                       // VkImageSubresourceRange      subresourceRange;
+       };
+
+       Move<VkImageView>                               imageView               = createImageView(vk, vkDevice, &viewParams);
+
+       const VkDescriptorImageInfo descriptor                  =
+       {
+               sampler.get(),                                                          // VkSampler                            sampler;
+               imageView.get(),                                                        // VkImageView                          imageView;
+               VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        imageLayout;
+       };
+
+       de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
+       uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+       uniform->descriptor = descriptor;
+       uniform->location = bindingLocation;
+       uniform->image = VkImageSp(new Unique<VkImage>(vkTexture));
+       uniform->imageView = VkImageViewSp(new Unique<VkImageView>(imageView));
+       uniform->sampler = VkSamplerSp(new Unique<VkSampler>(sampler));
+       uniform->alloc = AllocationSp(allocation.release());
+
+       return uniform;
+}
+
+SamplerUniformData::SamplerUniformData (deUint32                                               bindingLocation,
+                                                                               deUint32                                                numSamplers,
+                                                                               const tcu::Sampler&                             refSampler,
+                                                                               const tcu::TextureFormat&               texFormat,
+                                                                               const tcu::IVec3&                               texSize,
+                                                                               VkImageType                                             imageType,
+                                                                               VkImageViewType                                 imageViewType,
+                                                                               const void*                                             data)
+       : UniformDataBase               (bindingLocation)
+       , m_numSamplers                 (numSamplers)
+       , m_refSampler                  (refSampler)
+       , m_texFormat                   (texFormat)
+       , m_texSize                             (texSize)
+       , m_imageType                   (imageType)
+       , m_imageViewType               (imageViewType)
+       , m_data                                (data)
+{
+}
+
+SamplerUniformData::~SamplerUniformData (void)
+{
+}
+
+void SamplerUniformData::setup (ShaderExecutor& executor, const VkDevice& vkDevice, const DeviceInterface& vk, const deUint32 queueFamilyIndex, Allocator& memAlloc) const
+{
+       executor.setupSamplerData(vkDevice, vk, queueFamilyIndex, memAlloc, m_bindingLocation, m_numSamplers, m_refSampler, m_texFormat, m_texSize, m_imageType, m_imageViewType, m_data);
+}
+
 } // shaderexecutor
 } // vkt
 } // shaderexecutor
 } // vkt
index 6f6d523..1195fa5 100644 (file)
  * \brief Vulkan ShaderExecutor
  *//*--------------------------------------------------------------------*/
 
  * \brief Vulkan ShaderExecutor
  *//*--------------------------------------------------------------------*/
 
+#include "deSharedPtr.hpp"
+
 #include "vktTestCase.hpp"
 #include "vktTestCase.hpp"
-#include "vkPrograms.hpp"
+#include "vkMemUtil.hpp"
+#include "vkBuilderUtil.hpp"
 
 #include "gluVarType.hpp"
 
 
 #include "gluVarType.hpp"
 
+#include "tcuTexture.hpp"
+
 #include <vector>
 
 namespace vkt
 #include <vector>
 
 namespace vkt
@@ -47,6 +52,8 @@ namespace vkt
 namespace shaderexecutor
 {
 
 namespace shaderexecutor
 {
 
+using namespace vk;
+
 //! Shader input / output variable declaration.
 struct Symbol
 {
 //! Shader input / output variable declaration.
 struct Symbol
 {
@@ -69,6 +76,36 @@ struct ShaderSpec
        ShaderSpec (void) {}
 };
 
        ShaderSpec (void) {}
 };
 
+// UniformSetup
+
+class UniformDataBase;
+class ShaderExecutor;
+
+typedef de::SharedPtr<de::UniquePtr<UniformDataBase> > UniformDataSp;
+
+class UniformSetup
+{
+public:
+                                                                               UniformSetup            (void) {}
+       virtual                                                         ~UniformSetup           (void) {}
+
+       void                                                            addData                         (UniformDataBase* uniformData)
+                                                                               {
+                                                                                       m_uniforms.push_back(UniformDataSp(new de::UniquePtr<UniformDataBase>(uniformData)));
+                                                                               }
+
+       const std::vector<UniformDataSp>&       uniforms                        (void) const
+                                                                               {
+                                                                                       return m_uniforms;
+                                                                               }
+
+private:
+                                                                               UniformSetup            (const UniformSetup&);  // not allowed!
+       UniformSetup&                                           operator=                       (const UniformSetup&);  // not allowed!
+
+       std::vector<UniformDataSp>                      m_uniforms;
+};
+
 //! Base class for shader executor.
 class ShaderExecutor
 {
 //! Base class for shader executor.
 class ShaderExecutor
 {
@@ -81,13 +118,141 @@ public:
        //! Execute
        virtual void                    execute                         (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs) = 0;
 
        //! Execute
        virtual void                    execute                         (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs) = 0;
 
-       virtual void                    setShaderSources        (vk::SourceCollections& programCollection) const = 0;
+       virtual void                    setShaderSources        (SourceCollections& programCollection) const = 0;
+
+       void                                    setUniforms                     (const UniformSetup* uniformSetup)
+                                                                                               {
+                                                                                                       m_uniformSetup = de::MovePtr<const UniformSetup>(uniformSetup);
+                                                                                               };
+
+       void                                    setupUniformData        (const VkDevice&                        vkDevice,
+                                                                                                const DeviceInterface&         vk,
+                                                                                                const deUint32                         queueFamilyIndex,
+                                                                                                Allocator&                                     memAlloc,
+                                                                                                deUint32                                       bindingLocation,
+                                                                                                deUint32                                       size,
+                                                                                                const void*                            dataPtr);
+
+       void                                    setupSamplerData        (const VkDevice&                        vkDevice,
+                                                                                                const DeviceInterface&         vk,
+                                                                                                const deUint32                         queueFamilyIndex,
+                                                                                                Allocator&                                     memAlloc,
+                                                                                                deUint32                                       bindingLocation,
+                                                                                                deUint32                                       numSamplers,
+                                                                                                const tcu::Sampler&            refSampler,
+                                                                                                const tcu::TextureFormat&      texFormat,
+                                                                                                const tcu::IVec3&                      texSize,
+                                                                                                VkImageType                            imageType,
+                                                                                                VkImageViewType                        imageViewType,
+                                                                                                const void*                            data);
+
 
 protected:
                                                        ShaderExecutor          (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
 
 
 protected:
                                                        ShaderExecutor          (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
 
-       const ShaderSpec                m_shaderSpec;
-       const glu::ShaderType   m_shaderType;
+       void                                    addUniforms                     (const VkDevice& vkDevice, const DeviceInterface& vk, const deUint32 queueFamilyIndex, Allocator& memAlloc);
+
+       void                                    uploadUniforms          (DescriptorSetUpdateBuilder& descriptorSetUpdateBuilder, VkDescriptorSet descriptorSet);
+
+       class UniformInfo;
+       typedef de::SharedPtr<de::UniquePtr<UniformInfo> >                      UniformInfoSp;
+
+       class SamplerUniform;
+       typedef de::SharedPtr<de::UniquePtr<SamplerUniform> >           SamplerUniformSp;
+
+
+       typedef de::SharedPtr<Unique<VkBuffer> >                        VkBufferSp;
+       typedef de::SharedPtr<Unique<VkImage> >                         VkImageSp;
+       typedef de::SharedPtr<Unique<VkImageView> >                     VkImageViewSp;
+       typedef de::SharedPtr<Unique<VkSampler> >                       VkSamplerSp;
+       typedef de::SharedPtr<Allocation>                                       AllocationSp;
+
+
+       class UniformInfo
+       {
+       public:
+                                                                       UniformInfo                     (void) {}
+               virtual                                         ~UniformInfo            (void) {}
+               virtual bool                            isSamplerArray          (void) const { return false; }
+               virtual bool                            isBufferUniform         (void) const { return false; }
+               virtual bool                            isSamplerUniform        (void) const { return false; }
+
+               VkDescriptorType                        type;
+               deUint32                                        location;
+       };
+
+       class BufferUniform : public UniformInfo
+       {
+       public:
+                                                                       BufferUniform           (void) {}
+               virtual                                         ~BufferUniform          (void) {}
+               virtual bool                            isBufferUniform         (void) const { return true; }
+
+               VkBufferSp                                      buffer;
+               AllocationSp                            alloc;
+               VkDescriptorBufferInfo          descriptor;
+       };
+
+       class SamplerUniform : public UniformInfo
+       {
+       public:
+                                                                       SamplerUniform          (void) {}
+               virtual                                         ~SamplerUniform         (void) {}
+               virtual bool                            isSamplerUniform        (void) const { return true; }
+               VkImageSp                                       image;
+               VkImageViewSp                           imageView;
+               VkSamplerSp                                     sampler;
+               AllocationSp                            alloc;
+               VkDescriptorImageInfo           descriptor;
+       };
+
+       class SamplerArrayUniform : public UniformInfo
+       {
+       public:
+                                                                                               SamplerArrayUniform             (void) {}
+               virtual                                                                 ~SamplerArrayUniform    (void) {}
+               virtual bool                                                    isSamplerArray                  (void) const { return true; }
+
+               std::vector<SamplerUniformSp>           uniforms;
+       };
+
+       Move<VkImage>                                                           createCombinedImage                             (const VkDevice&                                vkDevice,
+                                                                                                                                                                const DeviceInterface&                 vk,
+                                                                                                                                                                const deUint32                                 queueFamilyIndex,
+                                                                                                                                                                const tcu::IVec3&                              texSize,
+                                                                                                                                                                const VkFormat                         format,
+                                                                                                                                                                const VkImageType                      imageType,
+                                                                                                                                                                const VkImageUsageFlags        usage,
+                                                                                                                                                                const VkImageTiling            tiling);
+
+       de::MovePtr<Allocation>                                                 uploadImage                                     (const VkDevice&                                vkDevice,
+                                                                                                                                                                const DeviceInterface&                 vk,
+                                                                                                                                                                Allocator&                                             memAlloc,
+                                                                                                                                                                const tcu::TextureFormat&              texFormat,
+                                                                                                                                                                const tcu::IVec3&                              texSize,
+                                                                                                                                                                const void*                                    data,
+                                                                                                                                                                const VkImage&                         vkTexture);
+
+       de::MovePtr<SamplerUniform>                                                     createSamplerUniform    (const VkDevice&                                vkDevice,
+                                                                                                                                                                const DeviceInterface&                 vk,
+                                                                                                                                                                const deUint32                                 queueFamilyIndex,
+                                                                                                                                                                Allocator&                                             memAlloc,
+                                                                                                                                                                deUint32                                               bindingLocation,
+                                                                                                                                                                const tcu::Sampler&                    refSampler,
+                                                                                                                                                                const tcu::TextureFormat&              texFormat,
+                                                                                                                                                                const tcu::IVec3&                              texSize,
+                                                                                                                                                                VkImageType                                    imageType,
+                                                                                                                                                                VkImageViewType                                imageViewType,
+                                                                                                                                                                const void*                                    data);
+
+       const ShaderSpec                                                                        m_shaderSpec;
+       const glu::ShaderType                                                           m_shaderType;
+
+       std::vector<UniformInfoSp>                                                      m_uniformInfos;
+       de::MovePtr<const UniformSetup>                                         m_uniformSetup;
+       DescriptorSetLayoutBuilder                                                      m_descriptorSetLayoutBuilder;
+       DescriptorPoolBuilder                                                           m_descriptorPoolBuilder;
+
 };
 
 inline tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderExecutor* executor) { executor->log(log); return log; }
 };
 
 inline tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderExecutor* executor) { executor->log(log); return log; }
@@ -95,6 +260,75 @@ inline tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderExecutor& execut
 
 ShaderExecutor* createExecutor(glu::ShaderType shaderType, const ShaderSpec& shaderSpec);
 
 
 ShaderExecutor* createExecutor(glu::ShaderType shaderType, const ShaderSpec& shaderSpec);
 
+
+class UniformDataBase
+{
+public:
+                                                       UniformDataBase         (deUint32 bindingLocation)
+                                                                                                       : m_bindingLocation             (bindingLocation)
+                                                                                               {
+                                                                                               }
+       virtual                                 ~UniformDataBase        (void) {}
+       virtual void                    setup                           (ShaderExecutor&, const VkDevice&, const DeviceInterface&, const deUint32, Allocator&) const = 0;
+
+protected:
+       const deUint32                  m_bindingLocation;
+};
+
+template<typename T>
+class UniformData : public UniformDataBase
+{
+public:
+                                                       UniformData                     (deUint32 bindingLocation, const T data);
+       virtual                                 ~UniformData            (void);
+       virtual void                    setup                           (ShaderExecutor& executor, const VkDevice& vkDevice, const DeviceInterface& vk, const deUint32 queueFamilyIndex, Allocator& memAlloc) const;
+
+private:
+       T                                               m_data;
+};
+
+template<typename T>
+UniformData<T>::UniformData (deUint32 bindingLocation, const T data)
+       : UniformDataBase               (bindingLocation)
+       , m_data                                (data)
+{
+}
+
+template<typename T>
+UniformData<T>::~UniformData (void)
+{
+}
+
+template<typename T>
+void UniformData<T>::setup (ShaderExecutor& executor, const VkDevice& vkDevice, const DeviceInterface& vk, const deUint32 queueFamilyIndex, Allocator& memAlloc) const
+{
+       executor.setupUniformData(vkDevice, vk, queueFamilyIndex, memAlloc, m_bindingLocation, sizeof(T), &m_data);
+}
+
+class SamplerUniformData : public UniformDataBase
+{
+public:
+                                                       SamplerUniformData      (deUint32                                               bindingLocation,
+                                                                                                deUint32                                               numSamplers,
+                                                                                                const tcu::Sampler&                    refSampler,
+                                                                                                const tcu::TextureFormat&              texFormat,
+                                                                                                const tcu::IVec3&                              texSize,
+                                                                                                VkImageType                                    imageType,
+                                                                                                VkImageViewType                                imageViewType,
+                                                                                                const void*                                    data);
+       virtual                                 ~SamplerUniformData     (void);
+       virtual void                    setup                           (ShaderExecutor& executor, const VkDevice& vkDevice, const DeviceInterface& vk, const deUint32 queueFamilyIndex, Allocator& memAlloc) const;
+
+private:
+       deUint32                                        m_numSamplers;
+       const tcu::Sampler                      m_refSampler;
+       const tcu::TextureFormat        m_texFormat;
+       const tcu::IVec3                        m_texSize;
+       VkImageType                                     m_imageType;
+       VkImageViewType                         m_imageViewType;
+       const void*                                     m_data;
+};
+
 } // shaderexecutor
 } // vkt
 
 } // shaderexecutor
 } // vkt
 
index a855f00..6d0f02c 100644 (file)
@@ -42,6 +42,7 @@
 #include "vktShaderCommonFunctionTests.hpp"
 #include "vktShaderIntegerFunctionTests.hpp"
 #include "vktShaderPackingFunctionTests.hpp"
 #include "vktShaderCommonFunctionTests.hpp"
 #include "vktShaderIntegerFunctionTests.hpp"
 #include "vktShaderPackingFunctionTests.hpp"
+#include "vktOpaqueTypeIndexingTests.hpp"
 
 namespace vkt
 {
 
 namespace vkt
 {
@@ -57,6 +58,7 @@ tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
        shaderExecutorTests->addChild(new ShaderCommonFunctionTests(testCtx));
        shaderExecutorTests->addChild(new ShaderIntegerFunctionTests(testCtx));
        shaderExecutorTests->addChild(new ShaderPackingFunctionTests(testCtx));
        shaderExecutorTests->addChild(new ShaderCommonFunctionTests(testCtx));
        shaderExecutorTests->addChild(new ShaderIntegerFunctionTests(testCtx));
        shaderExecutorTests->addChild(new ShaderPackingFunctionTests(testCtx));
+       shaderExecutorTests->addChild(new OpaqueTypeIndexingTests(testCtx));
 
        return shaderExecutorTests.release();
 }
 
        return shaderExecutorTests.release();
 }