Use de::ArrayBuffer in glu::TextureBuffer.
authorJarkko Pöyry <jpoyry@google.com>
Fri, 13 Mar 2015 19:32:21 +0000 (12:32 -0700)
committerJarkko Poyry <jpoyry@google.com>
Fri, 1 May 2015 20:47:17 +0000 (20:47 +0000)
- Use de::ArrayBuffer to make valgrind runs report incorrect use.
- Fix incorrect index when printing expected value in mapped memory
  content verification.
- Remove bufferData for consistency with other glu::Texture-types.
- Add de::ArrayBuffer(ptr, len) std::vector-like ctor.
- Throw NotSupported if MAX_TEXTURE_BUFFER_SIZE is 0.

Bug: 20667734
Change-Id: I574f0952b1bd97803cd52564b2ee9967ecde105a

framework/delibs/decpp/deArrayBuffer.hpp
framework/opengl/gluTexture.cpp
framework/opengl/gluTexture.hpp
framework/opengl/gluTextureUtil.cpp
framework/opengl/gluTextureUtil.hpp
modules/gles31/functional/es31fTextureFormatTests.cpp
modules/glshared/glsTextureBufferCase.cpp

index 0ecb690..5a98898 100644 (file)
@@ -48,8 +48,11 @@ template <typename T, size_t Alignment = (sizeof(T) > 4 ? 4 : sizeof(T)), size_t
 class ArrayBuffer
 {
 public:
+       DE_STATIC_ASSERT(Stride >= sizeof(T));
+
                                        ArrayBuffer             (void) throw();
                                        ArrayBuffer             (size_t numElements);
+                                       ArrayBuffer             (const T* ptr, size_t numElements);
                                        ArrayBuffer             (const ArrayBuffer& other);
                                        ~ArrayBuffer    (void) throw();
        ArrayBuffer&    operator=               (const ArrayBuffer& other);
@@ -97,6 +100,33 @@ ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (size_t numElements)
 }
 
 template <typename T, size_t Alignment, size_t Stride>
+ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const T* ptr, size_t numElements)
+       : m_ptr (DE_NULL)
+       , m_cap (0)
+{
+       if (numElements)
+       {
+               // create new buffer of wanted size, copy to it, and swap to it
+               ArrayBuffer<T,Alignment,Stride> tmp(numElements);
+
+               if (Stride == sizeof(T))
+               {
+                       // tightly packed
+                       const size_t storageSize = sizeof(T) * numElements;
+                       deMemcpy(tmp.m_ptr, ptr, (int)storageSize);
+               }
+               else
+               {
+                       // sparsely packed
+                       for (size_t ndx = 0; ndx < numElements; ++ndx)
+                               *tmp.getElementPtr(ndx) = ptr[ndx];
+               }
+
+               swap(tmp);
+       }
+}
+
+template <typename T, size_t Alignment, size_t Stride>
 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const ArrayBuffer<T,Alignment,Stride>& other)
        : m_ptr (DE_NULL)
        , m_cap (0)
index 7ae0a3c..d81bda1 100644 (file)
@@ -839,10 +839,9 @@ void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t off
                }
        }
 
-       m_refBuffer.resize(bufferSize, 0);
-
+       m_refBuffer.setStorage(bufferSize);
        if (data)
-               deMemcpy(&m_refBuffer[0], data, (int)bufferSize);
+               deMemcpy(m_refBuffer.getPtr(), data, (int)bufferSize);
 
        m_format        = internalFormat;
        m_offset        = offset;
@@ -851,16 +850,6 @@ void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t off
        DE_ASSERT(size != 0 || offset == 0);
 
        {
-               const tcu::TextureFormat        format                  = mapGLInternalFormat(internalFormat);
-               deInt32                                         maxTextureSize  = 0;
-
-               gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
-               GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed");
-
-               m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : bufferSize) / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset]));
-       }
-
-       {
                gl.genTextures(1, &m_glTexture);
                GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
 
@@ -868,7 +857,7 @@ void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t off
                GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
 
                gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
-               gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW);
+               gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), data, GL_STATIC_DRAW);
                gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
                GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer");
 
