| /*------------------------------------------------------------------------- |
| * 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 "gl4cShaderImageSizeTests.hpp" |
| #include "gluContextInfo.hpp" |
| #include "glwEnums.hpp" |
| #include "tcuMatrix.hpp" |
| #include "tcuRenderTarget.hpp" |
| #include "tcuVectorUtil.hpp" |
| #include <assert.h> |
| #include <cstdarg> |
| |
| namespace gl4cts |
| { |
| using namespace glw; |
| |
| namespace |
| { |
| typedef tcu::Vec3 vec3; |
| typedef tcu::Vec4 vec4; |
| typedef tcu::IVec4 ivec4; |
| typedef tcu::UVec4 uvec4; |
| |
| class ShaderImageSizeBase : public deqp::SubcaseBase |
| { |
| virtual std::string Title() |
| { |
| return ""; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return ""; |
| } |
| |
| virtual std::string Method() |
| { |
| return ""; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return ""; |
| } |
| |
| public: |
| bool SupportedInVS(int requiredVS) |
| { |
| GLint imagesVS; |
| glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS); |
| if (imagesVS >= requiredVS) |
| return true; |
| else |
| { |
| std::ostringstream reason; |
| reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available." |
| << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| } |
| |
| bool SupportedInTCS(int requiredTCS) |
| { |
| GLint imagesTCS; |
| glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS); |
| if (imagesTCS >= requiredTCS) |
| return true; |
| else |
| { |
| std::ostringstream reason; |
| reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available." |
| << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| } |
| |
| bool SupportedInTES(int requiredTES) |
| { |
| GLint imagesTES; |
| glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES); |
| if (imagesTES >= requiredTES) |
| return true; |
| else |
| { |
| std::ostringstream reason; |
| reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available." |
| << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| } |
| |
| bool SupportedInGS(int requiredGS) |
| { |
| GLint imagesGS; |
| glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS); |
| if (imagesGS >= requiredGS) |
| return true; |
| else |
| { |
| std::ostringstream reason; |
| reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available." |
| << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| } |
| |
| bool SupportedInStage(int stage, int required) |
| { |
| switch (stage) |
| { |
| case 0: |
| return SupportedInVS(required); |
| case 1: |
| return SupportedInTCS(required); |
| case 2: |
| return SupportedInTES(required); |
| case 3: |
| return SupportedInGS(required); |
| default: |
| return true; |
| } |
| } |
| |
| bool SupportedSamples(int required) |
| { |
| int i; |
| glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i); |
| if (i >= required) |
| return true; |
| else |
| { |
| std::ostringstream reason; |
| reason << "Required " << required << " image samples but only " << i << " available." << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| } |
| |
| int getWindowWidth() |
| { |
| const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); |
| return renderTarget.getWidth(); |
| } |
| |
| int getWindowHeight() |
| { |
| const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); |
| return renderTarget.getHeight(); |
| } |
| |
| inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon) |
| { |
| if (fabs(c0[0] - c1[0]) > epsilon[0]) |
| return false; |
| if (fabs(c0[1] - c1[1]) > epsilon[1]) |
| return false; |
| if (fabs(c0[2] - c1[2]) > epsilon[2]) |
| return false; |
| if (fabs(c0[3] - c1[3]) > epsilon[3]) |
| return false; |
| return true; |
| } |
| |
| template <class T> |
| std::string ToString(T v) |
| { |
| std::ostringstream s; |
| s << "["; |
| for (int i = 0; i < 4; ++i) |
| s << v[i] << (i == 3 ? "" : ","); |
| s << "]"; |
| return s.str(); |
| } |
| |
| bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected) |
| { |
| bool status = true; |
| const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); |
| const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat(); |
| vec4 g_color_eps = 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)); |
| |
| std::vector<vec4> fb(w * h); |
| glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]); |
| |
| for (int yy = 0; yy < h; ++yy) |
| { |
| for (int xx = 0; xx < w; ++xx) |
| { |
| const int idx = yy * w + xx; |
| if (!ColorEqual(fb[idx], expected, g_color_eps)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx]) |
| << tcu::TestLog::EndMessage; |
| status = false; |
| return status; |
| } |
| } |
| } |
| return status; |
| } |
| |
| bool CheckProgram(GLuint program) |
| { |
| if (program == 0) |
| return true; |
| GLint status; |
| glGetProgramiv(program, GL_LINK_STATUS, &status); |
| |
| if (status == GL_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) |
| { |
| GLenum type; |
| glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type)); |
| switch (type) |
| { |
| case GL_VERTEX_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| case GL_TESS_CONTROL_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Tessellation Control Shader ***" |
| << tcu::TestLog::EndMessage; |
| break; |
| case GL_TESS_EVALUATION_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***" |
| << tcu::TestLog::EndMessage; |
| break; |
| case GL_GEOMETRY_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| case GL_FRAGMENT_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| case GL_COMPUTE_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| default: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| } |
| 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]); |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage; |
| } |
| glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length); |
| if (length > 0) |
| { |
| std::vector<GLchar> log(length); |
| glGetShaderInfoLog(shaders[i], length, NULL, &log[0]); |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage; |
| } |
| } |
| } |
| GLint length; |
| glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); |
| if (length > 0) |
| { |
| std::vector<GLchar> log(length); |
| glGetProgramInfoLog(program, length, NULL, &log[0]); |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage; |
| } |
| } |
| return status == GL_TRUE ? true : false; |
| } |
| }; |
| |
| template <typename T> |
| std::string ImageTypePrefix(); |
| |
| template <> |
| std::string ImageTypePrefix<vec4>() |
| { |
| return ""; |
| } |
| |
| template <> |
| std::string ImageTypePrefix<ivec4>() |
| { |
| return "i"; |
| } |
| |
| template <> |
| std::string ImageTypePrefix<uvec4>() |
| { |
| return "u"; |
| } |
| |
| template <typename T> |
| std::string ImageFormatPostfix(); |
| |
| template <> |
| std::string ImageFormatPostfix<vec4>() |
| { |
| return "f"; |
| } |
| |
| template <> |
| std::string ImageFormatPostfix<ivec4>() |
| { |
| return "i"; |
| } |
| |
| template <> |
| std::string ImageFormatPostfix<uvec4>() |
| { |
| return "ui"; |
| } |
| |
| template <typename T> |
| GLenum TexInternalFormat(); |
| |
| template <> |
| GLenum TexInternalFormat<vec4>() |
| { |
| return GL_RGBA32F; |
| } |
| |
| template <> |
| GLenum TexInternalFormat<ivec4>() |
| { |
| return GL_RGBA32I; |
| } |
| |
| template <> |
| GLenum TexInternalFormat<uvec4>() |
| { |
| return GL_RGBA32UI; |
| } |
| |
| template <typename T> |
| GLenum TexType(); |
| |
| template <> |
| GLenum TexType<vec4>() |
| { |
| return GL_FLOAT; |
| } |
| |
| template <> |
| GLenum TexType<ivec4>() |
| { |
| return GL_INT; |
| } |
| |
| template <> |
| GLenum TexType<uvec4>() |
| { |
| return GL_UNSIGNED_INT; |
| } |
| |
| template <typename T> |
| GLenum TexFormat(); |
| |
| template <> |
| GLenum TexFormat<vec4>() |
| { |
| return GL_RGBA; |
| } |
| |
| template <> |
| GLenum TexFormat<ivec4>() |
| { |
| return GL_RGBA_INTEGER; |
| } |
| |
| template <> |
| GLenum TexFormat<uvec4>() |
| { |
| return GL_RGBA_INTEGER; |
| } |
| //============================================================================= |
| // ImageSizeMachine |
| //----------------------------------------------------------------------------- |
| class ImageSizeMachine : public deqp::GLWrapper |
| { |
| GLuint m_pipeline; |
| GLuint m_program[3]; |
| GLuint m_vertex_array; |
| GLuint m_texture; |
| |
| template <typename T> |
| std::string GenShader(int stage, bool ms_and_1d, bool subroutine) |
| { |
| std::ostringstream os; |
| os << "#version 430 core"; |
| if (stage == 4) |
| { // CS |
| os << NL "#extension GL_ARB_compute_shader : require"; |
| } |
| os << NL "layout(binding = 0, rgba32i) writeonly uniform iimage2D g_result;"; |
| if (ms_and_1d == false) |
| { |
| os << NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() |
| << "image2D g_image_2d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>() << ") uniform " |
| << ImageTypePrefix<T>() << "image3D g_image_3d;" NL "layout(binding = 3, rgba32" |
| << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() |
| << "imageCube g_image_cube;" NL "layout(binding = 4, rgba32" << ImageFormatPostfix<T>() << ") uniform " |
| << ImageTypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "layout(binding = 5, rgba32" |
| << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() |
| << "image2DRect g_image_rect;" NL "layout(binding = 6, rgba32" << ImageFormatPostfix<T>() << ") uniform " |
| << ImageTypePrefix<T>() << "image2DArray g_image_2d_array;" NL "layout(binding = 7, rgba32" |
| << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() << "imageBuffer g_image_buffer;"; |
| } |
| else |
| { |
| os << NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() |
| << "image1D g_image_1d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>() << ") uniform " |
| << ImageTypePrefix<T>() << "image1DArray g_image_1d_array;" NL "layout(binding = 3, rgba32" |
| << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() |
| << "image2DMS g_image_2dms;" NL "layout(binding = 4, rgba32" << ImageFormatPostfix<T>() << ") uniform " |
| << ImageTypePrefix<T>() << "image2DMSArray g_image_2dms_array;"; |
| } |
| if (subroutine) |
| { |
| os << NL "subroutine void FuncType(int coord);" NL "subroutine uniform FuncType g_func;"; |
| } |
| if (stage == 0) |
| { // VS |
| os << NL "void main() {" NL " int coord = gl_VertexID;"; |
| } |
| else if (stage == 1) |
| { // TCS |
| os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL |
| " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL |
| " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL " int coord = gl_PrimitiveID;"; |
| } |
| else if (stage == 2) |
| { // TES |
| os << NL "layout(quads, point_mode) in;" NL "void main() {" NL " int coord = gl_PrimitiveID;"; |
| } |
| else if (stage == 3) |
| { // GS |
| os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL |
| " int coord = gl_PrimitiveIDIn;"; |
| } |
| else if (stage == 4) |
| { // CS |
| os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL " int coord = int(gl_GlobalInvocationID.x);"; |
| } |
| else if (stage == 5) |
| { // FS |
| os << NL "void main() {" NL " int coord = gl_PrimitiveID;"; |
| } |
| if (subroutine) |
| { |
| os << NL " g_func(coord);" NL "}" NL "subroutine(FuncType) void Func0(int coord) {"; |
| } |
| if (ms_and_1d == false) |
| { |
| os << NL " imageStore(g_result, ivec2(coord, 0), ivec4(imageSize(g_image_2d), 0, 0));" NL |
| " imageStore(g_result, ivec2(coord, 1), ivec4(imageSize(g_image_3d), 0));" NL |
| " imageStore(g_result, ivec2(coord, 2), ivec4(imageSize(g_image_cube), 0, 0));" NL |
| " imageStore(g_result, ivec2(coord, 3), ivec4(imageSize(g_image_cube_array), 0));" NL |
| " imageStore(g_result, ivec2(coord, 4), ivec4(imageSize(g_image_rect), 0, 0));" NL |
| " imageStore(g_result, ivec2(coord, 5), ivec4(imageSize(g_image_2d_array), 0));" NL |
| " imageStore(g_result, ivec2(coord, 6), ivec4(imageSize(g_image_buffer), 0, 0, 0));" NL "}"; |
| } |
| else |
| { |
| os << NL " imageStore(g_result, ivec2(coord, 0), ivec4(imageSize(g_image_1d), 0, 0, 0));" NL |
| " imageStore(g_result, ivec2(coord, 1), ivec4(imageSize(g_image_1d_array), 0, 0));" NL |
| " imageStore(g_result, ivec2(coord, 2), ivec4(imageSize(g_image_2dms), 0, 0));" NL |
| " imageStore(g_result, ivec2(coord, 3), ivec4(imageSize(g_image_2dms_array), 0));" NL |
| " imageStore(g_result, ivec2(coord, 4), ivec4(0));" NL |
| " imageStore(g_result, ivec2(coord, 5), ivec4(0));" NL |
| " imageStore(g_result, ivec2(coord, 6), ivec4(0));" NL "}"; |
| } |
| return os.str(); |
| } |
| |
| bool CheckProgram(GLuint program) |
| { |
| if (program == 0) |
| return true; |
| GLint status; |
| glGetProgramiv(program, GL_LINK_STATUS, &status); |
| |
| if (status == GL_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) |
| { |
| GLenum type; |
| glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type)); |
| switch (type) |
| { |
| case GL_VERTEX_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| case GL_TESS_CONTROL_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Tessellation Control Shader ***" |
| << tcu::TestLog::EndMessage; |
| break; |
| case GL_TESS_EVALUATION_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***" |
| << tcu::TestLog::EndMessage; |
| break; |
| case GL_GEOMETRY_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| case GL_FRAGMENT_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| case GL_COMPUTE_SHADER: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| default: |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage; |
| break; |
| } |
| 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]); |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage; |
| } |
| glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length); |
| if (length > 0) |
| { |
| std::vector<GLchar> log(length); |
| glGetShaderInfoLog(shaders[i], length, NULL, &log[0]); |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage; |
| } |
| } |
| } |
| GLint length; |
| glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); |
| if (length > 0) |
| { |
| std::vector<GLchar> log(length); |
| glGetProgramInfoLog(program, length, NULL, &log[0]); |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage; |
| } |
| } |
| return status == GL_TRUE ? true : false; |
| } |
| |
| public: |
| ImageSizeMachine() |
| { |
| glGenProgramPipelines(1, &m_pipeline); |
| memset(m_program, 0, sizeof(m_program)); |
| glGenVertexArrays(1, &m_vertex_array); |
| glGenTextures(1, &m_texture); |
| } |
| |
| ~ImageSizeMachine() |
| { |
| glDeleteProgramPipelines(1, &m_pipeline); |
| for (int i = 0; i < 3; ++i) |
| glDeleteProgram(m_program[i]); |
| glDeleteVertexArrays(1, &m_vertex_array); |
| glDeleteTextures(1, &m_texture); |
| } |
| |
| template <typename T> |
| long Run(int stage, bool ms_and_1d, ivec4 expected_result[7], bool subroutine = false) |
| { |
| if (stage == 0) |
| { // VS |
| std::string vs = GenShader<T>(stage, ms_and_1d, subroutine); |
| const char* const glsl_vs = vs.c_str(); |
| m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); |
| glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); |
| } |
| else if (stage == 1) |
| { // TCS |
| const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL |
| "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}"; |
| const char* const glsl_tes = "#version 430 core" NL "layout(quads, point_mode) in;" NL "void main() {}"; |
| std::string tcs = GenShader<T>(stage, ms_and_1d, subroutine); |
| const char* const glsl_tcs = tcs.c_str(); |
| m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); |
| m_program[1] = glCreateShaderProgramv(GL_TESS_CONTROL_SHADER, 1, &glsl_tcs); |
| m_program[2] = glCreateShaderProgramv(GL_TESS_EVALUATION_SHADER, 1, &glsl_tes); |
| glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); |
| glUseProgramStages(m_pipeline, GL_TESS_CONTROL_SHADER_BIT, m_program[1]); |
| glUseProgramStages(m_pipeline, GL_TESS_EVALUATION_SHADER_BIT, m_program[2]); |
| } |
| else if (stage == 2) |
| { // TES |
| const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL |
| "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}"; |
| std::string tes = GenShader<T>(stage, ms_and_1d, subroutine); |
| const char* const glsl_tes = tes.c_str(); |
| m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); |
| m_program[1] = glCreateShaderProgramv(GL_TESS_EVALUATION_SHADER, 1, &glsl_tes); |
| glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); |
| glUseProgramStages(m_pipeline, GL_TESS_EVALUATION_SHADER_BIT, m_program[1]); |
| } |
| else if (stage == 3) |
| { // GS |
| const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL |
| "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}"; |
| std::string gs = GenShader<T>(stage, ms_and_1d, subroutine); |
| const char* const glsl_gs = gs.c_str(); |
| m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); |
| m_program[1] = glCreateShaderProgramv(GL_GEOMETRY_SHADER, 1, &glsl_gs); |
| glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); |
| glUseProgramStages(m_pipeline, GL_GEOMETRY_SHADER_BIT, m_program[1]); |
| } |
| else if (stage == 4) |
| { // CS |
| std::string cs = GenShader<T>(stage, ms_and_1d, subroutine); |
| const char* const glsl_cs = cs.c_str(); |
| m_program[0] = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs); |
| glUseProgramStages(m_pipeline, GL_COMPUTE_SHADER_BIT, m_program[0]); |
| } |
| else if (stage == 5) |
| { // FS |
| const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL |
| "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}"; |
| std::string fs = GenShader<T>(stage, ms_and_1d, subroutine); |
| const char* const glsl_fs = fs.c_str(); |
| m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); |
| m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs); |
| glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); |
| glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]); |
| } |
| for (int i = 0; i < 3; ++i) |
| { |
| if (!CheckProgram(m_program[i])) |
| return ERROR; |
| } |
| |
| glBindTexture(GL_TEXTURE_2D, m_texture); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| { |
| ivec4 data[7]; |
| for (int i = 0; i < 7; ++i) |
| data[i] = ivec4(100000); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 7, 0, GL_RGBA_INTEGER, GL_INT, &data[0]); |
| } |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32I); |
| glBindProgramPipeline(m_pipeline); |
| glBindVertexArray(m_vertex_array); |
| if (stage != 5) |
| { |
| glEnable(GL_RASTERIZER_DISCARD); |
| } |
| if (stage == 1 || stage == 2) |
| { // TCS or TES |
| glPatchParameteri(GL_PATCH_VERTICES, 1); |
| glDrawArrays(GL_PATCHES, 0, 1); |
| glPatchParameteri(GL_PATCH_VERTICES, 3); |
| } |
| else if (stage == 4) |
| { // CS |
| glDispatchCompute(1, 1, 1); |
| } |
| else |
| { |
| glDrawArrays(GL_POINTS, 0, 1); |
| } |
| glDisable(GL_RASTERIZER_DISCARD); |
| |
| glBindTexture(GL_TEXTURE_2D, m_texture); |
| glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); |
| { |
| ivec4 data[7]; |
| glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA_INTEGER, GL_INT, &data[0]); |
| for (int i = 0; i < 7; ++i) |
| { |
| if (data[i] != expected_result[i]) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Returned value is: (" << data[i][0] << " " << data[i][1] << " " |
| << data[i][2] << " " << data[i][3] << "). Expected value is: (" << expected_result[i][0] << " " |
| << expected_result[i][1] << " " << expected_result[i][2] << " " << expected_result[i][3] |
| << "). Image unit is: " << (i + 1) << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| } |
| } |
| return NO_ERROR; |
| } |
| }; |
| //============================================================================= |
| // 1.1.x.y BasicNonMS |
| //----------------------------------------------------------------------------- |
| |
| template <typename T, int STAGE> |
| class BasicNonMS : public ShaderImageSizeBase |
| { |
| GLuint m_texture[7]; |
| GLuint m_buffer; |
| |
| virtual long Setup() |
| { |
| glGenTextures(7, m_texture); |
| glGenBuffers(1, &m_buffer); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!SupportedInStage(STAGE, 8)) |
| return NOT_SUPPORTED; |
| |
| const GLenum target[7] = { GL_TEXTURE_2D, GL_TEXTURE_3D, |
| GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY, |
| GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_ARRAY, |
| GL_TEXTURE_BUFFER }; |
| for (int i = 0; i < 7; ++i) |
| { |
| glBindTexture(target[i], m_texture[i]); |
| if (target[i] != GL_TEXTURE_BUFFER) |
| { |
| glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| } |
| |
| if (i == 0) |
| { |
| glTexStorage2D(target[i], 10, TexInternalFormat<T>(), 512, 128); |
| glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 1) |
| { |
| glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 8, 8, 4); |
| glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 2) |
| { |
| glTexStorage2D(target[i], 4, TexInternalFormat<T>(), 16, 16); |
| glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>()); |
| } |
| else if (i == 3) |
| { |
| glTexStorage3D(target[i], 2, TexInternalFormat<T>(), 4, 4, 12); |
| glBindImageTexture(4, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 4) |
| { |
| glTexStorage2D(target[i], 1, TexInternalFormat<T>(), 16, 8); |
| glBindImageTexture(5, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 5) |
| { |
| glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 127, 39, 12); |
| glBindImageTexture(6, m_texture[i], 2, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 6) |
| { |
| std::vector<GLubyte> data(256); |
| glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); |
| glBufferData(GL_TEXTURE_BUFFER, 256, &data[0], GL_STATIC_DRAW); |
| glTexBuffer(GL_TEXTURE_BUFFER, TexInternalFormat<T>(), m_buffer); |
| glBindImageTexture(7, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| } |
| ImageSizeMachine machine; |
| ivec4 res[7] = { ivec4(256, 64, 0, 0), ivec4(8, 8, 4, 0), ivec4(16, 16, 0, 0), ivec4(2, 2, 2, 0), |
| ivec4(16, 8, 0, 0), ivec4(31, 9, 12, 0), ivec4(16, 0, 0, 0) }; |
| return machine.Run<T>(STAGE, false, res); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteTextures(7, m_texture); |
| glDeleteBuffers(1, &m_buffer); |
| return NO_ERROR; |
| } |
| }; |
| //============================================================================= |
| // 1.2.x.y BasicMS |
| //----------------------------------------------------------------------------- |
| |
| template <typename T, int STAGE> |
| class BasicMS : public ShaderImageSizeBase |
| { |
| GLuint m_texture[4]; |
| |
| virtual long Setup() |
| { |
| glGenTextures(4, m_texture); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!SupportedInStage(STAGE, 5)) |
| return NOT_SUPPORTED; |
| if (!SupportedSamples(4)) |
| return NOT_SUPPORTED; |
| |
| const GLenum target[4] = { GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE, |
| GL_TEXTURE_2D_MULTISAMPLE_ARRAY }; |
| for (int i = 0; i < 4; ++i) |
| { |
| glBindTexture(target[i], m_texture[i]); |
| if (target[i] == GL_TEXTURE_1D || target[i] == GL_TEXTURE_1D_ARRAY) |
| { |
| glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| } |
| |
| if (i == 0) |
| { |
| glTexStorage1D(target[i], 10, TexInternalFormat<T>(), 512); |
| glBindImageTexture(1, m_texture[i], 6, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 1) |
| { |
| glTexStorage2D(target[i], 3, TexInternalFormat<T>(), 15, 7); |
| glBindImageTexture(2, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 2) |
| { |
| glTexImage2DMultisample(target[i], 4, TexInternalFormat<T>(), 17, 19, GL_FALSE); |
| glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>()); |
| } |
| else if (i == 3) |
| { |
| glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 64, 32, 5, GL_FALSE); |
| glBindImageTexture(4, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| } |
| ImageSizeMachine machine; |
| ivec4 res[7] = { ivec4(8, 0, 0, 0), ivec4(7, 7, 0, 0), ivec4(17, 19, 0, 0), ivec4(64, 32, 5, 0), ivec4(0), |
| ivec4(0), ivec4(0) }; |
| return machine.Run<T>(STAGE, true, res); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteTextures(4, m_texture); |
| return NO_ERROR; |
| } |
| }; |
| //============================================================================= |
| // 2.1 AdvancedChangeSize |
| //----------------------------------------------------------------------------- |
| class AdvancedChangeSize : public ShaderImageSizeBase |
| { |
| GLuint m_pipeline; |
| GLuint m_program[2]; |
| GLuint m_vertex_array; |
| GLuint m_texture[2]; |
| |
| virtual long Setup() |
| { |
| glGenProgramPipelines(1, &m_pipeline); |
| memset(m_program, 0, sizeof(m_program)); |
| glGenVertexArrays(1, &m_vertex_array); |
| glGenTextures(2, m_texture); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL |
| "const vec2 g_position[3] = { vec2(-1, -1), vec2(3, -1), vec2(-1, 3) };" NL |
| "void main() { gl_Position = vec4(g_position[gl_VertexID], 0, 1); }"; |
| const char* const glsl_fs = |
| "#version 430 core" NL "layout(location = 0) out vec4 g_color;" NL |
| "layout(binding = 0, rgba8) uniform image2D g_image[2];" NL "uniform ivec2 g_expected_size[2];" NL |
| "uniform int g_0 = 0, g_1 = 1;" NL "void main() {" NL " vec4 c = vec4(0, 1, 0, 1);" NL |
| " if (imageSize(g_image[g_0]).xy != g_expected_size[g_0]) c = vec4(1, 0, 0, 1);" NL |
| " if (imageSize(g_image[g_1]).yx != g_expected_size[g_1]) c = vec4(1, 0, 0, 1);" NL " g_color = c;" NL |
| "}"; |
| m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); |
| m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs); |
| for (int i = 0; i < 2; ++i) |
| if (!CheckProgram(m_program[i])) |
| return ERROR; |
| |
| glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); |
| glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]); |
| |
| glBindVertexArray(m_vertex_array); |
| glBindProgramPipeline(m_pipeline); |
| |
| int size[2] = { 32, 128 }; |
| for (int i = 0; i < 2; ++i) |
| { |
| glBindTexture(GL_TEXTURE_2D, m_texture[i]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[i], size[i], 0, GL_RGBA, GL_FLOAT, NULL); |
| glBindImageTexture(i, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); |
| } |
| |
| for (int i = 0; i < 3; ++i) |
| { |
| glProgramUniform2i(m_program[1], glGetUniformLocation(m_program[1], "g_expected_size[0]"), size[0], |
| size[0]); |
| glProgramUniform2i(m_program[1], glGetUniformLocation(m_program[1], "g_expected_size[1]"), size[1], |
| size[1]); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glDrawArrays(GL_TRIANGLES, 0, 3); |
| |
| { |
| bool status = true; |
| std::vector<vec3> fb(getWindowWidth() * getWindowHeight()); |
| glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGB, GL_FLOAT, &fb[0][0]); |
| if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) |
| status = false; |
| if (!status) |
| return ERROR; |
| } |
| |
| size[0] /= 2; |
| size[1] /= 2; |
| |
| glBindTexture(GL_TEXTURE_2D, m_texture[0]); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[0], size[0], 0, GL_RGBA, GL_FLOAT, NULL); |
| glBindTexture(GL_TEXTURE_2D, m_texture[1]); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[1], size[1], 0, GL_RGBA, GL_FLOAT, NULL); |
| } |
| return NO_ERROR; |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteProgramPipelines(1, &m_pipeline); |
| for (int i = 0; i < 2; ++i) |
| glDeleteProgram(m_program[i]); |
| glDeleteVertexArrays(1, &m_vertex_array); |
| glDeleteTextures(2, m_texture); |
| return NO_ERROR; |
| } |
| }; |
| //============================================================================= |
| // 2.2.x.y AdvancedNonMS |
| //----------------------------------------------------------------------------- |
| |
| template <typename T, int STAGE> |
| class AdvancedNonMS : public ShaderImageSizeBase |
| { |
| GLuint m_texture[7]; |
| GLuint m_buffer; |
| |
| virtual long Setup() |
| { |
| glGenTextures(7, m_texture); |
| glGenBuffers(1, &m_buffer); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!SupportedInStage(STAGE, 8)) |
| return NOT_SUPPORTED; |
| |
| const GLenum target[7] = { GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARRAY, |
| GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_ARRAY, |
| GL_TEXTURE_BUFFER }; |
| for (int i = 0; i < 7; ++i) |
| { |
| glBindTexture(target[i], m_texture[i]); |
| if (target[i] != GL_TEXTURE_BUFFER) |
| { |
| glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| } |
| |
| if (i == 0) |
| { |
| glTexImage3D(target[i], 0, TexInternalFormat<T>(), 2, 2, 7, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 1, TexInternalFormat<T>(), 1, 1, 7, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 3, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 1) |
| { |
| glTexImage3D(target[i], 0, TexInternalFormat<T>(), 4, 4, 2, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 1, TexInternalFormat<T>(), 2, 2, 1, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 2, TexInternalFormat<T>(), 1, 1, 1, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(2, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 2) |
| { |
| glTexImage3D(target[i], 0, TexInternalFormat<T>(), 2, 2, 12, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 1, TexInternalFormat<T>(), 1, 1, 12, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 1, GL_READ_WRITE, TexInternalFormat<T>()); |
| } |
| else if (i == 3) |
| { |
| glTexImage3D(target[i], 0, TexInternalFormat<T>(), 4, 4, 18, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 1, TexInternalFormat<T>(), 2, 2, 18, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 2, TexInternalFormat<T>(), 1, 1, 18, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(4, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 4) |
| { |
| glTexImage2D(target[i], 0, TexInternalFormat<T>(), 123, 11, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(5, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>()); |
| } |
| else if (i == 5) |
| { |
| glTexImage3D(target[i], 0, TexInternalFormat<T>(), 13, 7, 4, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 1, TexInternalFormat<T>(), 6, 3, 4, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 2, TexInternalFormat<T>(), 3, 1, 4, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage3D(target[i], 3, TexInternalFormat<T>(), 1, 1, 4, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(6, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 6) |
| { |
| glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); |
| glBufferData(GL_TEXTURE_BUFFER, 1024, NULL, GL_STATIC_DRAW); |
| glTexBufferRange(GL_TEXTURE_BUFFER, TexInternalFormat<T>(), m_buffer, 256, 512); |
| glBindImageTexture(7, m_texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, TexInternalFormat<T>()); |
| } |
| } |
| ImageSizeMachine machine; |
| ivec4 res[7] = { ivec4(1, 1, 0, 0), ivec4(2, 2, 1, 0), ivec4(2, 2, 0, 0), ivec4(2, 2, 3, 0), |
| ivec4(123, 11, 0, 0), ivec4(6, 3, 4, 0), ivec4(32, 0, 0, 0) }; |
| return machine.Run<T>(STAGE, false, res, true); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteTextures(7, m_texture); |
| glDeleteBuffers(1, &m_buffer); |
| return NO_ERROR; |
| } |
| }; |
| //============================================================================= |
| // 2.3.x.y AdvancedMS |
| //----------------------------------------------------------------------------- |
| template <typename T, int STAGE> |
| class AdvancedMS : public ShaderImageSizeBase |
| { |
| GLuint m_texture[4]; |
| |
| virtual long Setup() |
| { |
| glGenTextures(4, m_texture); |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!SupportedInStage(STAGE, 5)) |
| return NOT_SUPPORTED; |
| if (!SupportedSamples(4)) |
| return NOT_SUPPORTED; |
| |
| const GLenum target[4] = { GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY, |
| GL_TEXTURE_2D_MULTISAMPLE_ARRAY }; |
| for (int i = 0; i < 4; ++i) |
| { |
| glBindTexture(target[i], m_texture[i]); |
| if (target[i] == GL_TEXTURE_1D || target[i] == GL_TEXTURE_1D_ARRAY) |
| { |
| glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| } |
| |
| if (i == 0) |
| { |
| glTexImage1D(target[i], 0, TexInternalFormat<T>(), 7, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage1D(target[i], 1, TexInternalFormat<T>(), 3, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glTexImage1D(target[i], 2, TexInternalFormat<T>(), 1, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 1) |
| { |
| glTexImage2D(target[i], 0, TexInternalFormat<T>(), 7, 15, 0, TexFormat<T>(), TexType<T>(), NULL); |
| glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| else if (i == 2) |
| { |
| glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 7, 9, 3, GL_FALSE); |
| glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 1, GL_READ_WRITE, TexInternalFormat<T>()); |
| } |
| else if (i == 3) |
| { |
| glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 64, 32, 5, GL_FALSE); |
| glBindImageTexture(4, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); |
| } |
| } |
| ImageSizeMachine machine; |
| ivec4 res[7] = { ivec4(3, 0, 0, 0), ivec4(7, 15, 0, 0), ivec4(7, 9, 0, 0), ivec4(64, 32, 5, 0), |
| ivec4(0), ivec4(0), ivec4(0) }; |
| return machine.Run<T>(STAGE, true, res, true); |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteTextures(4, m_texture); |
| return NO_ERROR; |
| } |
| }; |
| //============================================================================= |
| // 4.1 NegativeCompileTime |
| //----------------------------------------------------------------------------- |
| class NegativeCompileTime : public ShaderImageSizeBase |
| { |
| virtual long Run() |
| { |
| // '#extension GL_ARB_shader_image_size : require' is missing |
| if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 g_color;" NL |
| "layout(binding = 0, rg16f) uniform image2D g_image;" NL "uniform ivec2 g_expected_size;" NL |
| "void main() {" NL " if (imageSize(g_image) == g_expected_size) g_color = vec4(0, 1, 0, 1);" NL |
| " else g_color = vec4(1, 0, 0, 1);" NL "}")) |
| return ERROR; |
| // imageSize(sampler) |
| if (!Compile("#version 430 core" NL "layout(location = 0) out vec4 g_color;" NL |
| "layout(binding = 0) uniform sampler2D g_sampler;" NL "uniform ivec2 g_expected_size;" NL |
| "void main() {" NL " if (imageSize(g_sampler) == g_expected_size) g_color = vec4(0, 1, 0, 1);" NL |
| " else g_color = vec4(1, 0, 0, 1);" NL "}")) |
| return ERROR; |
| return NO_ERROR; |
| } |
| |
| bool Compile(const std::string& source) |
| { |
| const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); |
| |
| const char* const src = source.c_str(); |
| glShaderSource(sh, 1, &src, NULL); |
| glCompileShader(sh); |
| |
| GLchar log[1024]; |
| glGetShaderInfoLog(sh, sizeof(log), NULL, log); |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n" |
| << log << tcu::TestLog::EndMessage; |
| |
| GLint status; |
| glGetShaderiv(sh, GL_COMPILE_STATUS, &status); |
| glDeleteShader(sh); |
| |
| if (status == GL_TRUE) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| return true; |
| } |
| }; |
| |
| } // anonymous namespace |
| |
| ShaderImageSizeTests::ShaderImageSizeTests(deqp::Context& context) : TestCaseGroup(context, "shader_image_size", "") |
| { |
| } |
| |
| ShaderImageSizeTests::~ShaderImageSizeTests(void) |
| { |
| } |
| |
| void ShaderImageSizeTests::init() |
| { |
| using namespace deqp; |
| addChild(new TestSubcase(m_context, "basic-nonMS-vs-float", TestSubcase::Create<BasicNonMS<vec4, 0> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-vs-int", TestSubcase::Create<BasicNonMS<ivec4, 0> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-vs-uint", TestSubcase::Create<BasicNonMS<uvec4, 0> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-tcs-float", TestSubcase::Create<BasicNonMS<vec4, 1> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-tcs-int", TestSubcase::Create<BasicNonMS<ivec4, 1> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-tcs-uint", TestSubcase::Create<BasicNonMS<uvec4, 1> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-tes-float", TestSubcase::Create<BasicNonMS<vec4, 2> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-tes-int", TestSubcase::Create<BasicNonMS<ivec4, 2> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-tes-uint", TestSubcase::Create<BasicNonMS<uvec4, 2> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-gs-float", TestSubcase::Create<BasicNonMS<vec4, 3> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-gs-int", TestSubcase::Create<BasicNonMS<ivec4, 3> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-gs-uint", TestSubcase::Create<BasicNonMS<uvec4, 3> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-fs-float", TestSubcase::Create<BasicNonMS<vec4, 5> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-fs-int", TestSubcase::Create<BasicNonMS<ivec4, 5> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-fs-uint", TestSubcase::Create<BasicNonMS<uvec4, 5> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-cs-float", TestSubcase::Create<BasicNonMS<vec4, 4> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-cs-int", TestSubcase::Create<BasicNonMS<ivec4, 4> >)); |
| addChild(new TestSubcase(m_context, "basic-nonMS-cs-uint", TestSubcase::Create<BasicNonMS<uvec4, 4> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-vs-float", TestSubcase::Create<BasicMS<vec4, 0> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-vs-int", TestSubcase::Create<BasicMS<ivec4, 0> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-vs-uint", TestSubcase::Create<BasicMS<uvec4, 0> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-tcs-float", TestSubcase::Create<BasicMS<vec4, 1> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-tcs-int", TestSubcase::Create<BasicMS<ivec4, 1> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-tcs-uint", TestSubcase::Create<BasicMS<uvec4, 1> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-tes-float", TestSubcase::Create<BasicMS<vec4, 2> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-tes-int", TestSubcase::Create<BasicMS<ivec4, 2> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-tes-uint", TestSubcase::Create<BasicMS<uvec4, 2> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-gs-float", TestSubcase::Create<BasicMS<vec4, 3> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-gs-int", TestSubcase::Create<BasicMS<ivec4, 3> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-gs-uint", TestSubcase::Create<BasicMS<uvec4, 3> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-fs-float", TestSubcase::Create<BasicMS<vec4, 5> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-fs-int", TestSubcase::Create<BasicMS<ivec4, 5> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-fs-uint", TestSubcase::Create<BasicMS<uvec4, 5> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-cs-float", TestSubcase::Create<BasicMS<vec4, 4> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-cs-int", TestSubcase::Create<BasicMS<ivec4, 4> >)); |
| addChild(new TestSubcase(m_context, "basic-ms-cs-uint", TestSubcase::Create<BasicMS<uvec4, 4> >)); |
| addChild(new TestSubcase(m_context, "advanced-changeSize", TestSubcase::Create<AdvancedChangeSize>)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-vs-float", TestSubcase::Create<AdvancedNonMS<vec4, 0> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-vs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 0> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-vs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 0> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-float", TestSubcase::Create<AdvancedNonMS<vec4, 1> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 1> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 1> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-tes-float", TestSubcase::Create<AdvancedNonMS<vec4, 2> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-tes-int", TestSubcase::Create<AdvancedNonMS<ivec4, 2> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-tes-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 2> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-gs-float", TestSubcase::Create<AdvancedNonMS<vec4, 3> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-gs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 3> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-gs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 3> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-fs-float", TestSubcase::Create<AdvancedNonMS<vec4, 5> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-fs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 5> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-fs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 5> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-cs-float", TestSubcase::Create<AdvancedNonMS<vec4, 4> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-cs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 4> >)); |
| addChild(new TestSubcase(m_context, "advanced-nonMS-cs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 4> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-vs-float", TestSubcase::Create<AdvancedMS<vec4, 0> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-vs-int", TestSubcase::Create<AdvancedMS<ivec4, 0> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-vs-uint", TestSubcase::Create<AdvancedMS<uvec4, 0> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-tcs-float", TestSubcase::Create<AdvancedMS<vec4, 1> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-tcs-int", TestSubcase::Create<AdvancedMS<ivec4, 1> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-tcs-uint", TestSubcase::Create<AdvancedMS<uvec4, 1> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-tes-float", TestSubcase::Create<AdvancedMS<vec4, 2> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-tes-int", TestSubcase::Create<AdvancedMS<ivec4, 2> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-tes-uint", TestSubcase::Create<AdvancedMS<uvec4, 2> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-gs-float", TestSubcase::Create<AdvancedMS<vec4, 3> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-gs-int", TestSubcase::Create<AdvancedMS<ivec4, 3> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-gs-uint", TestSubcase::Create<AdvancedMS<uvec4, 3> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-fs-float", TestSubcase::Create<AdvancedMS<vec4, 5> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-fs-int", TestSubcase::Create<AdvancedMS<ivec4, 5> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-fs-uint", TestSubcase::Create<AdvancedMS<uvec4, 5> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-cs-float", TestSubcase::Create<AdvancedMS<vec4, 4> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-cs-int", TestSubcase::Create<AdvancedMS<ivec4, 4> >)); |
| addChild(new TestSubcase(m_context, "advanced-ms-cs-uint", TestSubcase::Create<AdvancedMS<uvec4, 4> >)); |
| addChild(new TestSubcase(m_context, "negative-compileTime", TestSubcase::Create<NegativeCompileTime>)); |
| } |
| |
| } // namespace gl4cts |