| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2014-2016 The Khronos Group Inc. |
| * |
| * 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 |
| */ /*-------------------------------------------------------------------*/ |
| |
| #include "es31cDrawIndirectTests.hpp" |
| #include "gluContextInfo.hpp" |
| #include "glwEnums.hpp" |
| #include "tcuMatrix.hpp" |
| #include "tcuRenderTarget.hpp" |
| #include "tcuVectorUtil.hpp" |
| |
| #include <map> |
| |
| namespace glcts |
| { |
| using namespace glw; |
| namespace |
| { |
| |
| class DILogger |
| { |
| public: |
| DILogger() : null_log_(0) |
| { |
| } |
| |
| DILogger(const DILogger& rhs) |
| { |
| null_log_ = rhs.null_log_; |
| if (!null_log_) |
| { |
| str_ << rhs.str_.str(); |
| } |
| } |
| |
| ~DILogger() |
| { |
| s_tcuLog->writeMessage(str_.str().c_str()); |
| if (!str_.str().empty()) |
| { |
| s_tcuLog->writeMessage(NL); |
| } |
| } |
| |
| template <class T> |
| DILogger& operator<<(const T& t) |
| { |
| if (!null_log_) |
| { |
| str_ << t; |
| } |
| return *this; |
| } |
| |
| DILogger& nullify() |
| { |
| null_log_ = true; |
| return *this; |
| } |
| |
| static void setOutput(tcu::TestLog& log) |
| { |
| s_tcuLog = &log; |
| } |
| |
| private: |
| void operator=(const DILogger&); |
| bool null_log_; |
| std::ostringstream str_; |
| static tcu::TestLog* s_tcuLog; |
| }; |
| tcu::TestLog* DILogger::s_tcuLog = NULL; |
| |
| class DIResult |
| { |
| public: |
| DIResult() : status_(NO_ERROR) |
| { |
| } |
| |
| DILogger error() |
| { |
| return sub_result(ERROR); |
| } |
| long code() const |
| { |
| return status_; |
| } |
| DILogger sub_result(long _code) |
| { |
| if (_code == NO_ERROR) |
| { |
| return sub_result_inner(_code).nullify(); |
| } |
| else |
| { |
| return sub_result_inner(_code); |
| } |
| } |
| |
| private: |
| DILogger sub_result_inner(long _code) |
| { |
| status_ |= _code; |
| return DILogger(); |
| } |
| DILogger logger_; |
| long status_; |
| }; |
| |
| namespace test_api |
| { |
| struct ES3 |
| { |
| static bool isES() |
| { |
| return true; |
| } |
| static std::string glslVer(bool = false) |
| { |
| return "#version 310 es"; |
| } |
| static void ES_Only() |
| { |
| } |
| }; |
| |
| struct GL |
| { |
| static bool isES() |
| { |
| return false; |
| } |
| static std::string glslVer(bool compute = false) |
| { |
| if (compute) |
| { |
| return "#version 430"; |
| } |
| else |
| { |
| return "#version 400"; |
| } |
| } |
| static void GL_Only() |
| { |
| } |
| }; |
| } |
| |
| namespace shaders |
| { |
| |
| template <typename api> |
| std::string vshSimple() |
| { |
| return api::glslVer() + NL "in vec4 i_vertex;" NL "void main()" NL "{" NL " gl_Position = i_vertex;" NL "}"; |
| } |
| template <typename api> |
| std::string vshSimple_point() |
| { |
| return api::glslVer() + NL "in vec4 i_vertex;" NL "void main()" NL "{" NL " gl_Position = i_vertex;" NL |
| "#if defined(GL_ES)" NL " gl_PointSize = 1.0;" NL "#endif" NL "}"; |
| } |
| |
| template <typename api> |
| std::string fshSimple() |
| { |
| return api::glslVer() + NL "precision highp float; " NL "out vec4 outColor;" NL "void main() {" NL |
| " outColor = vec4(0.1,0.2,0.3,1.0);" NL "}"; |
| } |
| } |
| |
| class DrawIndirectBase : public glcts::SubcaseBase |
| { |
| protected: |
| typedef std::vector<unsigned int> CDataArray; |
| typedef std::vector<tcu::Vec3> CVertexArray; |
| typedef std::vector<tcu::Vec4> CColorArray; |
| typedef std::vector<GLuint> CElementArray; |
| |
| enum TDrawFunction |
| { |
| DRAW_ARRAYS, |
| DRAW_ELEMENTS, |
| }; |
| |
| typedef struct |
| { |
| GLuint count; |
| GLuint primCount; |
| GLuint first; |
| GLuint reservedMustBeZero; |
| } DrawArraysIndirectCommand; |
| |
| typedef struct |
| { |
| GLuint count; |
| GLuint primCount; |
| GLuint firstIndex; |
| GLint baseVertex; |
| GLuint reservedMustBeZero; |
| } DrawElementsIndirectCommand; |
| |
| int getWindowWidth() |
| { |
| return m_context.getRenderContext().getRenderTarget().getWidth(); |
| } |
| |
| int getWindowHeight() |
| { |
| return m_context.getRenderContext().getRenderTarget().getHeight(); |
| } |
| |
| void getDataSize(int& width, int& height) |
| { |
| width = std::min(getWindowWidth(), 16384); // Cap width to 16384 |
| height = std::min(getWindowHeight(), 4 * 16384 / width); // Height is 4 if width is capped |
| } |
| |
| GLuint CreateComputeProgram(const std::string& cs, bool linkAndCheck) |
| { |
| const GLuint p = glCreateProgram(); |
| |
| const GLuint sh = glCreateShader(GL_COMPUTE_SHADER); |
| glAttachShader(p, sh); |
| glDeleteShader(sh); |
| const char* const src[1] = { cs.c_str() }; |
| glShaderSource(sh, 1, src, NULL); |
| glCompileShader(sh); |
| |
| if (linkAndCheck) |
| { |
| glLinkProgram(p); |
| if (!CheckProgram(p)) |
| { |
| return 0; |
| } |
| } |
| |
| return p; |
| } |
| |
| GLuint CreateProgram(const std::string& vs, const std::string& gs, const std::string& fs, bool linkAndCheck) |
| { |
| const GLuint p = glCreateProgram(); |
| |
| if (!vs.empty()) |
| { |
| const GLuint sh = glCreateShader(GL_VERTEX_SHADER); |
| glAttachShader(p, sh); |
| glDeleteShader(sh); |
| const char* const src[1] = { vs.c_str() }; |
| glShaderSource(sh, 1, src, NULL); |
| glCompileShader(sh); |
| } |
| if (!gs.empty()) |
| { |
| const GLuint sh = glCreateShader(GL_GEOMETRY_SHADER); |
| glAttachShader(p, sh); |
| glDeleteShader(sh); |
| const char* const src[1] = { gs.c_str() }; |
| glShaderSource(sh, 1, src, NULL); |
| glCompileShader(sh); |
| } |
| if (!fs.empty()) |
| { |
| const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); |
| glAttachShader(p, sh); |
| glDeleteShader(sh); |
| const char* const src[1] = { fs.c_str() }; |
| glShaderSource(sh, 1, src, NULL); |
| glCompileShader(sh); |
| } |
| |
| if (linkAndCheck) |
| { |
| glLinkProgram(p); |
| if (!CheckProgram(p)) |
| { |
| return 0; |
| } |
| } |
| |
| return p; |
| } |
| |
| long CheckProgram(GLuint program) |
| { |
| DIResult status; |
| GLint progStatus; |
| glGetProgramiv(program, GL_LINK_STATUS, &progStatus); |
| |
| if (progStatus == GL_FALSE) |
| { |
| |
| status.error() << "GL_LINK_STATUS is false"; |
| |
| GLint attached_shaders; |
| glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders); |
| |
| if (attached_shaders > 0) |
| { |
| std::vector<GLuint> shaders(attached_shaders); |
| glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]); |
| |
| for (GLint i = 0; i < attached_shaders; ++i) |
| { |
| // shader type |
| GLenum type; |
| glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type)); |
| switch (type) |
| { |
| case GL_VERTEX_SHADER: |
| status.error() << "*** Vertex Shader ***\n"; |
| break; |
| case GL_FRAGMENT_SHADER: |
| status.error() << "*** Fragment Shader ***\n"; |
| break; |
| case GL_COMPUTE_SHADER: |
| status.error() << "*** Compute Shader ***\n"; |
| break; |
| default: |
| status.error() << "*** Unknown Shader ***\n"; |
| break; |
| } |
| |
| // shader source |
| GLint length; |
| glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length); |
| if (length > 0) |
| { |
| std::vector<GLchar> source(length); |
| glGetShaderSource(shaders[i], length, NULL, &source[0]); |
| status.error() << source[0]; |
| } |
| |
| // shader info log |
| glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length); |
| if (length > 0) |
| { |
| std::vector<GLchar> log(length); |
| glGetShaderInfoLog(shaders[i], length, NULL, &log[0]); |
| status.error() << &log[0]; |
| } |
| } |
| } |
| |
| // program info log |
| GLint length; |
| glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); |
| if (length > 0) |
| { |
| std::vector<GLchar> log(length); |
| glGetProgramInfoLog(program, length, NULL, &log[0]); |
| status.error() << &log[0]; |
| } |
| } |
| |
| return status.code() == NO_ERROR; |
| } |
| |
| template <typename api> |
| void ReadPixelsFloat(int x, int y, int width, int height, void* data); |
| |
| template <typename api> |
| void GetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data); |
| |
| template <typename T> |
| void DataGen(std::vector<T>& data, unsigned int sizeX, unsigned int sizeY, T valueMin, T valueMax) |
| { |
| data.resize(sizeX * sizeY, 0); |
| T range = valueMax - valueMin; |
| T stepX = range / sizeX; |
| T stepY = range / sizeY; |
| |
| for (unsigned int i = 0; i < sizeY; ++i) |
| { |
| T valueY = i * stepY; |
| |
| for (unsigned int j = 0; j < sizeX; ++j) |
| { |
| data[j + i * sizeX] = valueMin + j * stepX + valueY; |
| } |
| } |
| } |
| |
| template <typename T> |
| long DataCompare(const std::vector<T>& dataRef, unsigned int widthRef, unsigned int heightRef, |
| const std::vector<T>& dataTest, unsigned int widthTest, unsigned int heightTest, |
| unsigned offsetYRef = 0, unsigned offsetYTest = 0) |
| { |
| if (widthRef * heightRef > dataRef.size()) |
| throw std::runtime_error("Invalid reference buffer resolution!"); |
| |
| if (widthTest * heightTest > dataTest.size()) |
| throw std::runtime_error("Invalid test buffer resolution!"); |
| |
| unsigned int width = std::min(widthRef, widthTest); |
| unsigned int height = std::min(heightRef, heightTest); |
| |
| for (unsigned int i = 0; i < height; ++i) |
| { |
| unsigned int offsetRef = (i + offsetYRef) * widthRef; |
| unsigned int offsetTest = (i + offsetYTest) * widthTest; |
| |
| for (size_t j = 0; j < width; ++j) |
| { |
| if (dataRef[offsetRef + j] != dataTest[offsetTest + j]) |
| { |
| DIResult status; |
| status.error() << "Compare failed: different values [x: " << j << ", y: " << i + offsetYTest |
| << ", reference: " << dataRef[offsetRef + j] |
| << ", test: " << dataTest[offsetTest + j] << "]"; |
| return status.code(); |
| } |
| } |
| } |
| |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long BindingPointCheck(GLuint expectedValue) |
| { |
| DIResult status; |
| |
| GLint valueInt = -9999; |
| glGetIntegerv(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueInt); |
| if (valueInt != static_cast<GLint>(expectedValue)) |
| { |
| status.error() << "glGetIntegerv(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: " << valueInt |
| << ", expected: " << expectedValue; |
| } |
| |
| GLboolean valueBool = expectedValue ? GL_FALSE : GL_TRUE; |
| glGetBooleanv(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueBool); |
| if (valueBool != (expectedValue ? GL_TRUE : GL_FALSE)) |
| { |
| status.error() << "glGetBooleanv(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: " |
| << BoolToString(valueBool) |
| << ", expected: " << BoolToString(expectedValue ? GL_TRUE : GL_FALSE); |
| } |
| |
| GLfloat valueFloat = -9999; |
| GLfloat expectedFloatValue = static_cast<GLfloat>(expectedValue); |
| glGetFloatv(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueFloat); |
| if (valueFloat != expectedFloatValue) |
| { |
| status.error() << "glGetFloatv(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: " << valueFloat |
| << ", expected: " << expectedValue; |
| } |
| |
| if (!api::isES()) |
| { |
| GLdouble valueDouble = -9999; |
| glGetDoublev(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueDouble); |
| if (valueDouble != static_cast<GLdouble>(expectedValue)) |
| { |
| status.error() << "glGetDoublev(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: " |
| << valueDouble << ", expected: " << expectedValue; |
| } |
| } |
| |
| return status.code(); |
| } |
| |
| template <typename T> |
| long BuffersCompare(const std::vector<T>& bufferTest, unsigned int widthTest, unsigned int heightTest, |
| const std::vector<T>& bufferRef, unsigned int widthRef, unsigned int heightRef) |
| { |
| |
| const tcu::PixelFormat& pixelFormat = m_context.getRenderContext().getRenderTarget().getPixelFormat(); |
| tcu::Vec4 epsilon = tcu::Vec4( |
| 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits), |
| 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits)); |
| |
| double stepX = widthRef / static_cast<double>(widthTest); |
| double stepY = heightRef / static_cast<double>(heightTest); |
| for (unsigned int i = 0; i < heightTest; ++i) |
| { |
| unsigned int offsetTest = i * widthTest; |
| unsigned int offsetRef = static_cast<int>(i * stepY + 0.5) * widthRef; |
| for (unsigned int j = 0; j < widthTest; ++j) |
| { |
| unsigned int posXRef = static_cast<int>(j * stepX + 0.5); |
| if (!ColorVerify(bufferTest[j + offsetTest], bufferRef[posXRef + offsetRef], epsilon)) |
| { |
| DIResult status; |
| status.error() << "(x,y)= (" << j << "," << i << "). Color RGBA(" << bufferTest[j + offsetTest][0] |
| << "," << bufferTest[j + offsetTest][1] << "," << bufferTest[j + offsetTest][2] |
| << "," << bufferTest[j + offsetTest][3] << ") is different than expected RGBA(" |
| << bufferRef[posXRef + offsetRef][0] << "," << bufferRef[posXRef + offsetRef][1] |
| << "," << bufferRef[posXRef + offsetRef][2] << "," |
| << bufferRef[posXRef + offsetRef][3] << ")"; |
| return status.code(); |
| } |
| } |
| } |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool ColorVerify(T color, T colorExpected, tcu::Vec4 epsilon) |
| { |
| for (int i = 0; i < 3; ++i) |
| { |
| if (fabsf(colorExpected[i] - color[i]) > epsilon[i]) |
| return false; |
| } |
| return true; |
| } |
| |
| long BufferCheck(const CDataArray& dataRef, unsigned int widthRef, unsigned int heightRef, const void* bufTest, |
| unsigned int widthTest, unsigned int heightTest, unsigned int offsetYRef = 0, |
| unsigned int offsetYTest = 0) |
| { |
| if (bufTest == 0) |
| { |
| throw std::runtime_error("Invalid test buffer!"); |
| } |
| |
| CDataArray dataTest(widthTest * heightTest, 0); |
| memcpy(&dataTest[0], bufTest, widthTest * heightTest * sizeof(unsigned int)); |
| |
| return DataCompare(dataRef, widthRef, heightRef, dataTest, widthTest, heightTest, offsetYRef, offsetYTest); |
| } |
| |
| template <typename api> |
| long StateValidate(GLboolean mapped, GLbitfield access, GLbitfield accessFlag, GLintptr offset, GLsizeiptr length) |
| { |
| DIResult result; |
| |
| if (!api::isES()) |
| { |
| int v; |
| glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_ACCESS, &v); |
| if (v != static_cast<int>(access)) |
| { |
| result.error() << "glGetBufferParameteriv(GL_BUFFER_ACCESS) returned incorrect state: " |
| << AccessToString(v) << ", expected: " << AccessToString(access); |
| } |
| } |
| |
| int v; |
| glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_ACCESS_FLAGS, &v); |
| if (v != static_cast<int>(accessFlag)) |
| { |
| result.error() << "glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS) returned incorrect state: " << v |
| << ", expected: " << accessFlag; |
| } |
| |
| glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAPPED, &v); |
| if (v != mapped) |
| { |
| result.error() << "glGetBufferParameteriv(GL_BUFFER_MAPPED) returned incorrect state: " |
| << BoolToString((GLboolean)v) << ", expected: " << BoolToString((GLboolean)access); |
| } |
| |
| glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_OFFSET, &v); |
| if (v != offset) |
| { |
| result.error() << "glGetBufferParameteriv(GL_BUFFER_MAP_OFFSET) returned incorrect offset: " << v |
| << ", expected: " << offset; |
| } |
| |
| glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_LENGTH, &v); |
| if (v != length) |
| { |
| result.error() << "glGetBufferParameteriv(GL_BUFFER_MAP_LENGTH) returned incorrect length: " << v |
| << ", expected: " << length; |
| } |
| |
| return result.code(); |
| } |
| |
| void PointsGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output) |
| { |
| output.reserve(drawSizeY * 2); |
| float rasterSizeX = 2.0f / static_cast<float>(getWindowWidth()); |
| float rasterSizeY = 2.0f / static_cast<float>(getWindowHeight()); |
| for (unsigned int i = 0; i < drawSizeY; ++i) |
| { |
| float offsetY = -1.0f + rasterSizeY * static_cast<float>(i) + rasterSizeY / 2; |
| for (unsigned int j = 0; j < drawSizeX; ++j) |
| { |
| float offsetX = -1.0f + rasterSizeX * static_cast<float>(j) + rasterSizeX / 2; |
| output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f)); |
| } |
| } |
| } |
| |
| float LinesOffsetY(unsigned int i, float rasterSize) |
| { |
| // Offset lines slightly from the center of pixels so as not to hit rasterizer |
| // tie-break conditions (the right-edge of the screen at half-integer pixel |
| // heights is the right corner of a diamond). rasterSize/16 is the smallest |
| // offset that the spec guarantees the rasterizer can resolve. |
| return -1.0f + rasterSize * static_cast<float>(i) + rasterSize / 2 + rasterSize / 16; |
| } |
| |
| void LinesGen(unsigned int, unsigned int drawSizeY, CColorArray& output) |
| { |
| output.reserve(drawSizeY * 2); |
| float rasterSize = 2.0f / static_cast<float>(getWindowHeight()); |
| for (unsigned int i = 0; i < drawSizeY; ++i) |
| { |
| float offsetY = LinesOffsetY(i, rasterSize); |
| output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f)); |
| } |
| } |
| |
| void LinesAdjacencyGen(unsigned int, unsigned int drawSizeY, CColorArray& output) |
| { |
| float rasterSize = 2.0f / static_cast<float>(getWindowHeight()); |
| for (unsigned int i = 0; i < drawSizeY; ++i) |
| { |
| float offsetY = LinesOffsetY(i, rasterSize); |
| output.push_back(tcu::Vec4(-1.5f, -1.0f + offsetY, 0.0f, 1.0f)); //adj |
| output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(1.5f, -1.0f + offsetY, 0.0f, 1.0f)); //adj |
| } |
| } |
| |
| void LineStripAdjacencyGen(unsigned int, unsigned int drawSizeY, CColorArray& output) |
| { |
| float rasterSize = 2.0f / static_cast<float>(getWindowHeight()); |
| output.push_back(tcu::Vec4(-1.5f, rasterSize / 2, 0.0f, 1.0f)); |
| for (unsigned int i = 0; i < drawSizeY; ++i) |
| { |
| float offsetY = LinesOffsetY(i, rasterSize); |
| output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f)); |
| } |
| output.push_back(tcu::Vec4(1.5f, 1.0f - rasterSize / 2, 0.0f, 1.0f)); |
| } |
| |
| void TrianglesGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output) |
| { |
| output.reserve(drawSizeX * 2 * 6); |
| |
| switch (drawSizeX) |
| { |
| case 1: |
| { |
| output.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(4.0f, -1.0f, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)); |
| } |
| break; |
| case 0: |
| { |
| throw std::runtime_error("Invalid drawSizeX!"); |
| } |
| break; |
| default: |
| { |
| float drawStepX = 2.0f / static_cast<float>(drawSizeX); |
| float drawStepY = 2.0f / static_cast<float>(drawSizeY); |
| |
| for (unsigned int i = 0; i < drawSizeY; ++i) |
| { |
| float offsetY = -1.0f + drawStepY * static_cast<float>(i); |
| for (unsigned int j = 0; j < drawSizeX; ++j) |
| { |
| float offsetX = -1.0f + drawStepX * static_cast<float>(j); |
| |
| output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + drawStepX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY + drawStepY, 0.0f, 1.0f)); |
| |
| output.push_back(tcu::Vec4(offsetX + drawStepX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + drawStepX, offsetY + drawStepY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY + drawStepY, 0.0f, 1.0f)); |
| } |
| } |
| } |
| break; |
| } |
| } |
| |
| void TrianglesAdjacencyGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output) |
| { |
| // Add a small amount (quarter pixel) of jitter to add to the rectangle sides to avoid |
| // triangle edges landing precisely on fragment centers. |
| float jigX = 0.5f / getWindowWidth(); |
| float jigY = 0.5f / getWindowHeight(); |
| |
| float sizeX = 1.0f / static_cast<float>(drawSizeX); |
| float sizeY = 1.0f / static_cast<float>(drawSizeY); |
| |
| for (unsigned int i = 0; i < drawSizeX; ++i) |
| { |
| float offsetY = -0.5f + jigY + sizeY * static_cast<float>(i); |
| for (unsigned int j = 0; j < drawSizeY; ++j) |
| { |
| float offsetX = -0.5f + jigX + sizeX * static_cast<float>(j); |
| |
| output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX - sizeX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY - sizeY, 0.0f, 1.0f)); |
| |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + 2 * sizeX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY + 2 * sizeY, 0.0f, 1.0f)); |
| } |
| } |
| } |
| |
| void TriangleStripAdjacencyGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output) |
| { |
| // Add a small amount (quarter pixel) of jitter to add to the rectangle sides to avoid |
| // triangle edges landing precisely on fragment centers. |
| float jigX = 0.5f / getWindowWidth(); |
| float jigY = 0.5f / getWindowHeight(); |
| |
| float sizeX = 1.0f / static_cast<float>(drawSizeX); |
| float sizeY = 1.0f / static_cast<float>(drawSizeY); |
| |
| for (unsigned int i = 0; i < drawSizeX; ++i) |
| { |
| float offsetY = -0.5f + jigY + sizeY * static_cast<float>(i); |
| for (unsigned int j = 0; j < drawSizeY; ++j) |
| { |
| float offsetX = -0.5f + jigX + sizeX * static_cast<float>(j); |
| |
| output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX - sizeX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY - sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX, offsetY + 2 * sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + sizeX, offsetY + sizeY, 0.0f, 1.0f)); |
| output.push_back(tcu::Vec4(offsetX + 2 * sizeX, offsetY - sizeY, 0.0f, 1.0f)); |
| } |
| } |
| } |
| |
| void PrimitiveGen(GLenum primitiveType, unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output) |
| { |
| switch (primitiveType) |
| { |
| case GL_POINTS: |
| PointsGen(drawSizeX, drawSizeY, output); |
| break; |
| case GL_LINES: |
| case GL_LINE_STRIP: |
| case GL_LINE_LOOP: |
| LinesGen(drawSizeX, drawSizeY, output); |
| break; |
| case GL_LINES_ADJACENCY: |
| LinesAdjacencyGen(drawSizeX, drawSizeY, output); |
| break; |
| case GL_LINE_STRIP_ADJACENCY: |
| LineStripAdjacencyGen(drawSizeX, drawSizeY, output); |
| break; |
| case GL_TRIANGLES: |
| case GL_TRIANGLE_STRIP: |
| case GL_TRIANGLE_FAN: |
| TrianglesGen(drawSizeX, drawSizeY, output); |
| break; |
| case GL_TRIANGLES_ADJACENCY: |
| TrianglesAdjacencyGen(drawSizeX, drawSizeY, output); |
| break; |
| case GL_TRIANGLE_STRIP_ADJACENCY: |
| TriangleStripAdjacencyGen(drawSizeX, drawSizeY, output); |
| break; |
| default: |
| throw std::runtime_error("Unknown primitive type!"); |
| break; |
| } |
| } |
| |
| std::string BoolToString(GLboolean value) |
| { |
| if (value == GL_TRUE) |
| return "GL_TRUE"; |
| |
| return "GL_FALSE"; |
| } |
| |
| std::string AccessToString(GLbitfield access) |
| { |
| switch (access) |
| { |
| case GL_READ_WRITE: |
| return "GL_READ_WRITE"; |
| break; |
| case GL_READ_ONLY: |
| return "GL_READ_ONLY"; |
| break; |
| case GL_WRITE_ONLY: |
| return "GL_WRITE_ONLY"; |
| break; |
| default: |
| throw std::runtime_error("Invalid access type!"); |
| break; |
| } |
| } |
| }; |
| |
| template <> |
| void DrawIndirectBase::ReadPixelsFloat<test_api::GL>(int x, int y, int width, int height, void* data) |
| { |
| glReadPixels(x, y, width, height, GL_RGBA, GL_FLOAT, data); |
| } |
| |
| template <> |
| void DrawIndirectBase::ReadPixelsFloat<test_api::ES3>(int x, int y, int width, int height, void* data) |
| { |
| // Use 1010102 pixel buffer for RGB10_A2 FBO to preserve precision during pixel transfer |
| std::vector<GLuint> uData(width * height); |
| const tcu::PixelFormat& pixelFormat = m_context.getRenderContext().getRenderTarget().getPixelFormat(); |
| GLfloat* fData = reinterpret_cast<GLfloat*>(data); |
| GLenum type = ((pixelFormat.redBits == 10) && |
| (pixelFormat.greenBits == 10) && |
| (pixelFormat.blueBits == 10) && |
| (pixelFormat.alphaBits == 2)) ? |
| GL_UNSIGNED_INT_2_10_10_10_REV : |
| GL_UNSIGNED_BYTE; |
| |
| glReadPixels(x, y, width, height, GL_RGBA, type, &uData[0]); |
| |
| if (type == GL_UNSIGNED_BYTE) |
| { |
| for (size_t i = 0; i < uData.size(); i++) |
| { |
| GLubyte* uCompData = reinterpret_cast<GLubyte*>(&uData[i]); |
| |
| for (size_t c = 0; c < 4; c++) |
| { |
| fData[i * 4 + c] = float(uCompData[c]) / 255.0f; |
| } |
| } |
| } |
| else |
| { |
| for (size_t i = 0; i < uData.size(); i++) |
| { |
| fData[i * 4] = float(uData[i] & 0x3FF) / 1023.0f; |
| fData[i * 4 + 1] = float((uData[i] >> 10) & 0x3FF) / 1023.0f; |
| fData[i * 4 + 2] = float((uData[i] >> 20) & 0x3FF) / 1023.0f; |
| fData[i * 4 + 3] = float((uData[i] >> 30) & 0x3) / 3.0f; |
| } |
| } |
| } |
| |
| template <> |
| void DrawIndirectBase::GetBufferSubData<test_api::GL>(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data) |
| { |
| glGetBufferSubData(target, offset, size, data); |
| } |
| |
| template <> |
| void DrawIndirectBase::GetBufferSubData<test_api::ES3>(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data) |
| { |
| void* ptr = glMapBufferRange(target, offset, size, GL_MAP_READ_BIT); |
| memcpy(data, ptr, size); |
| glUnmapBuffer(target); |
| } |
| |
| template <typename api> |
| struct CDefaultBindingPoint : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Draw Indirect: Check default binding point"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that default binding point is set to zero"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Use glGetIntegerv, glGetBooleanv, glGetFloatv, glGetDoublev to get default binding point"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if default binding point is zero"; |
| } |
| |
| virtual long Run() |
| { |
| return BindingPointCheck<api>(0); |
| } |
| }; |
| |
| template <typename api> |
| struct CZeroBindingPoint : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Draw Indirect: Zero binding point"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that binding point is set to zero"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Bind zero and check that binding point is set to zero"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if binding point is set to zero"; |
| } |
| |
| virtual long Run() |
| { |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); |
| |
| return BindingPointCheck<api>(0); |
| } |
| }; |
| |
| template <typename api> |
| struct CSingleBindingPoint : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Draw Indirect: Single binding point"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that binding point is set to correct value"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Bind non-zero buffer and check that binding point is set to correct value"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if binding point is set to correct value"; |
| } |
| |
| virtual long Run() |
| { |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| |
| long ret = BindingPointCheck<api>(_buffer); |
| |
| return ret; |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(1, &_buffer); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <typename api> |
| class CMultiBindingPoint : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Draw Indirect: Multi binding point"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that binding points are set to correct value"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Bind in loop non-zero buffers and check that binding points are set to correct value"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if binding points are set to correct value"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| const int buffNum = sizeof(_buffers) / sizeof(_buffers[0]); |
| |
| glGenBuffers(buffNum, _buffers); |
| |
| for (int i = 0; i < buffNum; ++i) |
| { |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[i]); |
| result.sub_result(BindingPointCheck<api>(_buffers[i])); |
| } |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(sizeof(_buffers) / sizeof(_buffers[0]), _buffers); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffers[10]; |
| }; |
| |
| template <typename api> |
| struct CDeleteBindingPoint : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Draw Indirect: Delete binding point"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that after deleting buffer, binding point is set to correct value"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Bind non-zero buffer, delete buffer, check that binding point is set to 0"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if binding point is set to correct value"; |
| } |
| |
| virtual long Run() |
| { |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| glDeleteBuffers(1, &_buffer); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <typename api> |
| struct CBufferData : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glBufferData and GetBufferSubData<api>"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glBufferData and GetBufferSubData<api> accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data using glBufferData" NL |
| "4. Get data using GetBufferSubData<api>" NL "5. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| |
| CDataArray dataTest(dataWidth * dataHeight, 0); |
| |
| glGenBuffers(sizeof(_buffers) / sizeof(_buffers[0]), _buffers); |
| CDataArray dataRef1; |
| DataGen<unsigned int>(dataRef1, dataWidth, dataHeight, 0, 50); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[1]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef1.size() * sizeof(unsigned int)), &dataRef1[0], |
| GL_DYNAMIC_DRAW); |
| result.sub_result(BindingPointCheck<api>(_buffers[1])); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| CDataArray dataRef2; |
| DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 10, 70); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[2]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef2.size() * sizeof(unsigned int)), &dataRef2[0], |
| GL_STREAM_DRAW); |
| result.sub_result(BindingPointCheck<api>(_buffers[2])); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[3]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, 300, NULL, GL_STATIC_DRAW); |
| result.sub_result(BindingPointCheck<api>(_buffers[3])); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[4]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, 400, NULL, GL_DYNAMIC_READ); |
| result.sub_result(BindingPointCheck<api>(_buffers[4])); |
| |
| CDataArray dataRef5; |
| DataGen<unsigned int>(dataRef5, dataWidth, dataHeight, 0, 50); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[5]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef5.size() * sizeof(unsigned int)), &dataRef5[0], |
| GL_STREAM_READ); |
| result.sub_result(BindingPointCheck<api>(_buffers[5])); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef5, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| CDataArray dataRef6; |
| DataGen<unsigned int>(dataRef6, dataWidth, dataHeight, 10, 40); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[6]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef6.size() * sizeof(unsigned int)), &dataRef6[0], |
| GL_STATIC_READ); |
| result.sub_result(BindingPointCheck<api>(_buffers[6])); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef6, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| CDataArray dataRef7; |
| DataGen<unsigned int>(dataRef7, dataWidth, dataHeight, 4, 70); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[7]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef7.size() * sizeof(unsigned int)), &dataRef7[0], |
| GL_DYNAMIC_COPY); |
| result.sub_result(BindingPointCheck<api>(_buffers[7])); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef7, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[8]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, 800, NULL, GL_STREAM_COPY); |
| result.sub_result(BindingPointCheck<api>(_buffers[8])); |
| |
| CDataArray dataRef9; |
| DataGen<unsigned int>(dataRef9, dataWidth, dataHeight, 18, 35); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[9]); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0], |
| GL_STATIC_COPY); |
| result.sub_result(BindingPointCheck<api>(_buffers[9])); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef9, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| //reallocation: same size |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0], |
| GL_STATIC_COPY); |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef9, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| //reallocation: larger size |
| DataGen<unsigned int>(dataRef9, dataWidth * 2, dataHeight * 2, 18, 35); |
| dataTest.resize(dataRef9.size()); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0], |
| GL_STATIC_COPY); |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result( |
| DataCompare(dataRef9, dataWidth * 2, dataHeight * 2, dataTest, dataWidth * 2, dataHeight * 2)); |
| |
| //reallocation: smaller size |
| DataGen<unsigned int>(dataRef9, dataWidth / 2, dataHeight / 2, 18, 35); |
| dataTest.resize(dataRef9.size()); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0], |
| GL_STATIC_COPY); |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result( |
| DataCompare(dataRef9, dataWidth / 2, dataHeight / 2, dataTest, dataWidth / 2, dataHeight / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(sizeof(_buffers) / sizeof(_buffers[0]), _buffers); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffers[10]; |
| }; |
| |
| template <typename api> |
| struct CBufferSubData : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check function: glBufferSubData and GetBufferSubData<api>"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glBufferSubData and GetBufferSubData<api> accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer" NL "3. Allocate buffer using glBufferData" NL |
| "4. Set data using glBufferSubData" NL "5. Get data using GetBufferSubData<api>" NL "6. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| |
| CDataArray dataRef; |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 4, 70); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), NULL, |
| GL_DYNAMIC_DRAW); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0]); |
| |
| CDataArray dataTest(dataWidth * dataHeight, 0); |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| |
| result.sub_result(DataCompare(dataRef, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| CDataArray dataSubRef; |
| DataGen<unsigned int>(dataSubRef, dataWidth / 2, dataHeight / 2, 80, 90); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 4, (GLsizeiptr)(dataSubRef.size() * sizeof(unsigned int)), |
| &dataSubRef[0]); |
| std::copy(dataSubRef.begin(), dataSubRef.end(), dataRef.begin() + 1); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(1, &_buffer); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <typename api> |
| struct CBufferMap : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glMapBuffer, glUnmapBuffer and getParameteriv"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glMapBuffer, glUnmapBuffer and getParameteriv accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Map buffer" NL |
| "5. Verify mapped buffer" NL "6. Check state" NL "7. Unmap buffer" NL "8. Check state"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| api::GL_Only(); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| |
| CDataArray dataRef; |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 30, 50); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0], |
| GL_DYNAMIC_DRAW); |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| |
| void* buf = glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_ONLY); |
| if (buf == 0) |
| { |
| result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_ONLY) returned NULL"; |
| } |
| |
| if (buf) |
| { |
| result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight)); |
| |
| result.sub_result(StateValidate<api>(GL_TRUE, GL_READ_ONLY, GL_MAP_READ_BIT, 0, |
| (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)))); |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| } |
| |
| buf = glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_WRITE_ONLY); |
| if (buf == 0) |
| { |
| result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_WRITE_ONLY) returned NULL"; |
| } |
| |
| if (buf) |
| { |
| result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight)); |
| |
| result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT, 0, |
| (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)))); |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) != GL_TRUE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| } |
| |
| buf = glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_WRITE); |
| if (buf == 0) |
| { |
| result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_WRITE) returned NULL"; |
| } |
| |
| if (buf) |
| { |
| result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight)); |
| |
| result.sub_result(StateValidate<api>(GL_TRUE, GL_READ_WRITE, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, 0, |
| (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)))); |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| } |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(1, &_buffer); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <typename api> |
| struct CBufferGetPointerv : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glBuffergetPointerv"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glBuffergetPointerv accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Map buffer" NL |
| "5. Get a pointer to buffer" NL "6. Compare pointers from point 4) and 5)" NL |
| "7. Verify mapped buffer" NL "8. Unmap buffer"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| |
| CDataArray dataRef; |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 30, 50); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0], |
| GL_DYNAMIC_DRAW); |
| |
| void* ptr = 0; |
| glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER, &ptr); |
| |
| if (ptr != 0) |
| { |
| result.error() << "glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER) returned invalid " |
| "pointer, expected: NULL"; |
| } |
| |
| void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), |
| GL_MAP_READ_BIT); |
| if (buf == 0) |
| { |
| result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_READ_BIT) returned NULL"; |
| |
| return result.code(); |
| } |
| |
| glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER, &ptr); |
| |
| if (ptr == 0) |
| { |
| result.error() << "glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER) returned NULL"; |
| } |
| |
| if (ptr) |
| { |
| result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, ptr, dataWidth, dataHeight)); |
| } |
| |
| if (ptr != buf) |
| { |
| result.error() << "glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER) different pointer " |
| "than glMapBuffer(GL_DRAW_INDIRECT_BUFFER)"; |
| } |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| ptr = 0; |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(1, &_buffer); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <class api> |
| struct CBufferMapRange : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glMapRangeBuffer, glUnmapBuffer and getParameteriv"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glMapRangeBuffer, glUnmapBuffer and getParameteriv accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Bind non-zero buffer and check that binding point is set to correct value"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Map buffer using glMapBufferRange" NL |
| "5. Check state" NL "6. Verify mapped buffer" NL "7. Unmap buffer" NL "8. Check state"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| |
| CDataArray dataRef; |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 30, 50); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0], |
| GL_DYNAMIC_DRAW); |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| |
| void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), |
| GL_MAP_READ_BIT); |
| if (buf == 0) |
| { |
| result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_MAP_READ_BIT) returned NULL"; |
| } |
| |
| if (buf) |
| { |
| result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight)); |
| |
| result.sub_result(StateValidate<api>(GL_TRUE, GL_READ_ONLY, GL_MAP_READ_BIT, 0, |
| (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)))); |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| } |
| |
| buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int)), |
| GL_MAP_WRITE_BIT); |
| if (buf == 0) |
| { |
| result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL"; |
| } |
| |
| if (buf) |
| { |
| result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight / 2, buf, dataWidth, dataHeight / 2)); |
| |
| result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT, 0, |
| (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int)))); |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| } |
| |
| buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, (GLintptr)(dataRef.size() / 4 * sizeof(unsigned int)), |
| (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int)), GL_MAP_WRITE_BIT); |
| if (buf == 0) |
| { |
| result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL"; |
| } |
| |
| if (buf) |
| { |
| result.sub_result( |
| BufferCheck(dataRef, dataWidth, dataHeight / 2, buf, dataWidth, dataHeight / 2, dataHeight / 4)); |
| |
| result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT, |
| (GLintptr)(dataRef.size() / 4 * sizeof(unsigned int)), |
| (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int)))); |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| } |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(1, &_buffer); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <class api> |
| struct CBufferFlushMappedRange : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glFlushMappedBufferRange"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glFlushMappedBufferRange and getParameteriv accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL |
| "4. Map buffer with GL_MAP_FLUSH_EXPLICIT_BIT flag" NL "5. Check state" NL "6. Modify mapped buffer" NL |
| "7. Flush buffer" NL "8. Unmap buffer" NL "9. Check state" NL "10. Verify buffer"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| |
| CDataArray dataRef; |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 1, 1000); |
| |
| CDataArray dataRef2; |
| DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 1000, 2000); |
| |
| const int halfSize = dataHeight / 2 * dataWidth; |
| const int quarterSize = dataHeight / 4 * dataWidth; |
| |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0], |
| GL_DYNAMIC_DRAW); |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| |
| void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, quarterSize * sizeof(unsigned int), |
| halfSize * sizeof(unsigned int), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| |
| if (buf == 0) |
| { |
| result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL"; |
| } |
| |
| if (buf) |
| { |
| result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT, |
| quarterSize * sizeof(unsigned int), halfSize * sizeof(unsigned int))); |
| |
| memcpy(buf, &dataRef2[quarterSize], halfSize * sizeof(unsigned int)); |
| glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, halfSize * sizeof(unsigned int)); |
| |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| |
| result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0)); |
| } |
| |
| CDataArray dataTest(dataWidth * dataHeight, 0); |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| |
| result.sub_result(DataCompare(dataRef, dataWidth, dataHeight / 4, dataTest, dataWidth, dataHeight / 4)); |
| |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight / 2, dataTest, dataWidth, dataHeight / 2, |
| dataHeight / 4, dataHeight / 4)); |
| |
| result.sub_result(DataCompare(dataRef, dataWidth, dataHeight / 4, dataTest, dataWidth, dataHeight / 4, |
| dataHeight * 3 / 4, dataHeight * 3 / 4)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(1, &_buffer); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <class api> |
| struct CBufferBindRange : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glBindBufferRange"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glBindBufferRange accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer using glBindBufferRange" NL "3. Set data" NL "4. Verify buffer"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer); |
| |
| CDataArray dataRef; |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 1, 100); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef.size() * sizeof(unsigned int), &dataRef[0], GL_DYNAMIC_DRAW); |
| |
| CDataArray dataTest(dataWidth * dataHeight, 0); |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]); |
| result.sub_result(DataCompare(dataRef, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); |
| result.sub_result(BindingPointCheck<api>(0)); |
| |
| glBindBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, _buffer, 0, dataTest.size() * sizeof(unsigned int) / 4); |
| result.sub_result(BindingPointCheck<api>(_buffer)); |
| |
| CDataArray dataRef2; |
| DataGen<unsigned int>(dataRef2, dataWidth, dataHeight / 2, 10, 15); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef2.size() * sizeof(unsigned int) / 4, &dataRef2[0], |
| GL_DYNAMIC_DRAW); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]); |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight / 4, dataTest, dataWidth, dataHeight / 4)); |
| result.sub_result(DataCompare(dataRef, dataWidth, dataHeight * 3 / 4, dataTest, dataWidth, dataHeight * 3 / 4, |
| dataHeight / 4, dataHeight / 4)); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); |
| result.sub_result(BindingPointCheck<api>(0)); |
| |
| glBindBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, _buffer, dataTest.size() * sizeof(unsigned int) / 4, |
| dataTest.size() * sizeof(unsigned int) / 4); |
| result.sub_result(BindingPointCheck<api>(_buffer)); |
| |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef2.size() * sizeof(unsigned int) / 2, |
| &dataRef2[dataRef2.size() / 2], GL_DYNAMIC_DRAW); |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight / 2, dataTest, dataWidth, dataHeight / 2)); |
| result.sub_result(DataCompare(dataRef, dataWidth, dataHeight / 2, dataTest, dataWidth, dataHeight / 2, |
| dataHeight / 2, dataHeight / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(1, &_buffer); |
| |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffer; |
| }; |
| |
| template <class api> |
| struct CBufferBindBase : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glBindBufferBase"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glBindBufferBase accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer using glBindBufferBase" NL "3. Set data" NL "4. Verify buffer"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| |
| glGenBuffers(2, _buffers); |
| |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| CDataArray dataTest(dataWidth * dataHeight, 0); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[0]); |
| CDataArray dataRef1; |
| DataGen<unsigned int>(dataRef1, dataWidth, dataHeight, 1, 100); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef1.size() * sizeof(unsigned int), &dataRef1[0], GL_DYNAMIC_DRAW); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); |
| result.sub_result(BindingPointCheck<api>(0)); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]); |
| result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| result.sub_result(BindingPointCheck<api>(_buffers[0])); |
| |
| glBindBufferBase(GL_DRAW_INDIRECT_BUFFER, 0, _buffers[1]); |
| result.sub_result(BindingPointCheck<api>(_buffers[1])); |
| |
| CDataArray dataRef2; |
| DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 50, 70); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef2.size() * sizeof(unsigned int), &dataRef2[0], GL_DYNAMIC_DRAW); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]); |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| result.sub_result(BindingPointCheck<api>(_buffers[1])); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(2, _buffers); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffers[2]; |
| }; |
| |
| template <class api> |
| struct CBufferCopySubData : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Check functions: glCopyBufferSubData"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glCopyBufferSubData accepts GL_DRAW_INDIRECT_BUFFER enum"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Verify buffer" NL |
| "5. Modify buffer using glCopyBufferSubData" NL "6. Verify buffer"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| DIResult result; |
| int dataWidth, dataHeight; |
| getDataSize(dataWidth, dataHeight); |
| CDataArray dataTest(dataWidth * dataHeight, 0); |
| |
| glGenBuffers(2, _buffers); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffers[0]); |
| |
| CDataArray dataRef1; |
| DataGen<unsigned int>(dataRef1, dataWidth, dataHeight, 1, 100); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(dataRef1.size() * sizeof(unsigned int)), &dataRef1[0], |
| GL_DYNAMIC_DRAW); |
| |
| GetBufferSubData<api>(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), &dataTest[0]); |
| result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[1]); |
| |
| CDataArray dataRef2; |
| DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 10, 30); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef2.size() * sizeof(unsigned int)), &dataRef2[0], |
| GL_DYNAMIC_DRAW); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| glCopyBufferSubData(GL_ARRAY_BUFFER, GL_DRAW_INDIRECT_BUFFER, 0, 0, |
| (GLsizeiptr)(dataTest.size() * sizeof(unsigned int))); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef2.size() * sizeof(unsigned int)), &dataRef2[0], |
| GL_DYNAMIC_DRAW); |
| |
| GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), |
| &dataTest[0]); |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| glCopyBufferSubData(GL_DRAW_INDIRECT_BUFFER, GL_ARRAY_BUFFER, 0, 0, |
| (GLsizeiptr)(dataTest.size() * sizeof(unsigned int))); |
| |
| GetBufferSubData<api>(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), &dataTest[0]); |
| result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteBuffers(2, _buffers); |
| return BindingPointCheck<api>(0); |
| } |
| |
| private: |
| GLuint _buffers[2]; |
| }; |
| |
| class CBasicVertexDef : public DrawIndirectBase |
| { |
| public: |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long Run() |
| { |
| CColorArray coords; |
| PrimitiveGen(_primitiveType, _drawSizeX, _drawSizeY, coords); |
| |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenBuffers(1, &_vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STATIC_DRAW); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| indirectArrays.first = 0; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW); |
| glDrawArraysIndirect(_primitiveType, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| indirectElements.firstIndex = 0; |
| indirectElements.baseVertex = 0; |
| indirectElements.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW); |
| glDrawElementsIndirect(_primitiveType, GL_UNSIGNED_INT, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| |
| DIResult result; |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| glBindVertexArray(0); |
| glUseProgram(0); |
| |
| if (_vao) |
| { |
| glDeleteVertexArrays(1, &_vao); |
| } |
| if (_vbo) |
| { |
| glDeleteBuffers(1, &_vbo); |
| } |
| if (_ebo) |
| { |
| glDeleteBuffers(1, &_ebo); |
| } |
| if (_program) |
| { |
| glDeleteProgram(_program); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| CBasicVertexDef(TDrawFunction drawFunc, GLenum primitiveType, unsigned int drawSizeX, unsigned int drawSizeY) |
| : _drawFunc(drawFunc) |
| , _primitiveType(primitiveType) |
| , _drawSizeX(drawSizeX) |
| , _drawSizeY(drawSizeY) |
| , _vao(0) |
| , _vbo(0) |
| , _ebo(0) |
| , _program(0) |
| { |
| } |
| |
| private: |
| TDrawFunction _drawFunc; |
| GLenum _primitiveType; |
| unsigned int _drawSizeX; |
| unsigned int _drawSizeY; |
| |
| GLuint _vao; |
| GLuint _vbo, _ebo; |
| GLuint _program; |
| |
| CBasicVertexDef() |
| { |
| } |
| }; |
| |
| class CBasicVertexInstancingDef : public DrawIndirectBase |
| { |
| public: |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long Run() |
| { |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, _drawSizeX, _drawSizeY, coords); |
| |
| CColorArray coords_instanced(4); |
| coords_instanced[0] = tcu::Vec4(0.5, 0.5, 0.0, 0.0); |
| coords_instanced[1] = tcu::Vec4(-0.5, 0.5, 0.0, 0.0); |
| coords_instanced[2] = tcu::Vec4(-0.5, -0.5, 0.0, 0.0); |
| coords_instanced[3] = tcu::Vec4(0.5, -0.5, 0.0, 0.0); |
| |
| CColorArray colors_instanced(2); |
| colors_instanced[0] = tcu::Vec4(1.0, 0.0, 0.0, 1.0); |
| colors_instanced[1] = tcu::Vec4(0.0, 1.0, 0.0, 1.0); |
| |
| _program = CreateProgram(Vsh<api>(), "", Fsh<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenBuffers(1, &_vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0]) + |
| coords_instanced.size() * sizeof(coords_instanced[0]) + |
| colors_instanced.size() * sizeof(colors_instanced[0])), |
| NULL, GL_STATIC_DRAW); |
| |
| const size_t coords_offset = 0; |
| const size_t coords_instanced_offset = coords_offset + coords.size() * sizeof(coords[0]); |
| const size_t colors_instanced_offset = |
| coords_instanced_offset + coords_instanced.size() * sizeof(coords_instanced[0]); |
| |
| glBufferSubData(GL_ARRAY_BUFFER, coords_offset, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0]); |
| glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)coords_instanced_offset, |
| (GLsizeiptr)(coords_instanced.size() * sizeof(coords_instanced[0])), &coords_instanced[0]); |
| glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)colors_instanced_offset, |
| (GLsizeiptr)(colors_instanced.size() * sizeof(colors_instanced[0])), &colors_instanced[0]); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| //i_vertex (coords) |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_offset)); |
| glEnableVertexAttribArray(0); |
| |
| //i_vertex_instanced (coords_instanced) |
| glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_instanced_offset)); |
| glEnableVertexAttribArray(1); |
| glVertexAttribDivisor(1, 1); |
| |
| //i_vertex_color_instanced (color_instanced) |
| glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(colors_instanced_offset)); |
| glEnableVertexAttribArray(2); |
| glVertexAttribDivisor(2, 3); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 4; |
| indirectArrays.first = 0; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW); |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 4; |
| indirectElements.firstIndex = 0; |
| indirectElements.baseVertex = 0; |
| indirectElements.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW); |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| CColorArray bufferRef1(getWindowWidth() / 2 * getWindowHeight() / 2, colors_instanced[0]); |
| CColorArray bufferRef2(getWindowWidth() / 2 * getWindowHeight() / 2, colors_instanced[1]); |
| |
| CColorArray bufferTest(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f)); |
| DIResult result; |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, 0, getWindowWidth() / 2, getWindowHeight() / 2, |
| &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef2, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth() / 2, getWindowHeight() / 2, |
| &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, (getWindowHeight() + 1) / 2, getWindowWidth() / 2, |
| getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| glBindVertexArray(0); |
| glUseProgram(0); |
| |
| if (_vao) |
| { |
| glDeleteVertexArrays(1, &_vao); |
| } |
| if (_vbo) |
| { |
| glDeleteBuffers(1, &_vbo); |
| } |
| if (_ebo) |
| { |
| glDeleteBuffers(1, &_ebo); |
| } |
| if (_program) |
| { |
| glDeleteProgram(_program); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| std::string Vsh() |
| { |
| return api::glslVer() + NL |
| "layout(location = 0) in vec4 i_vertex;" NL "layout(location = 1) in vec4 i_vertex_instanced;" NL |
| "layout(location = 2) in vec4 i_vertex_color_instanced;" NL "out vec4 vertex_color_instanced;" NL |
| "void main()" NL "{" NL " gl_Position = vec4(i_vertex.xyz * .5, 1.0) + i_vertex_instanced;" NL |
| " vertex_color_instanced = i_vertex_color_instanced;" NL "}"; |
| } |
| |
| template <typename api> |
| std::string Fsh() |
| { |
| return api::glslVer() + NL "precision highp float; " NL "in vec4 vertex_color_instanced;" NL |
| "out vec4 outColor;" NL "void main() {" NL " outColor = vertex_color_instanced;" NL |
| "}"; |
| } |
| |
| CBasicVertexInstancingDef(TDrawFunction drawFunc) |
| : _drawFunc(drawFunc), _drawSizeX(2), _drawSizeY(2), _vao(0), _vbo(0), _ebo(0), _program(0) |
| { |
| } |
| |
| private: |
| TDrawFunction _drawFunc; |
| unsigned int _drawSizeX; |
| unsigned int _drawSizeY; |
| |
| GLuint _vao; |
| GLuint _vbo, _ebo; |
| GLuint _program; |
| |
| CBasicVertexInstancingDef() |
| { |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawArraysSingle : public CBasicVertexDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: Single primitive using glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that the vertex attributes can be sourced from VBO for glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawArraysSingle() : CBasicVertexDef(DRAW_ARRAYS, GL_TRIANGLES, 1, 1) |
| { |
| } |
| virtual long Run() |
| { |
| return CBasicVertexDef::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawArraysMany : public CBasicVertexDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: Many primitives using glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that the vertex attributes can be sourced from VBO for glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define primitives using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawArraysMany() : CBasicVertexDef(DRAW_ARRAYS, GL_TRIANGLES, 8, 8) |
| { |
| } |
| virtual long Run() |
| { |
| return CBasicVertexDef::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawArraysInstancing : public CBasicVertexInstancingDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: Single primitive using glDrawArraysIndirect, multiple instances"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that the vertex attributes can be sourced from VBO for glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawArraysInstancing() : CBasicVertexInstancingDef(DRAW_ARRAYS) |
| { |
| } |
| virtual long Run() |
| { |
| return CBasicVertexInstancingDef::Run<api>(); |
| } |
| }; |
| |
| class CBasicXFBPausedDef : public DrawIndirectBase |
| { |
| public: |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long Run() |
| { |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, _drawSizeX, _drawSizeY, coords); |
| |
| _program = CreateProgram(Vsh<api>(), "", shaders::fshSimple<api>(), false); |
| |
| const GLchar* varyings[] = { "dataOut" }; |
| glTransformFeedbackVaryings(_program, 1, varyings, GL_INTERLEAVED_ATTRIBS); |
| glLinkProgram(_program); |
| if (!CheckProgram(_program)) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenBuffers(1, &_vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STATIC_DRAW); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenTransformFeedbacks(1, &_xfo); |
| glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, _xfo); |
| |
| glGenBuffers(1, &_xfbo); |
| glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _xfbo); |
| glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, NULL, GL_STATIC_DRAW); |
| glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _xfbo); |
| |
| glBeginTransformFeedback(GL_TRIANGLES); |
| glPauseTransformFeedback(); |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| indirectArrays.first = 0; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW); |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| indirectElements.firstIndex = 0; |
| indirectElements.baseVertex = 0; |
| indirectElements.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW); |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| glResumeTransformFeedback(); |
| glEndTransformFeedback(); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| |
| DIResult result; |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| glBindVertexArray(0); |
| glUseProgram(0); |
| |
| if (_vao) |
| { |
| glDeleteVertexArrays(1, &_vao); |
| } |
| if (_vbo) |
| { |
| glDeleteBuffers(1, &_vbo); |
| } |
| if (_ebo) |
| { |
| glDeleteBuffers(1, &_ebo); |
| } |
| if (_xfbo) |
| { |
| glDeleteBuffers(1, &_xfbo); |
| } |
| if (_program) |
| { |
| glDeleteProgram(_program); |
| } |
| if (_xfo) |
| { |
| glDeleteTransformFeedbacks(1, &_xfo); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| std::string Vsh() |
| { |
| return api::glslVer() + NL "in vec4 i_vertex;" NL "out vec4 dataOut;" NL "void main()" NL "{" NL |
| " gl_Position = i_vertex;" NL " dataOut = i_vertex;" NL "}"; |
| } |
| |
| CBasicXFBPausedDef(TDrawFunction drawFunc) |
| : _drawFunc(drawFunc), _drawSizeX(2), _drawSizeY(2), _vao(0), _vbo(0), _ebo(0), _xfbo(0), _program(0), _xfo(0) |
| { |
| } |
| |
| private: |
| TDrawFunction _drawFunc; |
| unsigned int _drawSizeX; |
| unsigned int _drawSizeY; |
| |
| GLuint _vao; |
| GLuint _vbo, _ebo, _xfbo; |
| GLuint _program; |
| GLuint _xfo; |
| |
| CBasicXFBPausedDef() |
| { |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawArraysXFBPaused : public CBasicXFBPausedDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: glDrawArraysIndirect, in paused transform feedback operation"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify glDrawArraysIndirect works, if XFB is active and paused"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawArraysXFBPaused() : CBasicXFBPausedDef(DRAW_ARRAYS) |
| { |
| } |
| virtual long Run() |
| { |
| return CBasicXFBPausedDef::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawElementsSingle : public CBasicVertexDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: Single primitive using glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that the vertex attributes can be sourced from VBO for glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawElementsIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawElementsSingle() : CBasicVertexDef(DRAW_ELEMENTS, GL_TRIANGLES, 1, 1) |
| { |
| } |
| virtual long Run() |
| { |
| return CBasicVertexDef::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawElementsMany : public CBasicVertexDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: Many primitives using glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that the vertex attributes can be sourced from VBO for glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define primitives using VBO" NL "2. Draw primitive using glDrawElementsIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawElementsMany() : CBasicVertexDef(DRAW_ELEMENTS, GL_TRIANGLES, 8, 8) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CBasicVertexDef::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawElementsInstancing : public CBasicVertexInstancingDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: Single primitive using glDrawElementsIndirect, multiple instances"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that the vertex attributes can be sourced from VBO for glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawElementsIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawElementsInstancing() : CBasicVertexInstancingDef(DRAW_ELEMENTS) |
| { |
| } |
| virtual long Run() |
| { |
| return CBasicVertexInstancingDef::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CVBODrawElementsXFBPaused : public CBasicXFBPausedDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "VBO: glDrawElementsIndirect, in paused transform feedback operation"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify glDrawElementsIndirect works, if XFB is active and paused"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CVBODrawElementsXFBPaused() : CBasicXFBPausedDef(DRAW_ELEMENTS) |
| { |
| } |
| virtual long Run() |
| { |
| return CBasicXFBPausedDef::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawArraysSimple : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawArraysIndirect: many primitives simple"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with specified indirect structure" NL "in a buffer"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| indirectArrays.first = 0; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawArraysNoFirst : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawArraysIndirect: non-zero 'first' argument"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with specified non-zero 'first' argument" NL |
| "in indirect buffer"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()) / 2; |
| indirectArrays.primCount = 1; |
| indirectArrays.first = static_cast<GLuint>(coords.size()) / 2; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| |
| CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawArraysOffset : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawArraysIndirect: offset as a function parameter"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with offset as a function parameter"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect with offset" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| indirectArrays.first = 0; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand) * 3, NULL, GL_STATIC_DRAW); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), sizeof(DrawArraysIndirectCommand), |
| &indirectArrays); |
| glDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DrawArraysIndirectCommand)); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawElementsSimple : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawElementsIndirect: many primitives simple"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with specified indirect structure" NL "in a buffer"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| indirectElements.baseVertex = 0; |
| indirectElements.firstIndex = 0; |
| indirectElements.reservedMustBeZero = 0; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| glDeleteBuffers(1, &_ebo); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect, _ebo; |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawElementsNoFirstIndex : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawElementsIndirect: non-zero first index"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with non-zero first index" NL "in indirect buffer"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()) / 2; |
| indirectElements.primCount = 1; |
| indirectElements.baseVertex = 0; |
| indirectElements.firstIndex = static_cast<GLuint>(coords.size()) / 2; |
| indirectElements.reservedMustBeZero = 0; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| |
| CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect, _ebo; |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawElementsNoBasevertex : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawElementsIndirect: non-zero base vertex"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with non-zero base vertex" NL "in indirect buffer"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()) / 2; |
| indirectElements.primCount = 1; |
| indirectElements.baseVertex = static_cast<GLint>(coords.size()) / 2; |
| indirectElements.firstIndex = 0; |
| indirectElements.reservedMustBeZero = 0; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| |
| CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawElementsOffset : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawElementsIndirect: offset as a function parameter"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with offset as a function parameter"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect with offset" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| indirectElements.baseVertex = 0; |
| indirectElements.firstIndex = 0; |
| indirectElements.reservedMustBeZero = 0; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand) * 3, NULL, GL_STATIC_DRAW); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), |
| sizeof(DrawElementsIndirectCommand), &indirectElements); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (void*)sizeof(DrawElementsIndirectCommand)); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| class CBasicVertexIDsDef : public DrawIndirectBase |
| { |
| public: |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long Run() |
| { |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, _drawSizeX, _drawSizeY, coords); |
| |
| CColorArray coords_instanced(4); |
| coords_instanced[0] = tcu::Vec4(0.5, 0.5, 0.0, 0.0); |
| coords_instanced[1] = tcu::Vec4(-0.5, 0.5, 0.0, 0.0); |
| coords_instanced[2] = tcu::Vec4(-0.5, -0.5, 0.0, 0.0); |
| coords_instanced[3] = tcu::Vec4(0.5, -0.5, 0.0, 0.0); |
| |
| std::vector<glw::GLfloat> ref_VertexId(coords.size()); |
| for (size_t i = 0; i < ref_VertexId.size(); i++) |
| { |
| ref_VertexId[i] = glw::GLfloat(i); |
| } |
| |
| std::vector<glw::GLfloat> ref_InstanceId(4); |
| for (size_t i = 0; i < ref_InstanceId.size(); i++) |
| { |
| ref_InstanceId[i] = glw::GLfloat(i); |
| } |
| |
| _program = CreateProgram(Vsh<api>(), "", Fsh<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenBuffers(1, &_vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0]) + |
| coords_instanced.size() * sizeof(coords_instanced[0]) + |
| ref_VertexId.size() * sizeof(ref_VertexId[0]) + |
| ref_InstanceId.size() * sizeof(ref_InstanceId[0])), |
| NULL, GL_STATIC_DRAW); |
| |
| const size_t coords_offset = 0; |
| const size_t coords_instanced_offset = coords_offset + coords.size() * sizeof(coords[0]); |
| const size_t ref_VertexId_offset = |
| coords_instanced_offset + coords_instanced.size() * sizeof(coords_instanced[0]); |
| const size_t ref_InstanceId_offset = ref_VertexId_offset + ref_VertexId.size() * sizeof(ref_VertexId[0]); |
| |
| glBufferSubData(GL_ARRAY_BUFFER, coords_offset, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0]); |
| glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)coords_instanced_offset, |
| (GLsizeiptr)(coords_instanced.size() * sizeof(coords_instanced[0])), &coords_instanced[0]); |
| glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)ref_VertexId_offset, |
| (GLsizeiptr)(ref_VertexId.size() * sizeof(ref_VertexId[0])), &ref_VertexId[0]); |
| glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)ref_InstanceId_offset, |
| (GLsizeiptr)(ref_InstanceId.size() * sizeof(ref_InstanceId[0])), &ref_InstanceId[0]); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| //i_vertex (coords) |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_offset)); |
| glEnableVertexAttribArray(0); |
| |
| //i_vertex_instanced (coords_instanced) |
| glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_instanced_offset)); |
| glEnableVertexAttribArray(1); |
| glVertexAttribDivisor(1, 1); |
| |
| //i_ref_VertexId |
| glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(ref_VertexId_offset)); |
| glEnableVertexAttribArray(2); |
| //i_ref_InstanceId |
| glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(ref_InstanceId_offset)); |
| glEnableVertexAttribArray(3); |
| glVertexAttribDivisor(3, 1); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 4; |
| indirectArrays.first = 0; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW); |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 4; |
| indirectElements.firstIndex = 0; |
| indirectElements.baseVertex = 0; |
| indirectElements.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| { |
| GLuint buffer; |
| glGenBuffers(1, &buffer); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW); |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| glDeleteBuffers(1, &buffer); |
| } |
| } |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| CColorArray bufferRef1(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.5f, 0.0f)); |
| CColorArray bufferRef2(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.75f, 0.0f)); |
| CColorArray bufferRef3(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.25f, 0.0f)); |
| CColorArray bufferRef4(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f)); |
| |
| CColorArray bufferTest(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f)); |
| DIResult result; |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, 0, getWindowWidth() / 2, getWindowHeight() / 2, |
| &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef2, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth() / 2, getWindowHeight() / 2, |
| &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef3, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, (getWindowHeight() + 1) / 2, getWindowWidth() / 2, |
| getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef4, |
| getWindowWidth() / 2, getWindowHeight() / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| glBindVertexArray(0); |
| glUseProgram(0); |
| |
| if (_vao) |
| { |
| glDeleteVertexArrays(1, &_vao); |
| } |
| if (_vbo) |
| { |
| glDeleteBuffers(1, &_vbo); |
| } |
| if (_ebo) |
| { |
| glDeleteBuffers(1, &_ebo); |
| } |
| if (_program) |
| { |
| glDeleteProgram(_program); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| std::string Vsh() |
| { |
| return api::glslVer() + NL |
| "layout(location = 0) in vec4 i_vertex;" NL "layout(location = 1) in vec4 i_vertex_instanced;" NL |
| "layout(location = 2) in float i_ref_VertexId;" NL "layout(location = 3) in float i_ref_InstanceId;" NL |
| "out vec4 val_Result;" NL "void main()" NL "{" NL |
| " gl_Position = vec4(i_vertex.xyz * .5, 1.0) + i_vertex_instanced;" NL |
| " if ( gl_VertexID == int(i_ref_VertexId + .5) && gl_InstanceID == int(i_ref_InstanceId + .5)) {" NL |
| " val_Result = vec4(0.0, 1.0, float(gl_InstanceID) / 4.0, 1.0);" NL " } else {" NL |
| " val_Result = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}"; |
| } |
| |
| template <typename api> |
| std::string Fsh() |
| { |
| return api::glslVer() + NL "precision highp float; " NL "in vec4 val_Result;" NL "out vec4 outColor;" NL |
| "void main() {" NL " outColor = val_Result;" NL "}"; |
| } |
| |
| CBasicVertexIDsDef(TDrawFunction drawFunc) |
| : _drawFunc(drawFunc), _drawSizeX(2), _drawSizeY(2), _vao(0), _vbo(0), _ebo(0), _program(0) |
| { |
| } |
| |
| private: |
| TDrawFunction _drawFunc; |
| unsigned int _drawSizeX; |
| unsigned int _drawSizeY; |
| |
| GLuint _vao; |
| GLuint _vbo, _ebo; |
| GLuint _program; |
| |
| CBasicVertexIDsDef() |
| { |
| } |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawArraysVertexIds : public CBasicVertexIDsDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawArraysIndirect: all non-zero arguments, verify vertex ids"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with all non-zero arguments" NL "in indirect buffer"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| return CBasicVertexIDsDef::Run<api>(); |
| } |
| |
| CBufferIndirectDrawArraysVertexIds() : CBasicVertexIDsDef(DRAW_ARRAYS) |
| { |
| } |
| }; |
| |
| template <typename api> |
| class CBufferIndirectDrawElementsVertexIds : public CBasicVertexIDsDef |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Indirect buffer glDrawElementsIndirect: all non-zero arguments, verify vertex ids"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that it is possible to draw primitives with all non-zero arguments" NL "in indirect buffer"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Run() |
| { |
| return CBasicVertexIDsDef::Run<api>(); |
| } |
| |
| CBufferIndirectDrawElementsVertexIds() : CBasicVertexIDsDef(DRAW_ELEMENTS) |
| { |
| } |
| }; |
| |
| template <typename api> |
| class CIndicesDataTypeUnsignedShort : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect indices data type: unsigned short"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that unsigned short indices are accepted by glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL "3. Create element buffer" NL |
| "4. Draw primitives using glDrawElementsIndirect" NL "5. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()) / 2; |
| indirectElements.primCount = 1; |
| indirectElements.baseVertex = -static_cast<GLint>(coords.size()) / 4; |
| indirectElements.firstIndex = static_cast<GLuint>(coords.size()) / 4; |
| indirectElements.reservedMustBeZero = 0; |
| |
| std::vector<GLushort> elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLushort>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), NULL, GL_STATIC_DRAW); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), &indirectElements); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0); |
| |
| CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| class CIndicesDataTypeUnsignedByte : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect indices data type: unsigned byte"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that unsigned byte indices are accepted by glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL "3. Create element buffer" NL |
| "4. Draw primitives using glDrawElementsIndirect" NL "5. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 2, 2, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()) / 2; |
| indirectElements.primCount = 1; |
| indirectElements.baseVertex = -static_cast<GLint>(coords.size()) / 4; |
| indirectElements.firstIndex = static_cast<GLuint>(coords.size()) / 4; |
| indirectElements.reservedMustBeZero = 0; |
| |
| std::vector<GLubyte> elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLubyte>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), NULL, GL_STATIC_DRAW); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), &indirectElements); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_BYTE, 0); |
| |
| CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1, |
| getWindowWidth(), getWindowHeight() / 2)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| class CPrimitiveMode : public DrawIndirectBase |
| { |
| public: |
| template <typename api> |
| bool IsGeometryShaderSupported() |
| { |
| if (api::isES()) |
| { |
| const glu::ContextInfo& info = m_context.getContextInfo(); |
| const glu::ContextType& type = m_context.getRenderContext().getType(); |
| |
| /* ES 3.2+ included geometry shaders into the core */ |
| if (glu::contextSupports(type, glu::ApiType(3, 2, glu::PROFILE_ES))) |
| { |
| return true; |
| } |
| /* ES 3.1 may be able to support geometry shaders via extensions */ |
| else if ((glu::contextSupports(type, glu::ApiType(3, 1, glu::PROFILE_ES))) && |
| ((true == info.isExtensionSupported("GL_EXT_geometry_shader")) || |
| (true == info.isExtensionSupported("GL_OES_geometry_shader")))) |
| { |
| return true; |
| } |
| else |
| { |
| OutputNotSupported("Geometry shader is not supported\n"); |
| return false; |
| } |
| } |
| else |
| { |
| return true; |
| } |
| } |
| virtual long Setup() |
| { |
| _sizeX = getWindowWidth(); |
| _sizeY = getWindowHeight(); |
| if (_primitiveType != GL_TRIANGLE_STRIP && _primitiveType != GL_TRIANGLE_STRIP_ADJACENCY && |
| _primitiveType != GL_TRIANGLES && _primitiveType != GL_TRIANGLES_ADJACENCY && |
| _primitiveType != GL_TRIANGLE_FAN) |
| { |
| _sizeX &= (-4); |
| _sizeY &= (-4); |
| } |
| if ((int)_drawSizeX < 0 || (int)_drawSizeY < 0) |
| { |
| //no PrimitiveGen dimensions given. assume same dimensions as rendered image^ |
| _drawSizeX = _sizeX; |
| _drawSizeY = _sizeY; |
| if (_primitiveType == GL_POINTS) |
| { |
| //clamp vertex number (and rendering size) for points to max. 10000 |
| _sizeX = _drawSizeX = std::min(_drawSizeX, 100u); |
| _sizeY = _drawSizeY = std::min(_drawSizeY, 100u); |
| } |
| } |
| |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long Run(bool pointMode = false) |
| { |
| |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| _program = CreateProgram(pointMode ? shaders::vshSimple_point<api>() : shaders::vshSimple<api>(), "", |
| shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(_primitiveType, _drawSizeX, _drawSizeY, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| CColorArray padding(10, tcu::Vec4(0.0f)); |
| |
| glBufferData(GL_ARRAY_BUFFER, |
| (GLsizeiptr)(coords.size() * (sizeof(coords[0])) + padding.size() * (sizeof(padding[0]))), NULL, |
| GL_STREAM_DRAW); |
| glBufferSubData(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(padding.size() * (sizeof(padding[0]))), &padding[0]); |
| glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)(padding.size() * (sizeof(padding[0]))), |
| (GLsizeiptr)(coords.size() * (sizeof(coords[0]))), &coords[0]); |
| |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| indirectArrays.count = static_cast<GLuint>(coords.size()) / 2; |
| indirectArrays.primCount = 1; |
| indirectArrays.first = 10; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), NULL, GL_STATIC_DRAW); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawArraysIndirectCommand), &indirectArrays); |
| |
| glDrawArraysIndirect(_primitiveType, 0); |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| indirectElements.count = static_cast<GLuint>(coords.size()) / 2; |
| indirectElements.primCount = 1; |
| indirectElements.baseVertex = 7; |
| indirectElements.firstIndex = 3; |
| indirectElements.reservedMustBeZero = 0; |
| |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), NULL, GL_STATIC_DRAW); |
| glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), &indirectElements); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(_primitiveType, GL_UNSIGNED_INT, 0); |
| } |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| CColorArray bufferRef1(_sizeX * _sizeY / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| CColorArray bufferRef2(_sizeX * _sizeY / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(_sizeX * _sizeY, tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, (_sizeY + 1) / 2, _sizeX, _sizeY / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, _sizeX, _sizeY / 2, bufferRef1, _sizeX, _sizeY / 2)); |
| |
| switch (_primitiveType) |
| { |
| case GL_TRIANGLES_ADJACENCY: |
| case GL_TRIANGLE_STRIP_ADJACENCY: |
| { |
| CColorArray bufferRef3(_sizeX * _sizeY / 16, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| CColorArray bufferRef4(_sizeX * _sizeY / 8, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferRef5(_sizeX * _sizeY / 4, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); |
| |
| CColorArray bufferTest3(_sizeX * _sizeY / 16, tcu::Vec4(0.0f)); |
| CColorArray bufferTest4(_sizeX * _sizeY / 8, tcu::Vec4(0.0f)); |
| CColorArray bufferTest5(_sizeX * _sizeY / 4, tcu::Vec4(0.0f)); |
| |
| ReadPixelsFloat<api>(0, (_sizeY + 3) / 4, _sizeX / 4, _sizeY / 4, &bufferTest3[0]); |
| result.sub_result(BuffersCompare(bufferTest3, _sizeX / 4, _sizeY / 4, bufferRef3, _sizeX / 4, _sizeY / 4)); |
| |
| ReadPixelsFloat<api>((_sizeX + 3) / 4, (_sizeY + 3) / 4, _sizeX / 2, _sizeY / 4, &bufferTest4[0]); |
| result.sub_result(BuffersCompare(bufferTest4, _sizeX / 2, _sizeY / 4, bufferRef4, _sizeX / 2, _sizeY / 4)); |
| |
| ReadPixelsFloat<api>((_sizeX * 3 + 3) / 4, (_sizeY + 3) / 4, _sizeX / 4, _sizeY / 4, &bufferTest3[0]); |
| result.sub_result(BuffersCompare(bufferTest3, _sizeX / 4, _sizeY / 4, bufferRef3, _sizeX / 4, _sizeY / 4)); |
| |
| ReadPixelsFloat<api>(0, 0, _sizeX, _sizeY / 4, &bufferTest5[0]); |
| result.sub_result(BuffersCompare(bufferTest5, _sizeX, _sizeY / 4, bufferRef5, _sizeX, _sizeY / 4)); |
| } |
| break; |
| default: |
| { |
| ReadPixelsFloat<api>(0, 0, _sizeX, _sizeY / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, _sizeX, _sizeY / 2, bufferRef2, _sizeX, _sizeY / 2)); |
| } |
| break; |
| } |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| CPrimitiveMode(TDrawFunction drawFunc, GLenum primitiveType, unsigned int sizeX = -1, unsigned sizeY = -1) |
| : _drawFunc(drawFunc) |
| , _primitiveType(primitiveType) |
| , _drawSizeX(sizeX) |
| , _drawSizeY(sizeY) |
| , _sizeX(0) |
| , _sizeY(0) |
| , _program(0) |
| , _vao(0) |
| , _buffer(0) |
| , _ebo(0) |
| , _bufferIndirect(0) |
| { |
| } |
| |
| private: |
| TDrawFunction _drawFunc; |
| GLenum _primitiveType; |
| unsigned int _drawSizeX, _drawSizeY; //dims for primitive generator |
| unsigned int _sizeX, _sizeY; //rendering size |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| |
| CPrimitiveMode(); |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysPoints : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_POINTS"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_POINTS works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysPoints() : CPrimitiveMode(DRAW_ARRAYS, GL_POINTS) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(true); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysLines : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_LINES"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_LINES works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysLines() : CPrimitiveMode(DRAW_ARRAYS, GL_LINES) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysLineStrip : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_LINE_STRIP"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_LINE_STRIP works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysLineStrip() : CPrimitiveMode(DRAW_ARRAYS, GL_LINE_STRIP) |
| { |
| } |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysLineLoop : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_LINE_LOOP"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_LINE_LOOP works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysLineLoop() : CPrimitiveMode(DRAW_ARRAYS, GL_LINE_LOOP) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysTriangleStrip : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_TRIANGLE_STRIP"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_TRIANGLE_STRIP works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysTriangleStrip() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLE_STRIP, 2, 2) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysTriangleFan : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_TRIANGLE_FAN"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_TRIANGLE_FAN works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysTriangleFan() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLE_FAN, 2, 2) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysLinesAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_LINES_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_LINES_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysLinesAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_LINES_ADJACENCY) |
| { |
| } |
| |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysLineStripAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_LINE_STRIP_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_LINE_STRIP_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysLineStripAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_LINE_STRIP_ADJACENCY) |
| { |
| } |
| |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysTrianglesAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_TRIANGLES_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_TRIANGLES_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysTrianglesAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLES_ADJACENCY, 4, 4) |
| { |
| } |
| |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawArraysTriangleStripAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawArraysIndirect mode: GL_TRIANGLE_STRIP_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawArraysIndirect with GL_TRIANGLE_STRIP_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawArraysTriangleStripAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLE_STRIP_ADJACENCY, 4, 4) |
| { |
| } |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsPoints : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_POINTS"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_POINTS works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsPoints() : CPrimitiveMode(DRAW_ELEMENTS, GL_POINTS) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(true); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsLines : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_LINES"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_LINES works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsLines() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINES) |
| { |
| } |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsLineStrip : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_LINE_STRIP"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_LINE_STRIP works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsLineStrip() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINE_STRIP) |
| { |
| } |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsLineLoop : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_LINE_LOOP"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_LINE_LOOP works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsLineLoop() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINE_LOOP) |
| { |
| } |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsTriangleStrip : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_TRIANGLE_STRIP"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_TRIANGLE_STRIP works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsTriangleStrip() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLE_STRIP, 2, 2) |
| { |
| } |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsTriangleFan : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_TRIANGLE_FAN"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_TRIANGLE_FAN works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsTriangleFan() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLE_FAN, 2, 2) |
| { |
| } |
| virtual long Run() |
| { |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsLinesAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_LINES_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_LINES_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsLinesAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINES_ADJACENCY) |
| { |
| } |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsLineStripAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_LINE_STRIP_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_LINE_STRIP_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsLineStripAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINE_STRIP_ADJACENCY) |
| { |
| } |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsTrianglesAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_TRIANGLES_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_TRIANGLES_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsTrianglesAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLES_ADJACENCY, 4, 4) |
| { |
| } |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CModeDrawElementsTriangleStripAdjacency : public CPrimitiveMode |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "glDrawElementsIndirect mode: GL_TRIANGLE_STRIP_ADJACENCY"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that glDrawElementsIndirect with GL_TRIANGLE_STRIP_ADJACENCY works correctly"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and fill VBO" NL "2. Create indirect buffer" NL |
| "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CModeDrawElementsTriangleStripAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLE_STRIP_ADJACENCY, 4, 4) |
| { |
| } |
| virtual long Run() |
| { |
| if (!IsGeometryShaderSupported<api>()) |
| return NOT_SUPPORTED; |
| return CPrimitiveMode::Run<api>(); |
| } |
| }; |
| |
| class CTransformFeedback : public DrawIndirectBase |
| { |
| public: |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long Run() |
| { |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLE_STRIP, 8, 8, coords); |
| |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| _program = CreateProgram(Vsh<api>(), "", shaders::fshSimple<api>(), false); |
| const GLchar* varyings[] = { "dataOut" }; |
| glTransformFeedbackVaryings(_program, 1, varyings, GL_INTERLEAVED_ATTRIBS); |
| glLinkProgram(_program); |
| if (!CheckProgram(_program)) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenBuffers(1, &_vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ubo); |
| glBindBuffer(GL_UNIFORM_BUFFER, _ubo); |
| glBufferData(GL_UNIFORM_BUFFER, 4 * 5 * sizeof(GLuint), NULL, GL_STATIC_DRAW); |
| glBindBufferBase(GL_UNIFORM_BUFFER, glGetUniformBlockIndex(_program, "BLOCK"), _ubo); |
| std::vector<GLuint> uboData; |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| uboData.resize(4 * 4, 0); |
| |
| uboData[0] = static_cast<GLuint>(coords.size()); //count |
| uboData[4] = 1; //primcount |
| uboData[8] = 0; //first |
| uboData[12] = 0; //mbz |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| uboData.resize(4 * 5, 0); |
| uboData[0] = static_cast<GLuint>(coords.size()); //count |
| uboData[4] = 1; //primcount |
| uboData[8] = 0; //firstindex |
| uboData[12] = 0; //basevertex |
| uboData[16] = 0; //mbz |
| } |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| glBufferSubData(GL_UNIFORM_BUFFER, 0, (GLsizeiptr)(uboData.size() * sizeof(uboData[0])), &uboData[0]); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_bufferIndirect); |
| |
| glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _bufferIndirect); |
| GLuint zeroes[] = { 0, 0, 0, 0, 0 }; |
| glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(zeroes), zeroes, GL_DYNAMIC_DRAW); |
| glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| |
| glEnable(GL_RASTERIZER_DISCARD); |
| glBeginTransformFeedback(GL_POINTS); |
| glDrawArrays(GL_POINTS, 0, 5); |
| glEndTransformFeedback(); |
| glDisable(GL_RASTERIZER_DISCARD); |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| break; |
| case DRAW_ELEMENTS: |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| |
| DIResult result; |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| glBindVertexArray(0); |
| glUseProgram(0); |
| |
| if (_vao) |
| { |
| glDeleteVertexArrays(1, &_vao); |
| } |
| if (_vbo) |
| { |
| glDeleteBuffers(1, &_vbo); |
| } |
| if (_ebo) |
| { |
| glDeleteBuffers(1, &_ebo); |
| } |
| if (_ubo) |
| { |
| glDeleteBuffers(1, &_ubo); |
| } |
| if (_bufferIndirect) |
| { |
| glDeleteBuffers(1, &_bufferIndirect); |
| } |
| if (_program) |
| { |
| glDeleteProgram(_program); |
| } |
| return NO_ERROR; |
| } |
| |
| CTransformFeedback(TDrawFunction drawFunc) |
| : _drawFunc(drawFunc), _program(0), _vao(0), _vbo(0), _ebo(0), _ubo(0), _bufferIndirect(0) |
| { |
| } |
| |
| private: |
| TDrawFunction _drawFunc; |
| GLuint _program; |
| GLuint _vao, _vbo, _ebo, _ubo, _bufferIndirect; |
| |
| CTransformFeedback(); |
| |
| template <typename api> |
| std::string Vsh() |
| { |
| return api::glslVer() + NL "flat out highp uint dataOut;" NL "in vec4 i_vertex;" NL |
| "layout(std140) uniform BLOCK {" NL " uint m[5];" NL "} b;" NL "void main() {" NL |
| " dataOut = b.m[min(4, gl_VertexID)];" NL " gl_Position = i_vertex;" NL "}"; |
| } |
| }; |
| |
| template <typename api> |
| struct CTransformFeedbackArray : public CTransformFeedback |
| { |
| virtual std::string Title() |
| { |
| return "Transform feedback: glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that transform feedback works correctly with glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create data" NL "2. Use data as input to glDrawArrayIndirect" NL "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CTransformFeedbackArray() : CTransformFeedback(DRAW_ARRAYS) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CTransformFeedback::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| struct CTransformFeedbackElements : public CTransformFeedback |
| { |
| virtual std::string Title() |
| { |
| return "Transform feedback: glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that transform feedback works correctly with glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create data" NL "2. Use data as input to glDrawElementsIndirect" NL "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CTransformFeedbackElements() : CTransformFeedback(DRAW_ELEMENTS) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CTransformFeedback::Run<api>(); |
| } |
| }; |
| |
| class CComputeBase : public DrawIndirectBase |
| { |
| public: |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| template <typename api> |
| long Run() |
| { |
| |
| int width, height; |
| glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &width); |
| glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &height); |
| |
| width = std::min(width, getWindowWidth()); |
| height = std::min(height, getWindowHeight()); |
| |
| glViewport(0, 0, width, height); |
| |
| CColorArray coords(width * height, tcu::Vec4(0)); |
| CColorArray colors(width * height, tcu::Vec4(0)); |
| |
| _program = CreateProgram(Vsh<api>(), "", Fsh<api>(), false); |
| glBindAttribLocation(_program, 0, "in_coords"); |
| glBindAttribLocation(_program, 1, "in_colors"); |
| glLinkProgram(_program); |
| if (!CheckProgram(_program)) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_bufferCoords); |
| glBindBuffer(GL_ARRAY_BUFFER, _bufferCoords); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), 0, GL_STREAM_DRAW); |
| |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0); |
| glEnableVertexAttribArray(0); |
| |
| glGenBuffers(1, &_bufferColors); |
| glBindBuffer(GL_ARRAY_BUFFER, _bufferColors); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(colors.size() * sizeof(colors[0])), 0, GL_STREAM_DRAW); |
| |
| glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0); |
| glEnableVertexAttribArray(1); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| |
| CElementArray elements(width * height, 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, |
| GL_STATIC_DRAW); |
| } |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| _programCompute = CreateComputeProgram(Csh<api>(), false); |
| glLinkProgram(_programCompute); |
| if (!CheckProgram(_programCompute)) |
| { |
| return ERROR; |
| } |
| glUseProgram(_programCompute); |
| glUniform1ui(glGetUniformLocation(_programCompute, "width"), width); |
| glUniform1ui(glGetUniformLocation(_programCompute, "height"), height); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, _bufferCoords); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, _bufferColors); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, _bufferIndirect); |
| |
| glDispatchCompute(width, height, 1); |
| glMemoryBarrier(GL_COMMAND_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT); |
| |
| glUseProgram(_program); |
| |
| switch (_drawFunc) |
| { |
| case DRAW_ARRAYS: |
| { |
| glDrawArraysIndirect(GL_POINTS, 0); |
| } |
| break; |
| case DRAW_ELEMENTS: |
| { |
| glDrawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, 0); |
| } |
| break; |
| default: |
| throw std::runtime_error("Unknown draw function!"); |
| break; |
| } |
| |
| CColorArray bufferRef1(width * height / 4, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); |
| CColorArray bufferRef2(width * height / 4, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f)); |
| CColorArray bufferRef3(width * height / 4, tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f)); |
| CColorArray bufferRef4(width * height / 4, tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)); |
| CColorArray bufferTest(width * height / 4, tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, width / 2, height / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef1, width / 2, height / 2)) |
| << "Region 0 verification failed"; |
| |
| ReadPixelsFloat<api>((width + 1) / 2, 0, width / 2, height / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef2, width / 2, height / 2)) |
| << "Region 1 verification failed"; |
| |
| ReadPixelsFloat<api>(0, (height + 1) / 2, width / 2, height / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef3, width / 2, height / 2)) |
| << "Region 2 verification failed"; |
| |
| ReadPixelsFloat<api>((width + 1) / 2, (height + 1) / 2, width / 2, height / 2, &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef4, width / 2, height / 2)) |
| << "Region 3 verification failed"; |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(1); |
| glDisableVertexAttribArray(0); |
| glDeleteProgram(_program); |
| glDeleteProgram(_programCompute); |
| glDeleteVertexArrays(1, &_vao); |
| if (_ebo) |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferCoords); |
| glDeleteBuffers(1, &_bufferColors); |
| glDeleteBuffers(1, &_bufferIndirect); |
| glViewport(0, 0, getWindowWidth(), getWindowHeight()); |
| return NO_ERROR; |
| } |
| CComputeBase(TDrawFunction drawFunc) |
| : _drawFunc(drawFunc) |
| , _program(0) |
| , _programCompute(0) |
| , _vao(0) |
| , _ebo(0) |
| , _bufferCoords(0) |
| , _bufferColors(0) |
| , _bufferIndirect(0) |
| { |
| } |
| |
| private: |
| CComputeBase(); |
| TDrawFunction _drawFunc; |
| |
| template <typename api> |
| std::string Vsh() |
| { |
| return api::glslVer() + NL "in vec4 in_coords;" NL "in vec4 in_colors;" NL "out vec4 colors;" NL |
| "void main() {" NL " colors = in_colors;" NL " gl_Position = in_coords;" NL |
| "#if defined(GL_ES)" NL " gl_PointSize = 1.0;" NL "#endif" NL "}"; |
| } |
| |
| template <typename api> |
| std::string Fsh() |
| { |
| return api::glslVer() + NL "precision highp float;" NL "in vec4 colors;" NL "out vec4 outColor;" NL |
| "void main() {" NL " outColor = colors;" NL "}"; |
| } |
| |
| template <typename api> |
| std::string Csh() |
| { |
| return api::glslVer(true) + NL "precision highp int; " NL |
| "precision highp float; " NL |
| " " NL |
| "layout(local_size_x = 1) in; " NL |
| "layout(std430, binding = 0) buffer Vertices { " NL |
| " vec4 vertices[]; " NL |
| "}; " NL |
| "layout(std430, binding = 1) buffer Colors { " NL |
| " vec4 colors[]; " NL |
| "}; " NL |
| "layout(std430, binding = 2) buffer Indirect { " NL |
| " uint indirect[4]; " NL |
| "}; " NL |
| " " NL |
| "uniform uint height; " NL |
| "uniform uint width; " NL |
| " " NL |
| "void main() { " NL |
| " uint w = gl_GlobalInvocationID.x; " NL |
| " uint h = gl_GlobalInvocationID.y; " NL |
| " float stepX = 2.0 / float(width); " NL |
| " float stepY = 2.0 / float(height); " NL |
| " float offsetX = -1.0 + stepX * float(w) + stepX / 2.0; " NL |
| " float offsetY = -1.0 + stepY * float(h) + stepY / 2.0; " NL |
| " uint arrayOffset = h * width + w; " NL |
| " vertices[ arrayOffset ] = vec4(offsetX, offsetY, 0.0, 1.0);" NL |
| " vec4 color = vec4(0.0, 0.0, 0.0, 1.0); " NL |
| " if(w > (width / 2u - 1u)) { " NL |
| " color = color + vec4(0.5, 0.0, 0.0, 0.0); " NL |
| " } " NL |
| " if(h > (height / 2u - 1u)) { " NL |
| " color = color + vec4(0.0, 0.5, 0.0, 0.0); " NL |
| " } " NL |
| " colors[ arrayOffset ] = color; " NL |
| " if(w == 0u && h == 0u) { " NL |
| " indirect[0] = width * height; " NL |
| " indirect[1] = 1u; " NL |
| " } " NL |
| "} "; |
| } |
| |
| GLuint _program, _programCompute; |
| GLuint _vao; |
| GLuint _ebo; |
| GLuint _bufferCoords; |
| GLuint _bufferColors; |
| GLuint _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CComputeShaderArray : public CComputeBase |
| { |
| virtual std::string Title() |
| { |
| return "Compute Shader: glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that data created by Compute Shader can be used as an input to glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create data by Compute Shader" NL "2. Use data as input to glDrawArrayIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CComputeShaderArray() : CComputeBase(DRAW_ARRAYS) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CComputeBase::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| struct CComputeShaderElements : public CComputeBase |
| { |
| virtual std::string Title() |
| { |
| return "Compute Shader: glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that data created by Compute Shader can be used as an input to glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create data by Compute Shader" NL "2. Use data as input to glDrawElementsIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| CComputeShaderElements() : CComputeBase(DRAW_ELEMENTS) |
| { |
| } |
| |
| virtual long Run() |
| { |
| return CComputeBase::Run<api>(); |
| } |
| }; |
| |
| template <typename api> |
| class CPrimitiveRestartElements : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Primitive restart - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that primitive restart works correctly with glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Define primitives using VBO" NL "2. Draw primitives using glDrawElementsIndirect" NL |
| "3. Verify results"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if no OpenGL errors reported"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| int PrimitiveRestartIndex(); |
| |
| void EnablePrimitiveRestart(); |
| |
| void DisablePrimitiveRestart(); |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords1; |
| TriangleStipGen(coords1, -1.0f, 1.0f, -1.0, -0.5, 2); |
| |
| CColorArray coords2; |
| TriangleStipGen(coords2, -1.0f, 1.0f, 0.5, 1.0, 4); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords1.size() + coords2.size()) * sizeof(coords1[0]), NULL, |
| GL_STREAM_DRAW); |
| glBufferSubData(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(coords1.size() * sizeof(coords1[0])), &coords1[0]); |
| glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)(coords1.size() * sizeof(coords1[0])), |
| (GLsizeiptr)(coords2.size() * sizeof(coords2[0])), &coords2[0]); |
| glVertexAttribPointer(0, sizeof(coords1[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords1[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords1.size() + coords2.size() + 1); |
| indirectElements.primCount = static_cast<GLuint>((coords1.size() + coords2.size()) / 2); |
| |
| CElementArray elements; |
| for (size_t i = 0; i < coords1.size(); ++i) |
| { |
| elements.push_back(static_cast<GLuint>(i)); |
| } |
| |
| elements.push_back(PrimitiveRestartIndex()); |
| for (size_t i = 0; i < coords2.size(); ++i) |
| { |
| elements.push_back(static_cast<GLuint>(coords1.size() + i)); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| EnablePrimitiveRestart(); |
| |
| glDrawElementsIndirect(GL_TRIANGLE_STRIP, GL_UNSIGNED_INT, 0); |
| |
| CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 4, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f)); |
| CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f)); |
| CColorArray bufferTest1(getWindowWidth() * getWindowHeight() / 4, tcu::Vec4(0.0f)); |
| CColorArray bufferTest2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f)); |
| |
| DIResult result; |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 4, &bufferTest1[0]); |
| result.sub_result(BuffersCompare(bufferTest1, getWindowWidth(), getWindowHeight() / 4, bufferRef1, |
| getWindowWidth(), getWindowHeight() / 4)); |
| // height = 2 * (getWindowHeight() / 4) to avoid border pixels |
| // in case the height is not a multiple of 4. |
| ReadPixelsFloat<api>(0, (getWindowHeight() + 3) / 4, getWindowWidth(), 2 * (getWindowHeight() / 4), &bufferTest2[0]); |
| result.sub_result(BuffersCompare(bufferTest2, getWindowWidth(), getWindowHeight() / 2, bufferRef2, |
| getWindowWidth(), 2 *(getWindowHeight() / 4))); |
| |
| ReadPixelsFloat<api>(0, (getWindowHeight() * 3 + 3) / 4, getWindowWidth(), getWindowHeight() / 4, |
| &bufferTest1[0]); |
| result.sub_result(BuffersCompare(bufferTest1, getWindowWidth(), getWindowHeight() / 4, bufferRef1, |
| getWindowWidth(), getWindowHeight() / 4)); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| |
| DisablePrimitiveRestart(); |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| void TriangleStipGen(CColorArray& coords, float widthStart, float widthEnd, float heightStart, float heightEnd, |
| unsigned int primNum) |
| { |
| float widthStep = (widthEnd - widthStart) / static_cast<float>(primNum); |
| float heightStep = (heightEnd - heightStart) / static_cast<float>(primNum); |
| for (unsigned int i = 0; i < primNum; ++i) |
| { |
| float heightOffset = heightStart + heightStep * static_cast<float>(i); |
| for (unsigned int j = 0; j < primNum; ++j) |
| { |
| float widthOffset = widthStart + widthStep * static_cast<float>(j); |
| |
| coords.push_back(tcu::Vec4(widthOffset, heightOffset, 0.0f, 1.0f)); |
| coords.push_back(tcu::Vec4(widthOffset, heightOffset + heightStep, 0.0f, 1.0f)); |
| coords.push_back(tcu::Vec4(widthOffset + widthStep, heightOffset, 0.0f, 1.0f)); |
| coords.push_back(tcu::Vec4(widthOffset + widthStep, heightOffset + heightStep, 0.0f, 1.0f)); |
| } |
| } |
| } |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <> |
| int CPrimitiveRestartElements<test_api::ES3>::PrimitiveRestartIndex() |
| { |
| return 0xffffffff; |
| } |
| |
| template <> |
| int CPrimitiveRestartElements<test_api::GL>::PrimitiveRestartIndex() |
| { |
| return 3432432; |
| } |
| |
| template <> |
| void CPrimitiveRestartElements<test_api::ES3>::DisablePrimitiveRestart() |
| { |
| glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX); |
| } |
| |
| template <> |
| void CPrimitiveRestartElements<test_api::GL>::DisablePrimitiveRestart() |
| { |
| glDisable(GL_PRIMITIVE_RESTART); |
| } |
| |
| template <> |
| void CPrimitiveRestartElements<test_api::ES3>::EnablePrimitiveRestart() |
| { |
| glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); |
| } |
| |
| template <> |
| void CPrimitiveRestartElements<test_api::GL>::EnablePrimitiveRestart() |
| { |
| glPrimitiveRestartIndex(PrimitiveRestartIndex()); |
| glEnable(GL_PRIMITIVE_RESTART); |
| } |
| |
| template <typename api> |
| struct CNegativeZeroBufferArray : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: no indirect buffer/parameter - glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call glDrawArrayIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| DIResult result; |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer; |
| }; |
| |
| template <typename api> |
| struct CNegativeZeroBufferElements : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: no indirect buffer/parameter - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call glDrawElementsIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| |
| DIResult result; |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo; |
| }; |
| |
| template <typename api> |
| struct CNegativeInvalidModeArray : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: invalid mode - glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Set invalid mode to glDrawArrayIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| glDrawArraysIndirect(GL_FLOAT, 0); |
| |
| DIResult result; |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_FLOAT as mode"; |
| } |
| |
| glDrawArraysIndirect(GL_STATIC_DRAW, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_STATIC_DRAW as mode"; |
| } |
| |
| glDrawArraysIndirect(GL_DRAW_INDIRECT_BUFFER, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_DRAW_INDIRECT_BUFFER as mode"; |
| } |
| |
| glDrawArraysIndirect(GL_INVALID_ENUM, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_ENUM as mode"; |
| } |
| |
| glDrawArraysIndirect(GL_COLOR_BUFFER_BIT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_COLOR_BUFFER_BIT as mode"; |
| } |
| |
| glDrawArraysIndirect(GL_ARRAY_BUFFER, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_ARRAY_BUFFER as mode"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeInvalidModeElements : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: invalid mode - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Set invalid mode to glDrawElemenetsIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| glDrawElementsIndirect(GL_INVALID_ENUM, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_FLOAT as mode"; |
| } |
| |
| glDrawElementsIndirect(GL_UNSIGNED_INT, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_UNSIGNED_INT as mode"; |
| } |
| |
| glDrawElementsIndirect(GL_ELEMENT_ARRAY_BUFFER, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_ELEMENT_ARRAY_BUFFER as mode"; |
| } |
| |
| glDrawElementsIndirect(GL_FASTEST, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_FASTEST as mode"; |
| } |
| |
| glDrawElementsIndirect(GL_PACK_ALIGNMENT, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_PACK_ALIGNMENT as mode"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeNoVAOArrays : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: no VAO - glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Use glDrawArraysIndirect with default VAO"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| DIResult result; |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| if (glu::isContextTypeES(m_context.getRenderContext().getType())) |
| glDisableVertexAttribArray(0); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| |
| if (glu::isContextTypeES(m_context.getRenderContext().getType())) |
| glDisableVertexAttribArray(0); |
| |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeNoVAOElements : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: no VAO - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Use glDrawElemenetsIndirect with default VAO"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| if (glu::isContextTypeES(m_context.getRenderContext().getType())) |
| glDisableVertexAttribArray(0); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeNoVBOArrays : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: no VBO - glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Use glDrawArraysIndirect with enabled vertex array, that has no VBO bound"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| DIResult result; |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| glDisableVertexAttribArray(0); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeNoVBOElements : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: no VBO - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Use glDrawElementsIndirect with enabled vertex array, that has no VBO bound"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| |
| api::ES_Only(); |
| |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| glEnableVertexAttribArray(0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| glDisableVertexAttribArray(0); |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeBufferMappedArray : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: buffer mapped - glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and bind buffer" NL "2. Map buffer" NL "3. Call glDrawArrayIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| DIResult result; |
| void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawArraysIndirectCommand), GL_MAP_READ_BIT); |
| if (buf == 0) |
| { |
| result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_MAP_READ_BIT) returned NULL"; |
| } |
| |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| |
| GLenum error = glGetError(); |
| if (error == GL_INVALID_OPERATION) |
| { |
| //GL error: nothing is rendered |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, |
| getWindowWidth(), getWindowHeight())); |
| } |
| else if (error == GL_NO_ERROR) |
| { |
| //No GL error: undefined |
| } |
| else |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| if (buf) |
| { |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) != GL_TRUE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| } |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeBufferMappedElements : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: buffer mapped - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Create and bind buffer" NL "2. Map buffer" NL "3. Call glDrawElementsIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT); |
| if (buf == 0) |
| { |
| result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| |
| GLenum error = glGetError(); |
| if (error == GL_INVALID_OPERATION) |
| { |
| //GL error: nothing is rendered |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, |
| getWindowWidth(), getWindowHeight())); |
| } |
| else if (error == GL_NO_ERROR) |
| { |
| //No GL error: undefined |
| } |
| else |
| { |
| result.error() << "Invalid error code returned by a driver"; |
| } |
| |
| if (buf) |
| { |
| if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) != GL_TRUE) |
| { |
| result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE"; |
| } |
| buf = 0; |
| } |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeDataWrongElements : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: invalid type - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Bind non-zero buffer" NL "2. Call glDrawElementsIndirect with invalid type"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_FLOAT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_FLOAT type"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_INT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INT type"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_STATIC_DRAW, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_STATIC_DRAW type"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_SHORT, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_SHORT type"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_BYTE, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_BYTE type"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_DOUBLE, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_DOUBLE type"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_INVALID_ENUM, 0); |
| if (glGetError() != GL_INVALID_ENUM) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_ENUM type"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| class CNegativeGshArray : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Negative: incompatible the input primitive type of gsh - glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Bind non-zero buffer" NL "2. Set data" NL "3. Set wrong geometry shader" NL |
| "4. Call glDrawArrayIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(Vsh(), Gsh(), Fsh(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| indirectArrays.first = 0; |
| indirectArrays.reservedMustBeZero = 0; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| glDrawArraysIndirect(GL_POINTS, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| std::string Vsh() |
| { |
| return "#version 150" NL "in vec4 coords;" NL "void main() {" NL " gl_Position = coords;" NL "}"; |
| } |
| |
| std::string Gsh() |
| { |
| return "#version 150" NL "layout(triangles) in;" NL "layout(triangle_strip, max_vertices = 10) out;" NL |
| "void main() {" NL " for (int i=0; i<gl_in.length(); ++i) {" NL |
| " gl_Position = gl_in[i].gl_Position;" NL " EmitVertex();" NL " }" NL "}"; |
| } |
| |
| std::string Fsh() |
| { |
| return "#version 140" NL "out vec4 outColor;" NL "void main() {" NL |
| " outColor = vec4(0.1f, 0.2f, 0.3f, 1.0f);" NL "}"; |
| } |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| class CNegativeGshElements : public DrawIndirectBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return "Negative: incompatible the input primitive type of gsh - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "1. Bind non-zero buffer" NL "2. Set data" NL "3. Set wrong geometry shader" NL |
| "4. Call glDrawElementsIndirect"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(Vsh(), Gsh(), Fsh(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| std::string Vsh() |
| { |
| return "#version 150" NL "in vec4 coords;" NL "void main() {" NL " gl_Position = coords;" NL "}"; |
| } |
| |
| std::string Gsh() |
| { |
| return "#version 150" NL "layout(lines) in;" NL "layout(line_strip, max_vertices = 10) out;" NL |
| "void main() {" NL " for (int i=0; i<gl_in.length(); ++i) {" NL |
| " gl_Position = gl_in[i].gl_Position;" NL " EmitVertex();" NL " }" NL "}"; |
| } |
| |
| std::string Fsh() |
| { |
| return "#version 140" NL "out vec4 outColor;" NL "void main() {" NL |
| " outColor = vec4(0.1f, 0.2f, 0.3f, 1.0f);" NL "}"; |
| } |
| int _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeInvalidSizeArrays : public DrawIndirectBase |
| { |
| struct TWrongStructure1 |
| { |
| GLuint count; |
| GLuint primCount; |
| }; |
| |
| struct TWrongStructure2 |
| { |
| GLfloat count; |
| GLuint primCount; |
| }; |
| |
| virtual std::string Title() |
| { |
| return "Negative: wrong structure - glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call glDrawArrayIndirect with wrong structure"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| TWrongStructure1 indirectArrays = { 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(TWrongStructure1), &indirectArrays, GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| glDeleteBuffers(1, &_bufferIndirect); |
| |
| TWrongStructure2 indirectArrays2 = { 0, 0 }; |
| indirectArrays2.count = static_cast<GLfloat>(coords.size()); |
| indirectArrays2.primCount = 1; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(TWrongStructure2), &indirectArrays2, GL_STATIC_DRAW); |
| |
| glDrawArraysIndirect(GL_TRIANGLES, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeInvalidSizeElements : public DrawIndirectBase |
| { |
| struct TWrongStructure |
| { |
| GLfloat count; |
| GLuint primCount; |
| }; |
| |
| virtual std::string Title() |
| { |
| return "Negative: wrong structure - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call glDrawElementsIndirect with wrong structure"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectElements = { 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| TWrongStructure indirectElements2 = { 0, 0 }; |
| indirectElements2.count = static_cast<GLfloat>(coords.size()); |
| indirectElements2.primCount = 1; |
| |
| glDeleteBuffers(1, &_bufferIndirect); |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(TWrongStructure), &indirectElements2, GL_STATIC_DRAW); |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeStructureWrongOffsetArray : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: wrong offset - glDrawArrayIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call glDrawArrayIndirect with wrong offset"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 }; |
| indirectArrays.count = static_cast<GLuint>(coords.size()); |
| indirectArrays.primCount = 1; |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| glDrawArraysIndirect(GL_TRIANGLES, (void*)(sizeof(DrawArraysIndirectCommand) * 2)); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| glDrawArraysIndirect(GL_TRIANGLES, (void*)(sizeof(GLuint))); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeStructureWrongOffsetElements : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: wrong offset - glDrawElementsIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call glDrawElementsIndirect with wrong structure"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Setup() |
| { |
| glClear(GL_COLOR_BUFFER_BIT); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| CColorArray coords; |
| PrimitiveGen(GL_TRIANGLES, 8, 8, coords); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| |
| glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0); |
| glEnableVertexAttribArray(0); |
| |
| DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 }; |
| indirectElements.count = static_cast<GLuint>(coords.size()); |
| indirectElements.primCount = 1; |
| |
| CElementArray elements(coords.size(), 0); |
| for (size_t i = 0; i < elements.size(); ++i) |
| { |
| elements[i] = static_cast<GLuint>(i); |
| } |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0], |
| GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (void*)(sizeof(DrawElementsIndirectCommand) * 2)); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (void*)(sizeof(GLuint))); |
| if (glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| |
| CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f)); |
| CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f)); |
| |
| ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]); |
| result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(), |
| getWindowHeight())); |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeUnalignedOffset : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: unaligned offset - glDrawElementsIndirect and glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no system/driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call with unaligned offset (1, 3, 1023)"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Run() |
| { |
| _program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true); |
| if (!_program) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| std::vector<GLuint> zarro(4096, 0); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| glBufferData(GL_ARRAY_BUFFER, 4096, &zarro[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); |
| glEnableVertexAttribArray(0); |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW); |
| |
| DIResult result; |
| |
| int offsets[] = { 1, 3, 1023 }; |
| for (size_t i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) |
| { |
| glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, reinterpret_cast<void*>((deUintptr)offsets[i])); |
| if (glGetError() != GL_INVALID_VALUE) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_VALUE type"; |
| } |
| glDrawArraysIndirect(GL_TRIANGLES, reinterpret_cast<void*>((deUintptr)offsets[i])); |
| if (glGetError() != GL_INVALID_VALUE) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_VALUE type"; |
| } |
| } |
| |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| return NO_ERROR; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect; |
| }; |
| |
| template <typename api> |
| struct CNegativeXFB : public DrawIndirectBase |
| { |
| virtual std::string Title() |
| { |
| return "Negative: transform feedback active and not paused - glDrawElementsIndirect and glDrawArraysIndirect"; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return "Verify that a driver sets error and no system/driver crash occurred"; |
| } |
| |
| virtual std::string Method() |
| { |
| return "Call with transform feedback active"; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return "The test will pass if OpenGL errors reported and no driver crash occurred"; |
| } |
| |
| virtual long Run() |
| { |
| api::ES_Only(); |
| |
| bool drawWithXFBAllowed = m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"); |
| |
| _program = CreateProgram(Vsh(), "", shaders::fshSimple<api>(), false); |
| const GLchar* varyings[] = { "dataOut" }; |
| glTransformFeedbackVaryings(_program, 1, varyings, GL_INTERLEAVED_ATTRIBS); |
| glLinkProgram(_program); |
| if (!CheckProgram(_program)) |
| { |
| return ERROR; |
| } |
| glUseProgram(_program); |
| |
| glGenVertexArrays(1, &_vao); |
| glBindVertexArray(_vao); |
| |
| std::vector<GLuint> zarro(4096, 0); |
| |
| glGenBuffers(1, &_buffer); |
| glBindBuffer(GL_ARRAY_BUFFER, _buffer); |
| glBufferData(GL_ARRAY_BUFFER, 4096, &zarro[0], GL_STREAM_DRAW); |
| glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); |
| glEnableVertexAttribArray(0); |
| |
| glGenBuffers(1, &_bufferIndirect); |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect); |
| glBufferData(GL_DRAW_INDIRECT_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW); |
| |
| glGenBuffers(1, &_xfb); |
| glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _xfb); |
| glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _xfb); |
| |
| DIResult result; |
| |
| //Without XFO |
| glBeginTransformFeedback(GL_POINTS); |
| |
| glDrawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, NULL); |
| if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| glDrawArraysIndirect(GL_POINTS, NULL); |
| if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| glEndTransformFeedback(); |
| |
| //With XFO |
| glGenTransformFeedbacks(1, &_xfo); |
| glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, _xfo); |
| glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _xfb); |
| glBeginTransformFeedback(GL_POINTS); |
| glPauseTransformFeedback(); |
| glResumeTransformFeedback(); |
| |
| glDrawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, NULL); |
| if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| glDrawArraysIndirect(GL_POINTS, NULL); |
| if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION) |
| { |
| result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type"; |
| } |
| glEndTransformFeedback(); |
| |
| glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); |
| return result.code(); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDisableVertexAttribArray(0); |
| glUseProgram(0); |
| glDeleteProgram(_program); |
| glDeleteVertexArrays(1, &_vao); |
| glDeleteBuffers(1, &_buffer); |
| glDeleteBuffers(1, &_ebo); |
| glDeleteBuffers(1, &_bufferIndirect); |
| glDeleteBuffers(1, &_xfb); |
| glDeleteTransformFeedbacks(1, &_xfo); |
| return NO_ERROR; |
| } |
| |
| std::string Vsh() |
| { |
| return api::glslVer() + NL "out highp vec4 dataOut;" NL "in vec4 i_vertex;" NL "void main() {" NL |
| " dataOut = i_vertex;" NL " gl_Position = i_vertex;" NL "}"; |
| } |
| |
| private: |
| GLuint _program; |
| GLuint _vao, _buffer, _ebo, _bufferIndirect, _xfo, _xfb; |
| }; |
| |
| } // namespace |
| DrawIndirectTestsGL40::DrawIndirectTestsGL40(glcts::Context& context) : TestCaseGroup(context, "draw_indirect", "") |
| { |
| } |
| |
| DrawIndirectTestsGL40::~DrawIndirectTestsGL40(void) |
| { |
| } |
| |
| void DrawIndirectTestsGL40::init() |
| { |
| using namespace glcts; |
| |
| DILogger::setOutput(m_context.getTestContext().getLog()); |
| |
| addChild( |
| new TestSubcase(m_context, "basic-binding-default", TestSubcase::Create<CDefaultBindingPoint<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-binding-zero", TestSubcase::Create<CZeroBindingPoint<test_api::GL> >)); |
| addChild( |
| new TestSubcase(m_context, "basic-binding-single", TestSubcase::Create<CSingleBindingPoint<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-binding-multi", TestSubcase::Create<CMultiBindingPoint<test_api::GL> >)); |
| addChild( |
| new TestSubcase(m_context, "basic-binding-delete", TestSubcase::Create<CDeleteBindingPoint<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-buffer-data", TestSubcase::Create<CBufferData<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-subData", TestSubcase::Create<CBufferSubData<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-unMap", TestSubcase::Create<CBufferMap<test_api::GL> >)); |
| addChild( |
| new TestSubcase(m_context, "basic-buffer-getPointerv", TestSubcase::Create<CBufferGetPointerv<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-mapRange", TestSubcase::Create<CBufferMapRange<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-flushMappedRange", |
| TestSubcase::Create<CBufferFlushMappedRange<test_api::GL> >)); |
| addChild( |
| new TestSubcase(m_context, "basic-buffer-copySubData", TestSubcase::Create<CBufferCopySubData<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-drawArrays-singlePrimitive", |
| TestSubcase::Create<CVBODrawArraysSingle<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-manyPrimitives", |
| TestSubcase::Create<CVBODrawArraysMany<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-instancing", |
| TestSubcase::Create<CVBODrawArraysInstancing<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-xfbPaused", |
| TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-singlePrimitive", |
| TestSubcase::Create<CVBODrawElementsSingle<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-manyPrimitives", |
| TestSubcase::Create<CVBODrawElementsMany<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-instancing", |
| TestSubcase::Create<CVBODrawElementsInstancing<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-xfbPaused", |
| TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-drawArrays-simple", |
| TestSubcase::Create<CBufferIndirectDrawArraysSimple<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-noFirst", |
| TestSubcase::Create<CBufferIndirectDrawArraysNoFirst<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-bufferOffset", |
| TestSubcase::Create<CBufferIndirectDrawArraysOffset<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-vertexIds", |
| TestSubcase::Create<CBufferIndirectDrawArraysVertexIds<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-simple", |
| TestSubcase::Create<CBufferIndirectDrawElementsSimple<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-noFirstIndex", |
| TestSubcase::Create<CBufferIndirectDrawElementsNoFirstIndex<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-basevertex", |
| TestSubcase::Create<CBufferIndirectDrawElementsNoBasevertex<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-bufferOffset", |
| TestSubcase::Create<CBufferIndirectDrawElementsOffset<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-vertexIds", |
| TestSubcase::Create<CBufferIndirectDrawElementsVertexIds<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_short", |
| TestSubcase::Create<CIndicesDataTypeUnsignedShort<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_byte", |
| TestSubcase::Create<CIndicesDataTypeUnsignedByte<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-points", |
| TestSubcase::Create<CModeDrawArraysPoints<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines", |
| TestSubcase::Create<CModeDrawArraysLines<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip", |
| TestSubcase::Create<CModeDrawArraysLineStrip<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_loop", |
| TestSubcase::Create<CModeDrawArraysLineLoop<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip", |
| TestSubcase::Create<CModeDrawArraysTriangleStrip<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_fan", |
| TestSubcase::Create<CModeDrawArraysTriangleFan<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines_adjacency", |
| TestSubcase::Create<CModeDrawArraysLinesAdjacency<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip_adjacency", |
| TestSubcase::Create<CModeDrawArraysLineStripAdjacency<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangles_adjacency", |
| TestSubcase::Create<CModeDrawArraysTrianglesAdjacency<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip_adjacency", |
| TestSubcase::Create<CModeDrawArraysTriangleStripAdjacency<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-points", |
| TestSubcase::Create<CModeDrawElementsPoints<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines", |
| TestSubcase::Create<CModeDrawElementsLines<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip", |
| TestSubcase::Create<CModeDrawElementsLineStrip<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_loop", |
| TestSubcase::Create<CModeDrawElementsLineLoop<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip", |
| TestSubcase::Create<CModeDrawElementsTriangleStrip<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_fan", |
| TestSubcase::Create<CModeDrawElementsTriangleFan<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines_adjacency", |
| TestSubcase::Create<CModeDrawElementsLinesAdjacency<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip_adjacency", |
| TestSubcase::Create<CModeDrawElementsLineStripAdjacency<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangles_adjacency", |
| TestSubcase::Create<CModeDrawElementsTrianglesAdjacency<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip_adjacency", |
| TestSubcase::Create<CModeDrawElementsTriangleStripAdjacency<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-arrays", |
| TestSubcase::Create<CTransformFeedbackArray<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-elements", |
| TestSubcase::Create<CTransformFeedbackElements<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "advanced-primitiveRestart-elements", |
| TestSubcase::Create<CPrimitiveRestartElements<test_api::GL> >)); |
| |
| addChild(new TestSubcase(m_context, "negative-noindirect-arrays", |
| TestSubcase::Create<CNegativeZeroBufferArray<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-noindirect-elements", |
| TestSubcase::Create<CNegativeZeroBufferElements<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidMode-arrays", |
| TestSubcase::Create<CNegativeInvalidModeArray<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidMode-elements", |
| TestSubcase::Create<CNegativeInvalidModeElements<test_api::GL> >)); |
| addChild( |
| new TestSubcase(m_context, "negative-noVAO-arrays", TestSubcase::Create<CNegativeNoVAOArrays<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-noVAO-elements", |
| TestSubcase::Create<CNegativeNoVAOElements<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-bufferMapped-arrays", |
| TestSubcase::Create<CNegativeBufferMappedArray<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-bufferMapped-elements", |
| TestSubcase::Create<CNegativeBufferMappedElements<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidType-elements", |
| TestSubcase::Create<CNegativeDataWrongElements<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-gshIncompatible-arrays", |
| TestSubcase::Create<CNegativeGshArray<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-gshIncompatible-elements", |
| TestSubcase::Create<CNegativeGshElements<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-wrongOffset-arrays", |
| TestSubcase::Create<CNegativeStructureWrongOffsetArray<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-wrongOffset-elements", |
| TestSubcase::Create<CNegativeStructureWrongOffsetElements<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidSize-arrays", |
| TestSubcase::Create<CNegativeInvalidSizeArrays<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidSize-elements", |
| TestSubcase::Create<CNegativeInvalidSizeElements<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "negative-unalignedOffset", |
| TestSubcase::Create<CNegativeUnalignedOffset<test_api::GL> >)); |
| } |
| |
| DrawIndirectTestsGL43::DrawIndirectTestsGL43(glcts::Context& context) : TestCaseGroup(context, "draw_indirect_43", "") |
| { |
| } |
| |
| DrawIndirectTestsGL43::~DrawIndirectTestsGL43(void) |
| { |
| } |
| |
| void DrawIndirectTestsGL43::init() |
| { |
| using namespace glcts; |
| |
| DILogger::setOutput(m_context.getTestContext().getLog()); |
| addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-arrays", |
| TestSubcase::Create<CComputeShaderArray<test_api::GL> >)); |
| addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-elements", |
| TestSubcase::Create<CComputeShaderElements<test_api::GL> >)); |
| } |
| |
| DrawIndirectTestsES31::DrawIndirectTestsES31(glcts::Context& context) : TestCaseGroup(context, "draw_indirect", "") |
| { |
| } |
| |
| DrawIndirectTestsES31::~DrawIndirectTestsES31(void) |
| { |
| } |
| |
| void DrawIndirectTestsES31::init() |
| { |
| using namespace glcts; |
| |
| DILogger::setOutput(m_context.getTestContext().getLog()); |
| |
| addChild( |
| new TestSubcase(m_context, "basic-binding-default", TestSubcase::Create<CDefaultBindingPoint<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-binding-zero", TestSubcase::Create<CZeroBindingPoint<test_api::ES3> >)); |
| addChild( |
| new TestSubcase(m_context, "basic-binding-single", TestSubcase::Create<CSingleBindingPoint<test_api::ES3> >)); |
| addChild( |
| new TestSubcase(m_context, "basic-binding-multi", TestSubcase::Create<CMultiBindingPoint<test_api::ES3> >)); |
| addChild( |
| new TestSubcase(m_context, "basic-binding-delete", TestSubcase::Create<CDeleteBindingPoint<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-buffer-data", TestSubcase::Create<CBufferData<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-subData", TestSubcase::Create<CBufferSubData<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-getPointerv", |
| TestSubcase::Create<CBufferGetPointerv<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-mapRange", TestSubcase::Create<CBufferMapRange<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-flushMappedRange", |
| TestSubcase::Create<CBufferFlushMappedRange<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-buffer-copySubData", |
| TestSubcase::Create<CBufferCopySubData<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-drawArrays-singlePrimitive", |
| TestSubcase::Create<CVBODrawArraysSingle<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-manyPrimitives", |
| TestSubcase::Create<CVBODrawArraysMany<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-instancing", |
| TestSubcase::Create<CVBODrawArraysInstancing<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-xfbPaused", |
| TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-singlePrimitive", |
| TestSubcase::Create<CVBODrawElementsSingle<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-manyPrimitives", |
| TestSubcase::Create<CVBODrawElementsMany<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-instancing", |
| TestSubcase::Create<CVBODrawElementsInstancing<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-xfbPaused", |
| TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-drawArrays-simple", |
| TestSubcase::Create<CBufferIndirectDrawArraysSimple<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-noFirst", |
| TestSubcase::Create<CBufferIndirectDrawArraysNoFirst<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-bufferOffset", |
| TestSubcase::Create<CBufferIndirectDrawArraysOffset<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawArrays-vertexIds", |
| TestSubcase::Create<CBufferIndirectDrawArraysVertexIds<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-simple", |
| TestSubcase::Create<CBufferIndirectDrawElementsSimple<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-noFirstIndex", |
| TestSubcase::Create<CBufferIndirectDrawElementsNoFirstIndex<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-basevertex", |
| TestSubcase::Create<CBufferIndirectDrawElementsNoBasevertex<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-bufferOffset", |
| TestSubcase::Create<CBufferIndirectDrawElementsOffset<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-drawElements-vertexIds", |
| TestSubcase::Create<CBufferIndirectDrawElementsVertexIds<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_short", |
| TestSubcase::Create<CIndicesDataTypeUnsignedShort<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_byte", |
| TestSubcase::Create<CIndicesDataTypeUnsignedByte<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-points", |
| TestSubcase::Create<CModeDrawArraysPoints<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines", |
| TestSubcase::Create<CModeDrawArraysLines<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip", |
| TestSubcase::Create<CModeDrawArraysLineStrip<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_loop", |
| TestSubcase::Create<CModeDrawArraysLineLoop<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip", |
| TestSubcase::Create<CModeDrawArraysTriangleStrip<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_fan", |
| TestSubcase::Create<CModeDrawArraysTriangleFan<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines_adjacency", |
| TestSubcase::Create<CModeDrawArraysLinesAdjacency<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip_adjacency", |
| TestSubcase::Create<CModeDrawArraysLineStripAdjacency<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangles_adjacency", |
| TestSubcase::Create<CModeDrawArraysTrianglesAdjacency<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip_adjacency", |
| TestSubcase::Create<CModeDrawArraysTriangleStripAdjacency<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-points", |
| TestSubcase::Create<CModeDrawElementsPoints<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines", |
| TestSubcase::Create<CModeDrawElementsLines<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip", |
| TestSubcase::Create<CModeDrawElementsLineStrip<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_loop", |
| TestSubcase::Create<CModeDrawElementsLineLoop<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip", |
| TestSubcase::Create<CModeDrawElementsTriangleStrip<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_fan", |
| TestSubcase::Create<CModeDrawElementsTriangleFan<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines_adjacency", |
| TestSubcase::Create<CModeDrawElementsLinesAdjacency<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip_adjacency", |
| TestSubcase::Create<CModeDrawElementsLineStripAdjacency<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangles_adjacency", |
| TestSubcase::Create<CModeDrawElementsTrianglesAdjacency<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip_adjacency", |
| TestSubcase::Create<CModeDrawElementsTriangleStripAdjacency<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-arrays", |
| TestSubcase::Create<CTransformFeedbackArray<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-elements", |
| TestSubcase::Create<CTransformFeedbackElements<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-arrays", |
| TestSubcase::Create<CComputeShaderArray<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-elements", |
| TestSubcase::Create<CComputeShaderElements<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "advanced-primitiveRestart-elements", |
| TestSubcase::Create<CPrimitiveRestartElements<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "negative-noindirect-arrays", |
| TestSubcase::Create<CNegativeZeroBufferArray<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-noindirect-elements", |
| TestSubcase::Create<CNegativeZeroBufferElements<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidMode-arrays", |
| TestSubcase::Create<CNegativeInvalidModeArray<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidMode-elements", |
| TestSubcase::Create<CNegativeInvalidModeElements<test_api::ES3> >)); |
| addChild( |
| new TestSubcase(m_context, "negative-noVAO-arrays", TestSubcase::Create<CNegativeNoVAOArrays<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-noVAO-elements", |
| TestSubcase::Create<CNegativeNoVAOElements<test_api::ES3> >)); |
| addChild( |
| new TestSubcase(m_context, "negative-noVBO-arrays", TestSubcase::Create<CNegativeNoVBOArrays<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-noVBO-elements", |
| TestSubcase::Create<CNegativeNoVBOElements<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-bufferMapped-arrays", |
| TestSubcase::Create<CNegativeBufferMappedArray<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-bufferMapped-elements", |
| TestSubcase::Create<CNegativeBufferMappedElements<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidType-elements", |
| TestSubcase::Create<CNegativeDataWrongElements<test_api::ES3> >)); |
| |
| addChild(new TestSubcase(m_context, "negative-wrongOffset-arrays", |
| TestSubcase::Create<CNegativeStructureWrongOffsetArray<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-wrongOffset-elements", |
| TestSubcase::Create<CNegativeStructureWrongOffsetElements<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidSize-arrays", |
| TestSubcase::Create<CNegativeInvalidSizeArrays<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-invalidSize-elements", |
| TestSubcase::Create<CNegativeInvalidSizeElements<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-unalignedOffset", |
| TestSubcase::Create<CNegativeUnalignedOffset<test_api::ES3> >)); |
| addChild(new TestSubcase(m_context, "negative-xfb", TestSubcase::Create<CNegativeXFB<test_api::ES3> >)); |
| } |
| } |