@@ -893,31 +882,31 @@ TextureBuffer::~TextureBuffer (void)
                m_context.getFunctions().deleteBuffers(1, &m_glBuffer);
 }
 
-void TextureBuffer::upload (void)
+
+const tcu::PixelBufferAccess TextureBuffer::getFullRefTexture (void)
 {
-       const glw::Functions& gl = m_context.getFunctions();
+       const tcu::TextureFormat        format                          = mapGLInternalFormat(m_format);
+       const size_t                            bufferLengthBytes       = (m_size != 0) ? (m_size) : (m_refBuffer.size());
+       const int                                       bufferLengthPixels      = (int)bufferLengthBytes / format.getPixelSize();
 
-       gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
-       gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW);
-       gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer");
+       return tcu::PixelBufferAccess(format,
+                                                                 tcu::IVec3(bufferLengthPixels, 1, 1),
+                                                                 (deUint8*)m_refBuffer.getPtr() + m_offset);
 }
 
-void TextureBuffer::bufferData (const deUint8* data, size_t size)
+const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const
 {
-       const glw::Functions& gl = m_context.getFunctions();
-
-       m_refBuffer = vector<deUint8>(data, data+size);
-
-       {
-               const tcu::TextureFormat        format                  = mapGLInternalFormat(m_format);
-               deInt32                                         maxTextureSize  = 0;
+       return const_cast<TextureBuffer*>(this)->getFullRefTexture();
+}
 
-               gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
-               GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed");
+void TextureBuffer::upload (void)
+{
+       const glw::Functions& gl = m_context.getFunctions();
 
-               m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : m_refBuffer.size())  / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset]));
-       }
+       gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
+       gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), m_refBuffer.getPtr(), GL_STATIC_DRAW);
+       gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer");
 }
 
 } // glu
index 1a8d7db..f3670d7 100644 (file)
@@ -276,11 +276,13 @@ public:
 
                                                                                ~TextureBuffer          (void);
 
-       const tcu::PixelBufferAccess&           getRefTexture           (void)                  { return m_refTexture;                  }
-       const tcu::ConstPixelBufferAccess&      getRefTexture           (void) const    { return m_refTexture;                  }
+       // \note Effective pixel buffer access must be limited to w <= GL_MAX_TEXTURE_BUFFER_SIZE
+       const tcu::PixelBufferAccess            getFullRefTexture       (void);
+       const tcu::ConstPixelBufferAccess       getFullRefTexture       (void) const;
 
-       deUint8*                                                        getRefBuffer            (void)                  { return &(m_refBuffer[0]);             }
-       const deUint8*                                          getRefBuffer            (void) const    { return &(m_refBuffer[0]);             }
+       // \note mutating buffer storage will invalidate existing pixel buffer accesses
+       de::ArrayBuffer<deUint8>&                       getRefBuffer            (void)                  { return m_refBuffer;                   }
+       const de::ArrayBuffer<deUint8>&         getRefBuffer            (void) const    { return m_refBuffer;                   }
 
        size_t                                                          getSize                         (void) const    { return m_size;                                }
        size_t                                                          getOffset                       (void) const    { return m_offset;                              }
@@ -289,25 +291,21 @@ public:
        deUint32                                                        getGLTexture            (void) const    { return m_glTexture;                   }
        deUint32                                                        getGLBuffer                     (void) const    { return m_glBuffer;                    }
 
-       // \note Resizes reference buffer. Invalidates old pixel buffer acceses.
-       // \note Doesn't upload data.
-       void                                                            bufferData                      (const deUint8* data, size_t size);
        void                                                            upload                          (void);
 
 private:
