| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2014-2018 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 glcLayoutLocationTests.cpp |
| * \brief |
| */ /*-------------------------------------------------------------------*/ |
| #include "glcLayoutLocationTests.hpp" |
| |
| #include "tcuRenderTarget.hpp" |
| #include "tcuStringTemplate.hpp" |
| #include "tcuSurface.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuTexture.hpp" |
| #include "tcuTextureUtil.hpp" |
| |
| #include "deStringUtil.hpp" |
| |
| #include "glwDefs.hpp" |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| |
| #include "gluDrawUtil.hpp" |
| #include "gluPixelTransfer.hpp" |
| #include "gluShaderProgram.hpp" |
| #include "gluTexture.hpp" |
| #include "gluTextureUtil.hpp" |
| |
| using namespace glw; |
| |
| namespace glcts |
| { |
| |
| static const GLuint WIDTH = 2; |
| static const GLuint HEIGHT = 2; |
| |
| // Helper function used to set texture parameters |
| void setTexParameters(const Functions& gl, GLenum target, bool depthTexture) |
| { |
| gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| |
| if (depthTexture) |
| { |
| gl.texParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); |
| gl.texParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LESS); |
| } |
| } |
| |
| // Helper function used to create texture data |
| template <typename DATA_TYPE> |
| std::vector<DATA_TYPE> generateData(std::size_t width, std::size_t height, std::size_t components) |
| { |
| DE_ASSERT((components == 1) || (components == 4)); |
| std::size_t size = width * height * components; |
| std::vector<DATA_TYPE> data(size, 0); |
| for (std::size_t i = 0; i < size; i += components) |
| data[i] = static_cast<DATA_TYPE>(255); |
| return data; |
| } |
| |
| // Structure used to return id of created object it had to be defined to support |
| // GL_TEXTURE_BUFFER cases which require creation of both texture and buffer |
| struct ResultData |
| { |
| deUint32 textureId; // id of created texture |
| deUint32 bufferId; // used only by GL_TEXTURE_BUFFER |
| |
| ResultData(deUint32 tId) : textureId(tId), bufferId(0) |
| { |
| } |
| |
| ResultData(deUint32 tId, deUint32 bId) : textureId(tId), bufferId(bId) |
| { |
| } |
| }; |
| |
| template <typename DATA_TYPE> |
| ResultData createTexture1D(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, |
| GLenum type) |
| { |
| std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, 1, components); |
| |
| deUint32 id; |
| gl.genTextures(1, &id); |
| gl.bindTexture(GL_TEXTURE_1D, id); |
| gl.texImage1D(GL_TEXTURE_1D, 0, internalFormat, WIDTH, 0, format, type, &data[0]); |
| setTexParameters(gl, GL_TEXTURE_1D, components == 1); |
| return id; |
| } |
| |
| template <typename DATA_TYPE> |
| ResultData createTexture2D(const Functions& gl, std::size_t components, GLenum target, GLenum internalFormat, |
| GLenum format, GLenum type) |
| { |
| std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); |
| |
| deUint32 id; |
| gl.genTextures(1, &id); |
| gl.bindTexture(target, id); |
| gl.texStorage2D(target, 1, internalFormat, WIDTH, HEIGHT); |
| gl.texSubImage2D(target, 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]); |
| setTexParameters(gl, target, components == 1); |
| return id; |
| } |
| |
| template <typename DATA_TYPE> |
| ResultData createTexture3D(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, |
| GLenum type) |
| { |
| std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); |
| |
| deUint32 id; |
| gl.genTextures(1, &id); |
| gl.bindTexture(GL_TEXTURE_3D, id); |
| gl.texStorage3D(GL_TEXTURE_3D, 1, internalFormat, WIDTH, HEIGHT, 1); |
| gl.texSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]); |
| setTexParameters(gl, GL_TEXTURE_3D, components == 1); |
| return id; |
| } |
| |
| template <typename DATA_TYPE> |
| ResultData createCubeMap(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, GLenum type) |
| { |
| std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); |
| |
| deUint32 id; |
| gl.genTextures(1, &id); |
| gl.bindTexture(GL_TEXTURE_CUBE_MAP, id); |
| GLenum faces[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, |
| GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; |
| gl.texStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalFormat, WIDTH, HEIGHT); |
| for (int i = 0; i < 6; ++i) |
| gl.texSubImage2D(faces[i], 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]); |
| setTexParameters(gl, GL_TEXTURE_CUBE_MAP, components == 1); |
| return id; |
| } |
| |
| template <typename DATA_TYPE> |
| ResultData createTexture2DArray(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, |
| GLenum type) |
| { |
| std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components); |
| |
| deUint32 id; |
| gl.genTextures(1, &id); |
| gl.bindTexture(GL_TEXTURE_2D_ARRAY, id); |
| gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalFormat, WIDTH, HEIGHT, 1); |
| gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]); |
| setTexParameters(gl, GL_TEXTURE_2D_ARRAY, components == 1); |
| return id; |
| } |
| |
| template <typename DATA_TYPE> |
| ResultData createTextureBuffer(const Functions& gl, GLenum internalFormat) |
| { |
| std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, 4); |
| |
| deUint32 bufferId; |
| gl.genBuffers(1, &bufferId); |
| gl.bindBuffer(GL_TEXTURE_BUFFER, bufferId); |
| gl.bufferData(GL_TEXTURE_BUFFER, WIDTH * HEIGHT * 4 * sizeof(DATA_TYPE), &data[0], GL_STATIC_DRAW); |
| |
| deUint32 textureId; |
| gl.genTextures(1, &textureId); |
| gl.bindTexture(GL_TEXTURE_BUFFER, textureId); |
| gl.texBuffer(GL_TEXTURE_BUFFER, internalFormat, bufferId); |
| return ResultData(textureId, bufferId); |
| } |
| |
| // create function was implemented for convinience. Specializations of this |
| // template simplify definition of test data by reducting the number of |
| // attributes which were moved to create fn implementation. This aproach |
| // also simplyfies texture creation in the test as create takes just a single |
| // parameter for all test cases. |
| template <GLenum, GLenum> |
| ResultData create(const Functions& gl) |
| { |
| (void)gl; |
| TCU_FAIL("Missing specialization implementation."); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D, GL_RGBA8>(const Functions& gl) |
| { |
| return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_2D, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_3D, GL_RGBA8>(const Functions& gl) |
| { |
| return createTexture3D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>(const Functions& gl) |
| { |
| return createCubeMap<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>(const Functions& gl) |
| { |
| return createCubeMap<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>(const Functions& gl) |
| { |
| return createTexture2D<short>(gl, 1, GL_TEXTURE_2D, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>(const Functions& gl) |
| { |
| return createTexture2DArray<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions& gl) |
| { |
| return createTexture2DArray<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D, GL_RGBA32I>(const Functions& gl) |
| { |
| return createTexture2D<int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_3D, GL_RGBA32I>(const Functions& gl) |
| { |
| return createTexture3D<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>(const Functions& gl) |
| { |
| return createCubeMap<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>(const Functions& gl) |
| { |
| return createTexture2DArray<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D, GL_RGBA32UI>(const Functions& gl) |
| { |
| return createTexture2D<unsigned int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_3D, GL_RGBA32UI>(const Functions& gl) |
| { |
| return createTexture3D<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>(const Functions& gl) |
| { |
| return createCubeMap<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>(const Functions& gl) |
| { |
| return createTexture2DArray<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_1D, GL_RGBA8>(const Functions& gl) |
| { |
| return createTexture1D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>(const Functions& gl) |
| { |
| return createTexture1D<unsigned char>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>(const Functions& gl) |
| { |
| return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_1D_ARRAY, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions& gl) |
| { |
| return createTexture2D<short>(gl, 1, GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, |
| GL_UNSIGNED_SHORT); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32F>(const Functions& gl) |
| { |
| return createTextureBuffer<float>(gl, GL_RGBA32F); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32I>(const Functions& gl) |
| { |
| return createTextureBuffer<int>(gl, GL_RGBA32I); |
| } |
| |
| template <> |
| ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32UI>(const Functions& gl) |
| { |
| return createTextureBuffer<unsigned int>(gl, GL_RGBA32UI); |
| } |
| |
| // Structure used to define all test case data |
| struct SamplerCaseData |
| { |
| typedef ResultData (*CreateFnPtr)(const Functions& gl); |
| |
| CreateFnPtr create; // pointer to function that will create texture |
| const char* name; // test case name |
| const char* opaqueType; // sampler or image |
| const char* outAssignment; // operation that determines fragment color |
| const int num_frag_image_uniforms; // the number of required fragment image uniform |
| }; |
| |
| class SpecifiedLocationCase : public deqp::TestCase |
| { |
| public: |
| SpecifiedLocationCase(deqp::Context& context, const SamplerCaseData& data); |
| virtual ~SpecifiedLocationCase(); |
| |
| tcu::TestNode::IterateResult iterate(); |
| |
| private: |
| ResultData (*m_createFn)(const Functions& gl); |
| std::map<std::string, std::string> m_specializationMap; |
| |
| bool m_isImageCase; |
| GLenum m_imageFormat; |
| std::string m_imageFormatQualifier; |
| int m_num_frag_image_uniform; |
| }; |
| |
| SpecifiedLocationCase::SpecifiedLocationCase(deqp::Context& context, const SamplerCaseData& data) |
| : deqp::TestCase(context, data.name, ""), m_createFn(data.create) |
| { |
| std::string type(data.opaqueType); |
| m_specializationMap["OPAQUE_TYPE"] = type; |
| m_specializationMap["OUT_ASSIGNMENT"] = data.outAssignment; |
| |
| m_isImageCase = (type.find("sampler") == std::string::npos); |
| if (m_isImageCase) |
| { |
| m_specializationMap["OPAQUE_TYPE_NAME"] = "image"; |
| m_specializationMap["ACCESS"] = "readonly"; |
| |
| if (type.find("iimage") != std::string::npos) |
| { |
| m_imageFormatQualifier = "rgba32i"; |
| m_imageFormat = GL_RGBA32I; |
| } |
| else if (type.find("uimage") != std::string::npos) |
| { |
| m_imageFormatQualifier = "rgba32ui"; |
| m_imageFormat = GL_RGBA32UI; |
| } |
| else |
| { |
| m_imageFormatQualifier = "rgba8"; |
| m_imageFormat = GL_RGBA8; |
| } |
| } |
| else |
| { |
| m_specializationMap["OPAQUE_TYPE_NAME"] = "sampler"; |
| m_specializationMap["ACCESS"] = ""; |
| } |
| m_num_frag_image_uniform = data.num_frag_image_uniforms; |
| } |
| |
| SpecifiedLocationCase::~SpecifiedLocationCase() |
| { |
| } |
| |
| tcu::TestNode::IterateResult SpecifiedLocationCase::iterate(void) |
| { |
| static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 }; |
| static const float positions[] = { -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0 }; |
| |
| static const char* vsTemplate = "${VERSION}\n" |
| "precision highp float;\n" |
| "layout(location=0) in highp vec2 inPosition;\n" |
| "layout(location=0) out highp vec2 coords;\n" |
| "void main(void)\n" |
| "{\n" |
| " coords = vec2(max(0.0, inPosition.x), max(0.0, inPosition.y));\n" |
| " gl_Position = vec4(inPosition, 0.0, 1.0);\n" |
| "}\n"; |
| |
| static const char* fsTemplate = |
| "${VERSION}\n" |
| "precision highp float;\n" |
| "layout(location=0) in vec2 coords;\n" |
| "layout(location=0) out vec4 fragColor;\n" |
| "layout(${OPAQUE_TYPE_QUALIFIERS}) ${ACCESS} uniform highp ${OPAQUE_TYPE} ${OPAQUE_TYPE_NAME};\n" |
| "void main(void)\n" |
| "{\n" |
| " fragColor = ${OUT_ASSIGNMENT};\n" |
| "}\n"; |
| |
| glu::RenderContext& renderContext = m_context.getRenderContext(); |
| glu::ContextType contextType = renderContext.getType(); |
| glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType); |
| const Functions& gl = renderContext.getFunctions(); |
| bool contextTypeES = glu::isContextTypeES(contextType); |
| bool contextES32 = glu::contextSupports(contextType, glu::ApiType::es(3, 2)); |
| if (contextTypeES && !contextES32 && !m_context.getContextInfo().isExtensionSupported("GL_ANDROID_extension_pack_es31a")) |
| if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < m_num_frag_image_uniform) |
| throw tcu::NotSupportedError("The number of required fragment image uniform is larger than GL_MAX_FRAGMENT_IMAGE_UNIFORMS"); |
| |
| const int expectedLocation = 2; |
| const int definedBinding = 1; |
| |
| std::ostringstream layoutSpecification; |
| layoutSpecification << "location=" << expectedLocation; |
| if (m_isImageCase) |
| { |
| if (contextTypeES) |
| layoutSpecification << ", binding=" << definedBinding; |
| layoutSpecification << ", " << m_imageFormatQualifier; |
| } |
| |
| m_specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion); |
| m_specializationMap["OPAQUE_TYPE_QUALIFIERS"] = layoutSpecification.str(); |
| |
| std::string vs = tcu::StringTemplate(vsTemplate).specialize(m_specializationMap); |
| std::string fs = tcu::StringTemplate(fsTemplate).specialize(m_specializationMap); |
| glu::ShaderProgram program(gl, glu::makeVtxFragSources(vs.c_str(), fs.c_str())); |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| if (!program.isOk()) |
| { |
| m_testCtx.getLog() << program << tcu::TestLog::Message << "Creation of program failed." |
| << tcu::TestLog::EndMessage; |
| return STOP; |
| } |
| |
| deUint32 programId = program.getProgram(); |
| int location = gl.getUniformLocation(programId, m_specializationMap["OPAQUE_TYPE_NAME"].c_str()); |
| if (location != expectedLocation) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Expected uniform to be at location " << expectedLocation |
| << ", not at " << location << "." << tcu::TestLog::EndMessage; |
| return STOP; |
| } |
| |
| gl.useProgram(programId); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); |
| |
| // Prepare texture/buffer |
| gl.activeTexture(GL_TEXTURE1); |
| ResultData resultData = (*m_createFn)(gl); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "GL object creation failed."); |
| |
| if (m_isImageCase) |
| { |
| gl.bindImageTexture(definedBinding, resultData.textureId, 0, GL_TRUE, 0, GL_READ_ONLY, m_imageFormat); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| } |
| |
| // in ES image uniforms cannot be updated |
| // through any of the glUniform* commands |
| if (!(contextTypeES && m_isImageCase)) |
| { |
| gl.uniform1i(expectedLocation, definedBinding); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| } |
| |
| // Create FBO with RBO |
| deUint32 rboId; |
| deUint32 fboId; |
| gl.genRenderbuffers(1, &rboId); |
| gl.bindRenderbuffer(GL_RENDERBUFFER, rboId); |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, WIDTH, HEIGHT); |
| gl.genFramebuffers(1, &fboId); |
| gl.bindFramebuffer(GL_FRAMEBUFFER, fboId); |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboId); |
| |
| // Render |
| gl.viewport(0, 0, WIDTH, HEIGHT); |
| const glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, positions) }; |
| glu::draw(renderContext, programId, DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays, |
| glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices)); |
| |
| // Grab surface |
| tcu::Surface resultFrame(WIDTH, HEIGHT); |
| glu::readPixels(renderContext, 0, 0, resultFrame.getAccess()); |
| |
| // Verify color of just first pixel |
| const tcu::RGBA expectedColor(255, 0, 0, 0); |
| tcu::RGBA pixel = resultFrame.getPixel(0, 0); |
| if (pixel != expectedColor) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Incorrect color was generated, expected: [" |
| << expectedColor.getRed() << ", " << expectedColor.getGreen() << ", " |
| << expectedColor.getBlue() << ", " << expectedColor.getAlpha() << "], got [" |
| << pixel.getRed() << ", " << pixel.getGreen() << ", " << pixel.getBlue() << ", " |
| << pixel.getAlpha() << "]" << tcu::TestLog::EndMessage; |
| } |
| else |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| |
| // Cleanup |
| if (resultData.bufferId) |
| gl.deleteBuffers(1, &resultData.bufferId); |
| gl.deleteFramebuffers(1, &fboId); |
| gl.deleteRenderbuffers(1, &rboId); |
| gl.deleteTextures(1, &resultData.textureId); |
| |
| return STOP; |
| } |
| |
| class NegativeLocationCase : public deqp::TestCase |
| { |
| public: |
| NegativeLocationCase(deqp::Context& context); |
| virtual ~NegativeLocationCase(); |
| |
| tcu::TestNode::IterateResult iterate(); |
| }; |
| |
| NegativeLocationCase::NegativeLocationCase(deqp::Context& context) : deqp::TestCase(context, "invalid_cases", "") |
| { |
| } |
| |
| NegativeLocationCase::~NegativeLocationCase() |
| { |
| } |
| |
| tcu::TestNode::IterateResult NegativeLocationCase::iterate() |
| { |
| glu::RenderContext& renderContext = m_context.getRenderContext(); |
| glu::ContextType contextType = renderContext.getType(); |
| glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType); |
| const Functions& gl = renderContext.getFunctions(); |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| |
| static const char* csTemplate = "${VERSION}\n" |
| "layout(location=2, binding=0) uniform atomic_uint u_atomic;\n" |
| "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" |
| "layout(binding=0) buffer Output {\n uint value;\n} sb_out;\n\n" |
| "void main (void) {\n" |
| " sb_out.value = atomicCounterIncrement(u_atomic);\n" |
| "}"; |
| |
| std::map<std::string, std::string> specializationMap; |
| specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion); |
| std::string cs = tcu::StringTemplate(csTemplate).specialize(specializationMap); |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| |
| glu::ProgramSources sourcesCompute; |
| sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(cs); |
| glu::ShaderProgram program(gl, sourcesCompute); |
| if (program.isOk()) |
| { |
| m_testCtx.getLog() << program << tcu::TestLog::Message |
| << "layout(location = N) is not allowed for atomic counters" << tcu::TestLog::EndMessage; |
| return STOP; |
| } |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| return STOP; |
| } |
| |
| LayoutLocationTests::LayoutLocationTests(Context& context) : TestCaseGroup(context, "layout_location", "") |
| { |
| } |
| |
| LayoutLocationTests::~LayoutLocationTests(void) |
| { |
| } |
| |
| void LayoutLocationTests::init(void) |
| { |
| const SamplerCaseData commonArguments[] = |
| { |
| { &create<GL_TEXTURE_2D, GL_RGBA8>, "sampler_2d", "sampler2D", "texture(sampler, coords)", 0 }, |
| { &create<GL_TEXTURE_3D, GL_RGBA8>, "sampler_3d", "sampler3D", "texture(sampler, vec3(coords, 0.0))", 0 }, |
| { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>, "sampler_cube", "samplerCube", "texture(sampler, vec3(coords, 0.0))", 0 }, |
| { &create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>, "sampler_cube_shadow", "samplerCubeShadow", "vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)", 0 }, |
| { &create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>, "sampler_2d_shadow", "sampler2DShadow", "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0 }, |
| { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>, "sampler_2d_array", "sampler2DArray", "texture(sampler, vec3(coords, 0.0))", 0 }, |
| { &create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>, "sampler_2d_array_shadow", "sampler2DArrayShadow", "vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)", 0 }, |
| { &create<GL_TEXTURE_2D, GL_RGBA32I>, "isampler_2d", "isampler2D", "vec4(texture(sampler, coords))/255.0", 0 }, |
| { &create<GL_TEXTURE_3D, GL_RGBA32I>, "isampler_3d", "isampler3D", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, |
| { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>, "isampler_cube", "isamplerCube", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, |
| { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>, "isampler_2d_array", "isampler2DArray", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, |
| { &create<GL_TEXTURE_2D, GL_RGBA32UI>, "usampler_2d", "usampler2D", "vec4(texture(sampler, coords))/255.0", 0 }, |
| { &create<GL_TEXTURE_3D, GL_RGBA32UI>, "usampler_3d", "usampler3D", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, |
| { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>, "usampler_cube", "usamplerCube", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, |
| { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>, "usampler_2d_array", "usampler2DArray", "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0 }, |
| |
| { &create<GL_TEXTURE_2D, GL_RGBA8>, "image_2d", "image2D", "imageLoad(image, ivec2(0, 0))", 1 }, |
| { &create<GL_TEXTURE_2D, GL_RGBA32I>, "iimage_2d", "iimage2D", "vec4(imageLoad(image, ivec2(0, 0)))/255.0", 1 }, |
| { &create<GL_TEXTURE_2D, GL_RGBA32UI>, "uimage_2d", "uimage2D", "vec4(imageLoad(image, ivec2(0, 0)))/255.0", 1 }, |
| { &create<GL_TEXTURE_3D, GL_RGBA8>, "image_3d", "image3D", "imageLoad(image, ivec3(0, 0, 0))", 1 }, |
| { &create<GL_TEXTURE_3D, GL_RGBA32I>, "iimage_3d", "iimage3D", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, |
| { &create<GL_TEXTURE_3D, GL_RGBA32UI>, "uimage_3d", "uimage3D", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, |
| { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>, "image_cube", "imageCube", "imageLoad(image, ivec3(0, 0, 0))", 1 }, |
| { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>, "iimage_cube", "iimageCube", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, |
| { &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>, "uimage_cube", "uimageCube", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, |
| { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>, "image_2d_array", "image2DArray", "imageLoad(image, ivec3(0, 0, 0))", 1 }, |
| { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>, "iimage_2d_array", "iimage2DArray", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, |
| { &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>, "uimage_2d_array", "uimage2DArray", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1 }, |
| }; |
| |
| // Additional array containing entries for core gl |
| const SamplerCaseData coreArguments[] = |
| { |
| { &create<GL_TEXTURE_BUFFER, GL_RGBA32F>, "sampler_buffer", "samplerBuffer", "texelFetch(sampler, 1)", 0 }, |
| { &create<GL_TEXTURE_BUFFER, GL_RGBA32I>, "isampler_buffer", "isamplerBuffer", "vec4(texelFetch(sampler, 1))/255.0", 0 }, |
| { &create<GL_TEXTURE_BUFFER, GL_RGBA32UI>, "usampler_buffer", "usamplerBuffer", "vec4(texelFetch(sampler, 1))/255.0", 0 }, |
| { &create<GL_TEXTURE_1D, GL_RGBA8>, "sampler_1d", "sampler1D", "texture(sampler, coords.x)", 0 }, |
| { &create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>, "sampler_1d_shadow", "sampler1DShadow", "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0 }, |
| { &create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>, "sampler_1d_array", "sampler1DArray", "texture(sampler, coords, 0.0)", 0 }, |
| { &create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>, "sampler_1d_array_shadow", "sampler1DArrayShadow", "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0 }, |
| }; |
| |
| for (int i = 0; i < DE_LENGTH_OF_ARRAY(commonArguments); ++i) |
| addChild(new SpecifiedLocationCase(m_context, commonArguments[i])); |
| |
| glu::RenderContext& renderContext = m_context.getRenderContext(); |
| glu::ContextType contextType = renderContext.getType(); |
| if (!glu::isContextTypeES(contextType)) |
| { |
| for (int i = 0; i < DE_LENGTH_OF_ARRAY(coreArguments); ++i) |
| addChild(new SpecifiedLocationCase(m_context, coreArguments[i])); |
| } |
| |
| addChild(new NegativeLocationCase(m_context)); |
| } |
| |
| } // glcts |