/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 3.0 Module * ------------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Buffer copying tests. *//*--------------------------------------------------------------------*/ #include "es3fBufferCopyTests.hpp" #include "glsBufferTestUtil.hpp" #include "tcuTestLog.hpp" #include "deMemory.h" #include "deString.h" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include <algorithm> using std::vector; using std::string; using tcu::TestLog; namespace deqp { namespace gles3 { namespace Functional { using namespace gls::BufferTestUtil; class BasicBufferCopyCase : public BufferCase { public: BasicBufferCopyCase (Context& context, const char* name, const char* desc, deUint32 srcTarget, int srcSize, deUint32 srcHint, deUint32 dstTarget, int dstSize, deUint32 dstHint, int copySrcOffset, int copyDstOffset, int copySize, VerifyType verifyType) : BufferCase (context.getTestContext(), context.getRenderContext(), name, desc) , m_srcTarget (srcTarget) , m_srcSize (srcSize) , m_srcHint (srcHint) , m_dstTarget (dstTarget) , m_dstSize (dstSize) , m_dstHint (dstHint) , m_copySrcOffset (copySrcOffset) , m_copyDstOffset (copyDstOffset) , m_copySize (copySize) , m_verifyType (verifyType) { DE_ASSERT(de::inBounds(m_copySrcOffset, 0, m_srcSize) && de::inRange(m_copySrcOffset+m_copySize, m_copySrcOffset, m_srcSize)); DE_ASSERT(de::inBounds(m_copyDstOffset, 0, m_dstSize) && de::inRange(m_copyDstOffset+m_copySize, m_copyDstOffset, m_dstSize)); } IterateResult iterate (void) { BufferVerifier verifier (m_renderCtx, m_testCtx.getLog(), m_verifyType); ReferenceBuffer srcRef; ReferenceBuffer dstRef; deUint32 srcBuf = 0; deUint32 dstBuf = 0; deUint32 srcSeed = deStringHash(getName()) ^ 0xabcd; deUint32 dstSeed = deStringHash(getName()) ^ 0xef01; bool isOk = true; srcRef.setSize(m_srcSize); fillWithRandomBytes(srcRef.getPtr(), m_srcSize, srcSeed); dstRef.setSize(m_dstSize); fillWithRandomBytes(dstRef.getPtr(), m_dstSize, dstSeed); // Create source buffer and fill with data. srcBuf = genBuffer(); glBindBuffer(m_srcTarget, srcBuf); glBufferData(m_srcTarget, m_srcSize, srcRef.getPtr(), m_srcHint); GLU_CHECK_MSG("glBufferData"); // Create destination buffer and fill with data. dstBuf = genBuffer(); glBindBuffer(m_dstTarget, dstBuf); glBufferData(m_dstTarget, m_dstSize, dstRef.getPtr(), m_dstHint); GLU_CHECK_MSG("glBufferData"); // Verify both buffers before executing copy. isOk = verifier.verify(srcBuf, srcRef.getPtr(), 0, m_srcSize, m_srcTarget) && isOk; isOk = verifier.verify(dstBuf, dstRef.getPtr(), 0, m_dstSize, m_dstTarget) && isOk; // Execute copy. deMemcpy(dstRef.getPtr()+m_copyDstOffset, srcRef.getPtr()+m_copySrcOffset, m_copySize); glBindBuffer(m_srcTarget, srcBuf); glBindBuffer(m_dstTarget, dstBuf); glCopyBufferSubData(m_srcTarget, m_dstTarget, m_copySrcOffset, m_copyDstOffset, m_copySize); GLU_CHECK_MSG("glCopyBufferSubData"); // Verify both buffers after copy. isOk = verifier.verify(srcBuf, srcRef.getPtr(), 0, m_srcSize, m_srcTarget) && isOk; isOk = verifier.verify(dstBuf, dstRef.getPtr(), 0, m_dstSize, m_dstTarget) && isOk; m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Buffer verification failed"); return STOP; } private: deUint32 m_srcTarget; int m_srcSize; deUint32 m_srcHint; deUint32 m_dstTarget; int m_dstSize; deUint32 m_dstHint; int m_copySrcOffset; int m_copyDstOffset; int m_copySize; VerifyType m_verifyType; }; // Case B: same buffer, take range as parameter class SingleBufferCopyCase : public BufferCase { public: SingleBufferCopyCase (Context& context, const char* name, const char* desc, deUint32 srcTarget, deUint32 dstTarget, deUint32 hint, VerifyType verifyType) : BufferCase (context.getTestContext(), context.getRenderContext(), name, desc) , m_srcTarget (srcTarget) , m_dstTarget (dstTarget) , m_hint (hint) , m_verifyType (verifyType) { } IterateResult iterate (void) { const int size = 1000; BufferVerifier verifier (m_renderCtx, m_testCtx.getLog(), m_verifyType); ReferenceBuffer ref; deUint32 buf = 0; deUint32 baseSeed = deStringHash(getName()); bool isOk = true; ref.setSize(size); // Create buffer. buf = genBuffer(); glBindBuffer(m_srcTarget, buf); static const struct { int srcOffset; int dstOffset; int copySize; } copyRanges[] = { { 57, 701, 101 }, // Non-adjecent, from low to high. { 640, 101, 101 }, // Non-adjecent, from high to low. { 0, 500, 500 }, // Lower half to upper half. { 500, 0, 500 } // Upper half to lower half. }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(copyRanges) && isOk; ndx++) { int srcOffset = copyRanges[ndx].srcOffset; int dstOffset = copyRanges[ndx].dstOffset; int copySize = copyRanges[ndx].copySize; fillWithRandomBytes(ref.getPtr(), size, baseSeed ^ deInt32Hash(ndx)); // Fill with data. glBindBuffer(m_srcTarget, buf); glBufferData(m_srcTarget, size, ref.getPtr(), m_hint); GLU_CHECK_MSG("glBufferData"); // Execute copy. deMemcpy(ref.getPtr()+dstOffset, ref.getPtr()+srcOffset, copySize); glBindBuffer(m_dstTarget, buf); glCopyBufferSubData(m_srcTarget, m_dstTarget, srcOffset, dstOffset, copySize); GLU_CHECK_MSG("glCopyBufferSubData"); // Verify buffer after copy. isOk = verifier.verify(buf, ref.getPtr(), 0, size, m_dstTarget) && isOk; } m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Buffer verification failed"); return STOP; } private: deUint32 m_srcTarget; deUint32 m_dstTarget; deUint32 m_hint; VerifyType m_verifyType; }; BufferCopyTests::BufferCopyTests (Context& context) : TestCaseGroup(context, "copy", "Buffer copy tests") { } BufferCopyTests::~BufferCopyTests (void) { } void BufferCopyTests::init (void) { static const deUint32 bufferTargets[] = { GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER }; // .basic { tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic buffer copy cases"); addChild(basicGroup); for (int srcTargetNdx = 0; srcTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); srcTargetNdx++) { for (int dstTargetNdx = 0; dstTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); dstTargetNdx++) { if (srcTargetNdx == dstTargetNdx) continue; deUint32 srcTarget = bufferTargets[srcTargetNdx]; deUint32 dstTarget = bufferTargets[dstTargetNdx]; const int size = 1017; const deUint32 hint = GL_STATIC_DRAW; VerifyType verify = VERIFY_AS_VERTEX_ARRAY; string name = string(getBufferTargetName(srcTarget)) + "_" + getBufferTargetName(dstTarget); basicGroup->addChild(new BasicBufferCopyCase(m_context, name.c_str(), "", srcTarget, size, hint, dstTarget, size, hint, 0, 0, size, verify)); } } } // .subrange { tcu::TestCaseGroup* subrangeGroup = new tcu::TestCaseGroup(m_testCtx, "subrange", "Buffer subrange copy tests"); addChild(subrangeGroup); static const struct { const char* name; int srcSize; int dstSize; int srcOffset; int dstOffset; int copySize; } cases[] = { // srcSize dstSize srcOffs dstOffs copySize { "middle", 1000, 1000, 250, 250, 500 }, { "small_to_large", 100, 1000, 0, 409, 100 }, { "large_to_small", 1000, 100, 409, 0, 100 }, { "low_to_high_1", 1000, 1000, 0, 500, 500 }, { "low_to_high_2", 997, 1027, 0, 701, 111 }, { "high_to_low_1", 1000, 1000, 500, 0, 500 }, { "high_to_low_2", 1027, 997, 701, 17, 111 } }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++) { deUint32 srcTarget = GL_COPY_READ_BUFFER; deUint32 dstTarget = GL_COPY_WRITE_BUFFER; deUint32 hint = GL_STATIC_DRAW; VerifyType verify = VERIFY_AS_VERTEX_ARRAY; subrangeGroup->addChild(new BasicBufferCopyCase(m_context, cases[ndx].name, "", srcTarget, cases[ndx].srcSize, hint, dstTarget, cases[ndx].dstSize, hint, cases[ndx].srcOffset, cases[ndx].dstOffset, cases[ndx].copySize, verify)); } } // .single_buffer { tcu::TestCaseGroup* singleBufGroup = new tcu::TestCaseGroup(m_testCtx, "single_buffer", "Copies within single buffer"); addChild(singleBufGroup); for (int srcTargetNdx = 0; srcTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); srcTargetNdx++) { for (int dstTargetNdx = 0; dstTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); dstTargetNdx++) { if (srcTargetNdx == dstTargetNdx) continue; deUint32 srcTarget = bufferTargets[srcTargetNdx]; deUint32 dstTarget = bufferTargets[dstTargetNdx]; const deUint32 hint = GL_STATIC_DRAW; VerifyType verify = VERIFY_AS_VERTEX_ARRAY; string name = string(getBufferTargetName(srcTarget)) + "_" + getBufferTargetName(dstTarget); singleBufGroup->addChild(new SingleBufferCopyCase(m_context, name.c_str(), "", srcTarget, dstTarget, hint, verify)); } } } } } // Functional } // gles3 } // deqp