-       void                                    init                                    (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data);
-                                                       TextureBuffer                   (const TextureBuffer& other); // Not allowed!
-       TextureBuffer&                  operator=                               (const TextureBuffer& other); // Not allowed!
-
-       const RenderContext&    m_context;
-       deUint32                                m_format;               //!< Internal format.
-       std::vector<deUint8>    m_refBuffer;
-       size_t                                  m_offset;
-       size_t                                  m_size;
-
-       tcu::PixelBufferAccess  m_refTexture;
-       deUint32                                m_glTexture;
-       deUint32                                m_glBuffer;
+       void                                                            init                            (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data);
+                                                                               TextureBuffer           (const TextureBuffer& other); // Not allowed!
+       TextureBuffer&                                          operator=                       (const TextureBuffer& other); // Not allowed!
+
+       const RenderContext&                            m_context;
+       deUint32                                                        m_format;               //!< Internal format.
+       de::ArrayBuffer<deUint8>                        m_refBuffer;
+       size_t                                                          m_offset;
+       size_t                                                          m_size;
+
+       deUint32                                                        m_glTexture;
+       deUint32                                                        m_glBuffer;
 } DE_WARN_UNUSED_TYPE;
 
 } // glu
index 5b31d2f..154963e 100644 (file)
@@ -24,6 +24,7 @@
 #include "gluTextureUtil.hpp"
 #include "gluRenderContext.hpp"
 #include "gluContextInfo.hpp"
+#include "gluTexture.hpp"
 #include "tcuTextureUtil.hpp"
 #include "tcuFormatUtil.hpp"
 #include "glwEnums.hpp"
@@ -1170,4 +1171,21 @@ const tcu::IVec2 (&getDefaultGatherOffsets (void))[4]
        return s_defaultOffsets;
 }
 
+tcu::PixelBufferAccess getTextureBufferEffectiveRefTexture (TextureBuffer& buffer, int maxTextureBufferSize)
+{
+       DE_ASSERT(maxTextureBufferSize > 0);
+
+       const tcu::PixelBufferAccess& fullAccess = buffer.getFullRefTexture();
+
+       return tcu::PixelBufferAccess(fullAccess.getFormat(),
+                                                                 tcu::IVec3(de::min(fullAccess.getWidth(), maxTextureBufferSize), 1, 1),
+                                                                 fullAccess.getPitch(),
+                                                                 fullAccess.getDataPtr());
+}
+
+tcu::ConstPixelBufferAccess getTextureBufferEffectiveRefTexture (const TextureBuffer& buffer, int maxTextureBufferSize)
+{
+       return getTextureBufferEffectiveRefTexture(const_cast<TextureBuffer&>(buffer), maxTextureBufferSize);
+}
+
 } // glu
index 3112347..f806ec8 100644 (file)
@@ -34,6 +34,7 @@ namespace glu
 
 class RenderContext;
 class ContextInfo;
+class TextureBuffer;
 
 /*--------------------------------------------------------------------*//*!
  * \brief GL pixel transfer format.
@@ -88,6 +89,9 @@ bool                                                  isCompressedFormat                                      (deUint32 internalFormat);
 
 const tcu::IVec2                               (&getDefaultGatherOffsets                       (void))[4];
 
+tcu::PixelBufferAccess                 getTextureBufferEffectiveRefTexture     (TextureBuffer& buffer, int maxTextureBufferSize);
+tcu::ConstPixelBufferAccess            getTextureBufferEffectiveRefTexture     (const TextureBuffer& buffer, int maxTextureBufferSize);
+
 } // glu
 
 #endif // _GLUTEXTUREUTIL_HPP
index ad35705..c014870 100644 (file)
@@ -240,10 +240,10 @@ TextureCubeArrayFormatCase::IterateResult TextureCubeArrayFormatCase::iterate (v
 
 // TextureBufferFormatCase
 
-class TextureBufferFormatCase : public tcu::TestCase
+class TextureBufferFormatCase : public TestCase
 {
 public:
-                                                               TextureBufferFormatCase         (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 internalFormat, int width);
+                                                               TextureBufferFormatCase         (Context& ctx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 internalFormat, int width);
                                                                ~TextureBufferFormatCase        (void);
 
        void                                            init                                            (void);
@@ -258,18 +258,20 @@ private:
 
        deUint32                                        m_format;
        int                                                     m_width;
+       int                                                     m_maxTextureBufferSize;
 
        glu::TextureBuffer*                     m_texture;
        TextureRenderer                         m_renderer;
 };
 
-TextureBufferFormatCase::TextureBufferFormatCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 internalFormat, int width)
-       : TestCase              (testCtx, name, description)
-       , m_renderCtx   (renderCtx)
-       , m_format              (internalFormat)
-       , m_width               (width)
-       , m_texture             (DE_NULL)
-       , m_renderer    (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
+TextureBufferFormatCase::TextureBufferFormatCase (Context& ctx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 internalFormat, int width)
+       : TestCase                                      (ctx, name, description)
+       , m_renderCtx                           (renderCtx)
+       , m_format                                      (internalFormat)
+       , m_width                                       (width)
+       , m_maxTextureBufferSize        (0)
+       , m_texture                                     (DE_NULL)
+       , m_renderer                            (renderCtx, ctx.getTestContext().getLog(), glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
 {
 }
 
@@ -285,18 +287,19 @@ void TextureBufferFormatCase::init (void)
        tcu::TextureFormatInfo  spec    = tcu::getTextureFormatInfo(fmt);
        tcu::Vec4                               colorA  (spec.valueMin.x(), spec.valueMax.y(), spec.valueMin.z(), spec.valueMax.w());
        tcu::Vec4                               colorB  (spec.valueMax.x(), spec.valueMin.y(), spec.valueMax.z(), spec.valueMin.w());
-       std::ostringstream              fmtName;
 
-       fmtName << glu::getPixelFormatStr(m_format);
+       m_maxTextureBufferSize = m_context.getContextInfo().getInt(GL_MAX_TEXTURE_BUFFER_SIZE);
+       if (m_maxTextureBufferSize <= 0)
+               TCU_THROW(NotSupportedError, "GL_MAX_TEXTURE_BUFFER_SIZE > 0 required");
 
-       log << TestLog::Message << "Buffer texture, " << fmtName.str() << ", " << m_width
+       log << TestLog::Message << "Buffer texture, " << glu::getPixelFormatStr(m_format) << ", " << m_width
                                                        << ",\n  fill with " << formatGradient(&colorA, &colorB) << " gradient"
                << TestLog::EndMessage;
 
        m_texture = new glu::TextureBuffer(m_renderCtx, m_format, m_width * fmt.getPixelSize());
 
        // Fill level 0.
-       tcu::fillWithComponentGradients(m_texture->getRefTexture(), colorA, colorB);
+       tcu::fillWithComponentGradients(m_texture->getFullRefTexture(), colorA, colorB);
 }
 
 void TextureBufferFormatCase::deinit (void)
@@ -309,22 +312,23 @@ void TextureBufferFormatCase::deinit (void)
 
 TextureBufferFormatCase::IterateResult TextureBufferFormatCase::iterate (void)
 {
-       TestLog&                                log                                     = m_testCtx.getLog();
-       const glw::Functions&   gl                                      = m_renderCtx.getFunctions();
-       RandomViewport                  viewport                        (m_renderCtx.getRenderTarget(), m_width, 1, deStringHash(getName()));
-       tcu::Surface                    renderedFrame           (viewport.width, viewport.height);
-       tcu::Surface                    referenceFrame          (viewport.width, viewport.height);
-       tcu::RGBA                               threshold                       = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
-       vector<float>                   texCoord;
-       RenderParams                    renderParams            (TEXTURETYPE_BUFFER);
-       tcu::TextureFormatInfo  spec                            = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
+       TestLog&                                                        log                                             = m_testCtx.getLog();
+       const glw::Functions&                           gl                                              = m_renderCtx.getFunctions();
+       RandomViewport                                          viewport                                (m_renderCtx.getRenderTarget(), m_width, 1, deStringHash(getName()));
+       tcu::Surface                                            renderedFrame                   (viewport.width, viewport.height);
+       tcu::Surface                                            referenceFrame                  (viewport.width, viewport.height);
+       tcu::RGBA                                                       threshold                               = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+       vector<float>                                           texCoord;
+       RenderParams                                            renderParams                    (TEXTURETYPE_BUFFER);
+       const tcu::ConstPixelBufferAccess       effectiveRefTexture             = glu::getTextureBufferEffectiveRefTexture(*m_texture, m_maxTextureBufferSize);
+       tcu::TextureFormatInfo                          spec                                    = tcu::getTextureFormatInfo(effectiveRefTexture.getFormat());
 
        renderParams.flags                      |= RenderParams::LOG_ALL;
-       renderParams.samplerType        = getFetchSamplerType(m_texture->getRefTexture().getFormat());
+       renderParams.samplerType        = getFetchSamplerType(effectiveRefTexture.getFormat());
        renderParams.colorScale         = spec.lookupScale;
        renderParams.colorBias          = spec.lookupBias;
 
-       computeQuadTexCoord1D(texCoord, 0.0f, (float)(m_texture->getRefTexture().getWidth()));
+       computeQuadTexCoord1D(texCoord, 0.0f, (float)(effectiveRefTexture.getWidth()));
 
        gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
        gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
@@ -349,7 +353,7 @@ TextureBufferFormatCase::IterateResult TextureBufferFormatCase::iterate (void)
        GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
 
        // Compute reference.
-       fetchTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], spec.lookupScale, spec.lookupBias);
+       fetchTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), effectiveRefTexture, &texCoord[0], spec.lookupScale, spec.lookupBias);
 
        // Compare and log.
        bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
@@ -553,8 +557,8 @@ void TextureFormatTests::init (void)
                string          nameBase                = bufferColorFormats[formatNdx].name;
                string          descriptionBase = glu::getPixelFormatName(internalFormat);
 
-               sizedBufferGroup->addChild      (new TextureBufferFormatCase    (m_testCtx, m_context.getRenderContext(),       (nameBase + "_pot").c_str(),    (descriptionBase + ", GL_TEXTURE_BUFFER").c_str(),      internalFormat, 64));
-               sizedBufferGroup->addChild      (new TextureBufferFormatCase    (m_testCtx, m_context.getRenderContext(),       (nameBase + "_npot").c_str(),   (descriptionBase + ", GL_TEXTURE_BUFFER").c_str(),      internalFormat, 112));
+               sizedBufferGroup->addChild      (new TextureBufferFormatCase    (m_context, m_context.getRenderContext(),       (nameBase + "_pot").c_str(),    (descriptionBase + ", GL_TEXTURE_BUFFER").c_str(),      internalFormat, 64));
+               sizedBufferGroup->addChild      (new TextureBufferFormatCase    (m_context, m_context.getRenderContext(),       (nameBase + "_npot").c_str(),   (descriptionBase + ", GL_TEXTURE_BUFFER").c_str(),      internalFormat, 112));
        }
 }
 
index 21787a2..5c62626 100644 (file)
@@ -41,6 +41,7 @@
 #include "gluShaderUtil.hpp"
 #include "gluStrUtil.hpp"
 #include "gluTexture.hpp"
+#include "gluTextureUtil.hpp"
 
 #include "glwEnums.hpp"
 #include "glwFunctions.hpp"
@@ -211,7 +212,7 @@ public:
        }
 
 private:
-       const tcu::ConstPixelBufferAccess& m_texture;
+       const tcu::ConstPixelBufferAccess m_texture;
 };
 
 class CoordFragmentShader : public rr::FragmentShader
@@ -294,7 +295,7 @@ public:
        }
 
 private:
-       const tcu::ConstPixelBufferAccess& m_texture;
+       const tcu::ConstPixelBufferAccess m_texture;
 };
 
 string generateVertexShaderTemplate (RenderBits renderBits)
@@ -435,7 +436,12 @@ void modifyBufferData (TestLog&                            log,
 
        log << TestLog::Message << "BufferData, Size: " << data.size() << TestLog::EndMessage;
 
-       texture.bufferData(&(data[0]), data.size());
+       {
+               // replace getRefBuffer with a new buffer
+               de::ArrayBuffer<deUint8> buffer(&(data[0]), data.size());
+               texture.getRefBuffer().swap(buffer);
+       }
+
        texture.upload();
 }
 
@@ -459,7 +465,7 @@ void modifyBufferSubData (TestLog&                          log,
        gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
        GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glBufferSubData()");
 
-       deMemcpy(texture.getRefBuffer() + offset, &(data[0]), int(data.size()));
+       deMemcpy((deUint8*)texture.getRefBuffer().getPtr() + offset, &(data[0]), int(data.size()));
 }
 
 void modifyMapWrite (TestLog&                          log,
@@ -492,7 +498,7 @@ void modifyMapWrite (TestLog&                               log,
        gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
        GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
 
-       deMemcpy(texture.getRefBuffer()+offset, &(data[0]), int(data.size()));
+       deMemcpy((deUint8*)texture.getRefBuffer().getPtr()+offset, &(data[0]), int(data.size()));
 }
 
 void modifyMapReadWrite (TestLog&                              log,
@@ -505,6 +511,7 @@ void modifyMapReadWrite (TestLog&                           log,
        const size_t                            size            = de::max<size_t>(minSize, size_t((texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7 + 0.3 * rng.getFloat())));
        const size_t                            minOffset       = texture.getOffset();
        const size_t                            offset          = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
+       deUint8* const                          refPtr          = (deUint8*)texture.getRefBuffer().getPtr() + offset;
        vector<deUint8>                         data;
 
        genRandomCoords(rng, data, offset, size);
@@ -521,10 +528,10 @@ void modifyMapReadWrite (TestLog&                         log,
 
                for (int i = 0; i < (int)data.size(); i++)
                {
-                       if (ptr[i] != texture.getRefBuffer()[offset+i])
+                       if (ptr[i] != refPtr[i])
                        {
                                if (invalidBytes < 24)
-                                       log << TestLog::Message << "Invalid byte in mapped buffer. " << tcu::Format::Hex<2>(data[i]).toString() << " at " << i << ", expected " << tcu::Format::Hex<2>(texture.getRefBuffer()[i]).toString() << TestLog::EndMessage;
+                                       log << TestLog::Message << "Invalid byte in mapped buffer. " << tcu::Format::Hex<2>(data[i]).toString() << " at " << i << ", expected " << tcu::Format::Hex<2>(refPtr[i]).toString() << TestLog::EndMessage;
 
                                invalidBytes++;
                        }
@@ -545,7 +552,7 @@ void modifyMapReadWrite (TestLog&                           log,
        GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
 
        for (int i = 0; i < (int)data.size(); i++)
-               texture.getRefBuffer()[offset+i] = data[i];
+               refPtr[i] = data[i];
 }
 
 void modify (TestLog&                                          log,
@@ -656,31 +663,34 @@ void renderGL (glu::RenderContext&                renderContext,
 void renderReference (RenderBits                                       renderBits,
                                          deUint32                                              coordSeed,
                                          int                                                   triangleCount,
-                                         glu::TextureBuffer&                   texture,
+                                         const glu::TextureBuffer&             texture,
+                                         int                                                   maxTextureBufferSize,
                                          const tcu::PixelBufferAccess& target)
 {
-       const CoordVertexShader                 coordVertexShader;
-       const TextureVertexShader               textureVertexShader             (texture.getRefTexture());
-       const rr::VertexShader* const   vertexShader                    = (renderBits & RENDERBITS_AS_VERTEX_TEXTURE ? static_cast<const rr::VertexShader*>(&textureVertexShader) : &coordVertexShader);
+       const tcu::ConstPixelBufferAccess       effectiveAccess                 = glu::getTextureBufferEffectiveRefTexture(texture, maxTextureBufferSize);
+
+       const CoordVertexShader                         coordVertexShader;
+       const TextureVertexShader                       textureVertexShader             (effectiveAccess);
+       const rr::VertexShader* const           vertexShader                    = (renderBits & RENDERBITS_AS_VERTEX_TEXTURE ? static_cast<const rr::VertexShader*>(&textureVertexShader) : &coordVertexShader);
 
-       const CoordFragmentShader               coordFragmmentShader;
-       const TextureFragmentShader             textureFragmentShader   (texture.getRefTexture());
-       const rr::FragmentShader* const fragmentShader                  = (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE ? static_cast<const rr::FragmentShader*>(&textureFragmentShader) : &coordFragmmentShader);
+       const CoordFragmentShader                       coordFragmmentShader;
+       const TextureFragmentShader                     textureFragmentShader   (effectiveAccess);
+       const rr::FragmentShader* const         fragmentShader                  = (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE ? static_cast<const rr::FragmentShader*>(&textureFragmentShader) : &coordFragmmentShader);
 
-       const rr::Renderer                              renderer;
-       const rr::RenderState                   renderState(rr::ViewportState(rr::WindowRectangle(0, 0, target.getWidth(), target.getHeight())));
-       const rr::RenderTarget                  renderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(target));
+       const rr::Renderer                                      renderer;
+       const rr::RenderState                           renderState(rr::ViewportState(rr::WindowRectangle(0, 0, target.getWidth(), target.getHeight())));
+       const rr::RenderTarget                          renderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(target));
 
-       const rr::Program                               program(vertexShader, fragmentShader);
+       const rr::Program                                       program(vertexShader, fragmentShader);
 
-       rr::VertexAttrib                                vertexAttribs[1];
-       vector<deUint8>                                 coords;
+       rr::VertexAttrib                                        vertexAttribs[1];
+       vector<deUint8>                                         coords;
 
        if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
        {
                vertexAttribs[0].type                   = rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
                vertexAttribs[0].size                   = 2;
-               vertexAttribs[0].pointer                = texture.getRefBuffer();
+               vertexAttribs[0].pointer                = texture.getRefBuffer().getPtr();
        }
        else
        {
@@ -695,7 +705,7 @@ void renderReference (RenderBits                                    renderBits,
 
        if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
        {
-               const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, rr::DrawIndices((const void*)texture.getRefBuffer(), rr::INDEXTYPE_UINT8));
+               const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, rr::DrawIndices(texture.getRefBuffer().getPtr(), rr::INDEXTYPE_UINT8));
                const rr::DrawCommand   cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
 
                renderer.draw(cmd);
@@ -759,14 +769,19 @@ void render (TestLog&                                             log,
                         glu::TextureBuffer&                    texture,
                         const tcu::PixelBufferAccess&  target)
 {
-       const tcu::ScopedLogSection     renderSection   (log, "Render Texture buffer", "Render Texture Buffer");
-       const int                                       triangleCount   = 8;
-       const deUint32                          coordSeed               = rng.getUint32();
+       const tcu::ScopedLogSection     renderSection                   (log, "Render Texture buffer", "Render Texture Buffer");
+       const int                                       triangleCount                   = 8;
+       const deUint32                          coordSeed                               = rng.getUint32();
+       int                                                     maxTextureBufferSize    = 0;
+
+       renderContext.getFunctions().getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize);
+       GLU_EXPECT_NO_ERROR(renderContext.getFunctions().getError(), "query GL_MAX_TEXTURE_BUFFER_SIZE");
+       DE_ASSERT(maxTextureBufferSize > 0); // checked in init()
 
        logRendering(log, renderBits);
 
        renderGL(renderContext, renderBits, coordSeed, triangleCount, program, texture);
-       renderReference(renderBits, coordSeed, triangleCount, texture, target);
+       renderReference(renderBits, coordSeed, triangleCount, texture, maxTextureBufferSize, target);
 }
 
 void verifyScreen (TestLog&                                                            log,
@@ -958,6 +973,12 @@ void TextureBufferCase::init (void)
                && !(glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer")))
                throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
 
+       {
+               const int maxTextureBufferSize = info->getInt(GL_MAX_TEXTURE_BUFFER_SIZE);
+               if (maxTextureBufferSize <= 0)
+                       TCU_THROW(NotSupportedError, "GL_MAX_TEXTURE_BUFFER_SIZE > 0 required");
+       }
+
        if (m_preRender != 0)
        {
                TestLog&                                        log                     = m_testCtx.getLog();